Pull to refresh

Disruptor — новая парадигма многопоточного программирования

Reading time 4 min
Views 33K
На прошлой неделе компания 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(стырено с блога коллеги).
Метод
Время (мс)
Один поток
300
Один поток с Memory Barrier
4,700
Один поток с CAS
5,700
Два потока с CAS
30,000
Один поток с Lock
10,000
Два потока с Lock
224,000


Подход LMAX


Давайте используем простой пример для иллюстрации. Представьте, что вы заказываете пачку конфет и оплачиваете их по кредитной карте. Простая система розничной торговли примет информацию о вашем заказе, воспользуется сервисом проверки кредитных карт чтобы проверить номер карты, а затем подтвердит ваш заказ — все в рамках одной операции. Поток, обрабатывающий Ваш заказ будет блокирован в ожидании проверки кредитной карты, но эта блокировка не будет очень долгой для пользователя, и сервер всегда сможет запустить другой поток на процессор.

В архитектуре LMAX, эта операция будет разделена на две части. Первая операция — это сбор информации о заказе, который закончится выводом события (запрос проверки кредитной карты) для компании кредитных карт. Процессор бизнес-логики затем продолжит обработку событий для других клиентов, пока не получит событие проверки кредитной карты в поток событий ввода. После обработки этого события будет осуществлено подтверждение заказа.

Disruptor – это очень высокоскоростной, низколатентный способ обмена сообщениями между потоками. Это как очередь на стероидах(на больших количествах стероидов!) и он является одной из главных инноваций биржи LMAX. Disruptor включает в себя производителя, потребителя и круговой буфер. Каждый производитель и потребитель знает порядковый номер – ячейка в буфере, которую он сейчас обрабатывает. Каждый производитель и потребитель записывает свой номер в счётчик, и может считывать другие счётчики. Таким образом, потребитель может считать счётчик производителя чтобы убедиться что ячейка, в которую он хочет записать доступна. Так же потребитель может проверить что он обрабатывает сообщение только после того, как другой потребитель закончил обработку.

Disruptor в LMAX

Преимущество Disruptor состоит в том, что потребители могут быстро догнать остальных, если они отстали. Если преобразователь сообщения (un-marshaller) столкнулся с проблемой на ячейке 15, и понял это когда получатель на ячейке 31, он может считать данные из ячеек 16-30 в один заход и быстро догнать. Возможность считывать большие блоки помогает отстающим потребителям быстро нагнать других, таким образом снижая латентность.

Процессор бизнес-логики управляет всей бизнес-логикой c помощью однопоточной Java-программы, которая реагирует на вызовы методов и производит события вывода. Он работает полностью в оперативной памяти, без базы данных или другого постоянного хранилища.

Хотя бизнес-логика осуществляется в одном потоке, целый ряд задач следует осуществить перед вызовом бизнес-объекта. Входящее сообщение из сети нужно unmarshall в формат удобный для бизнес логики, нужно сохранить на надёжный накопитель чтобы иметь возможность восстановить данные в случае аварии.

Эти задачи решаются дисраптарами ввода и вывода. В отличие от процессора бизнес-логики, это параллельные компоненты, так как они включают в себя операции ввода-вывода, которые медленны и независимы.

image

Поскольку входной поток событий хранится в надёжном хранилище (это является одним из заданий входного дисраптора), всегда можно восстановить текущее состояние процессора бизнес-логики путем повторного проигрывания событий ввода – так же как в системе контроля версий, имея последовательность изменений, можно получить конечную версию документа.

Выводы и ресурсы


Disruptor не является универсальным решением для каждой разработки, однако при правильном применении может показать заметное повышение скорости программных систем.
Часто финансовые компании не распространяются о своих технологиях. LMAX не только открыто говорит о своих разработках(см. блоги), но так же выпустил код Disruptor в Open Source.

См. так же — официальный сайт LMAX и партнёрский сайт LMAX на русском.

P.S. Добавлю, что этот фреймфорк лежит в основе трейдинговой платформы LMAX, запущенной год назад, и успешно обрабатывающей тысячи транзакций в секунду.
Tags:
Hubs:
+19
Comments 25
Comments Comments 25

Articles