На прошлой неделе компания LMAX, где я работаю, получила приз Java Duke's Choice Award 2011 за фреймворк Disruptor. Ранее об этой технологии писал Martin Fowler, известный многим читателям публикациями об объектном программировании.
В этой статье я хотела бы вкратце рассказать об этой технологии, а так же о конкретной проблеме, которую эта технология решает в компании LMAX.
LMAX предоставляет трейдинговую платформу по CFD и Forex, отличающуюся очень низкой латентностью и высокой пропускной способностью.
Чтобы добиться скорости исполнения более 10 тысяч операций в секунду, LMAX разработали паттерн Disruptor. Это – совершенно новый и очень нетрадиционный подход к решению задач параллельного программирования. Disruptor – это многопоточный параллельный фреймворк для обработки транзакций отличающийся высокой пропускной способностью и очень низкой латентностью. Disruptor LMAX заменяет java.util.concurrent.ArrayBlockingQueue и превосходит её по производительности вплоть до 80 раз.
Тестирование производительности показало, что с использованием queues для передачи данных между частями системы образуются задержки. Блокировка потоков и семафоры трудны для понимания и тестирования, и часто с их использованием больше времени уходит на отладку, чем на решение реальной проблемы. Так же тестирование многопоточного программирования показало, что использование множества потоков часто не только не приводит к высокой производительности, но и понижает её.
Таблица иллюстрирует затраты на увеличение 64-битного счётчика 500 миллионов раз используя разные техники на процессоре 2.4Ghz Nehalem(стырено с блога коллеги).
Давайте используем простой пример для иллюстрации. Представьте, что вы заказываете пачку конфет и оплачиваете их по кредитной карте. Простая система розничной торговли примет информацию о вашем заказе, воспользуется сервисом проверки кредитных карт чтобы проверить номер карты, а затем подтвердит ваш заказ — все в рамках одной операции. Поток, обрабатывающий Ваш заказ будет блокирован в ожидании проверки кредитной карты, но эта блокировка не будет очень долгой для пользователя, и сервер всегда сможет запустить другой поток на процессор.
В архитектуре LMAX, эта операция будет разделена на две части. Первая операция — это сбор информации о заказе, который закончится выводом события (запрос проверки кредитной карты) для компании кредитных карт. Процессор бизнес-логики затем продолжит обработку событий для других клиентов, пока не получит событие проверки кредитной карты в поток событий ввода. После обработки этого события будет осуществлено подтверждение заказа.
Disruptor – это очень высокоскоростной, низколатентный способ обмена сообщениями между потоками. Это как очередь на стероидах(на больших количествах стероидов!) и он является одной из главных инноваций биржи LMAX. Disruptor включает в себя производителя, потребителя и круговой буфер. Каждый производитель и потребитель знает порядковый номер – ячейка в буфере, которую он сейчас обрабатывает. Каждый производитель и потребитель записывает свой номер в счётчик, и может считывать другие счётчики. Таким образом, потребитель может считать счётчик производителя чтобы убедиться что ячейка, в которую он хочет записать доступна. Так же потребитель может проверить что он обрабатывает сообщение только после того, как другой потребитель закончил обработку.
Преимущество Disruptor состоит в том, что потребители могут быстро догнать остальных, если они отстали. Если преобразователь сообщения (un-marshaller) столкнулся с проблемой на ячейке 15, и понял это когда получатель на ячейке 31, он может считать данные из ячеек 16-30 в один заход и быстро догнать. Возможность считывать большие блоки помогает отстающим потребителям быстро нагнать других, таким образом снижая латентность.
Процессор бизнес-логики управляет всей бизнес-логикой c помощью однопоточной Java-программы, которая реагирует на вызовы методов и производит события вывода. Он работает полностью в оперативной памяти, без базы данных или другого постоянного хранилища.
Хотя бизнес-логика осуществляется в одном потоке, целый ряд задач следует осуществить перед вызовом бизнес-объекта. Входящее сообщение из сети нужно unmarshall в формат удобный для бизнес логики, нужно сохранить на надёжный накопитель чтобы иметь возможность восстановить данные в случае аварии.
Эти задачи решаются дисраптарами ввода и вывода. В отличие от процессора бизнес-логики, это параллельные компоненты, так как они включают в себя операции ввода-вывода, которые медленны и независимы.
Поскольку входной поток событий хранится в надёжном хранилище (это является одним из заданий входного дисраптора), всегда можно восстановить текущее состояние процессора бизнес-логики путем повторного проигрывания событий ввода – так же как в системе контроля версий, имея последовательность изменений, можно получить конечную версию документа.
Disruptor не является универсальным решением для каждой разработки, однако при правильном применении может показать заметное повышение скорости программных систем.
Часто финансовые компании не распространяются о своих технологиях. LMAX не только открыто говорит о своих разработках(см. блоги), но так же выпустил код Disruptor в Open Source.
См. так же — официальный сайт LMAX и партнёрский сайт LMAX на русском.
P.S. Добавлю, что этот фреймфорк лежит в основе трейдинговой платформы LMAX, запущенной год назад, и успешно обрабатывающей тысячи транзакций в секунду.
В этой статье я хотела бы вкратце рассказать об этой технологии, а так же о конкретной проблеме, которую эта технология решает в компании LMAX.
LMAX предоставляет трейдинговую платформу по CFD и Forex, отличающуюся очень низкой латентностью и высокой пропускной способностью.
Чтобы добиться скорости исполнения более 10 тысяч операций в секунду, LMAX разработали паттерн Disruptor. Это – совершенно новый и очень нетрадиционный подход к решению задач параллельного программирования. Disruptor – это многопоточный параллельный фреймворк для обработки транзакций отличающийся высокой пропускной способностью и очень низкой латентностью. Disruptor LMAX заменяет java.util.concurrent.ArrayBlockingQueue и превосходит её по производительности вплоть до 80 раз.
Проблема многопоточного программирования
Тестирование производительности показало, что с использованием queues для передачи данных между частями системы образуются задержки. Блокировка потоков и семафоры трудны для понимания и тестирования, и часто с их использованием больше времени уходит на отладку, чем на решение реальной проблемы. Так же тестирование многопоточного программирования показало, что использование множества потоков часто не только не приводит к высокой производительности, но и понижает её.
Таблица иллюстрирует затраты на увеличение 64-битного счётчика 500 миллионов раз используя разные техники на процессоре 2.4Ghz Nehalem(стырено с блога коллеги).
Метод |
Время (мс) |
Один поток |
300 |
Один поток с Memory Barrier |
4,700 |
Один поток с CAS |
5,700 |
Два потока с CAS |
30,000 |
Один поток с Lock |
10,000 |
Два потока с Lock |
224,000 |
Подход LMAX
Давайте используем простой пример для иллюстрации. Представьте, что вы заказываете пачку конфет и оплачиваете их по кредитной карте. Простая система розничной торговли примет информацию о вашем заказе, воспользуется сервисом проверки кредитных карт чтобы проверить номер карты, а затем подтвердит ваш заказ — все в рамках одной операции. Поток, обрабатывающий Ваш заказ будет блокирован в ожидании проверки кредитной карты, но эта блокировка не будет очень долгой для пользователя, и сервер всегда сможет запустить другой поток на процессор.
В архитектуре LMAX, эта операция будет разделена на две части. Первая операция — это сбор информации о заказе, который закончится выводом события (запрос проверки кредитной карты) для компании кредитных карт. Процессор бизнес-логики затем продолжит обработку событий для других клиентов, пока не получит событие проверки кредитной карты в поток событий ввода. После обработки этого события будет осуществлено подтверждение заказа.
Disruptor – это очень высокоскоростной, низколатентный способ обмена сообщениями между потоками. Это как очередь на стероидах(на больших количествах стероидов!) и он является одной из главных инноваций биржи LMAX. Disruptor включает в себя производителя, потребителя и круговой буфер. Каждый производитель и потребитель знает порядковый номер – ячейка в буфере, которую он сейчас обрабатывает. Каждый производитель и потребитель записывает свой номер в счётчик, и может считывать другие счётчики. Таким образом, потребитель может считать счётчик производителя чтобы убедиться что ячейка, в которую он хочет записать доступна. Так же потребитель может проверить что он обрабатывает сообщение только после того, как другой потребитель закончил обработку.
Преимущество Disruptor состоит в том, что потребители могут быстро догнать остальных, если они отстали. Если преобразователь сообщения (un-marshaller) столкнулся с проблемой на ячейке 15, и понял это когда получатель на ячейке 31, он может считать данные из ячеек 16-30 в один заход и быстро догнать. Возможность считывать большие блоки помогает отстающим потребителям быстро нагнать других, таким образом снижая латентность.
Процессор бизнес-логики управляет всей бизнес-логикой c помощью однопоточной Java-программы, которая реагирует на вызовы методов и производит события вывода. Он работает полностью в оперативной памяти, без базы данных или другого постоянного хранилища.
Хотя бизнес-логика осуществляется в одном потоке, целый ряд задач следует осуществить перед вызовом бизнес-объекта. Входящее сообщение из сети нужно unmarshall в формат удобный для бизнес логики, нужно сохранить на надёжный накопитель чтобы иметь возможность восстановить данные в случае аварии.
Эти задачи решаются дисраптарами ввода и вывода. В отличие от процессора бизнес-логики, это параллельные компоненты, так как они включают в себя операции ввода-вывода, которые медленны и независимы.
Поскольку входной поток событий хранится в надёжном хранилище (это является одним из заданий входного дисраптора), всегда можно восстановить текущее состояние процессора бизнес-логики путем повторного проигрывания событий ввода – так же как в системе контроля версий, имея последовательность изменений, можно получить конечную версию документа.
Выводы и ресурсы
Disruptor не является универсальным решением для каждой разработки, однако при правильном применении может показать заметное повышение скорости программных систем.
Часто финансовые компании не распространяются о своих технологиях. LMAX не только открыто говорит о своих разработках(см. блоги), но так же выпустил код Disruptor в Open Source.
См. так же — официальный сайт LMAX и партнёрский сайт LMAX на русском.
P.S. Добавлю, что этот фреймфорк лежит в основе трейдинговой платформы LMAX, запущенной год назад, и успешно обрабатывающей тысячи транзакций в секунду.