23 МАЯ 2019
Автор: Алекс Ниммо
В первой части мы рассказали об образовании BitMEX.
Сегодня мы предлагаем вашему вниманию вторую часть статьи — углубленный анализ перегрузки системы и проблем, связанных с горизонтальным масштабированием. Мы рассмотрим, каких результатов мы достигли на сегодняшний день в обработке беспрецедентных объемов сделок, и подробно опишем части торгового механизма BitMEX, которые должны оставаться последовательными, части, которые можно распараллелить, и преимущества архитектуры API First, которую использует BitMEX.
В третьей части мы расскажем об оптимизации кода, которая уже была проведена, системах, которые уже распараллелены, и о причинах удаления некоторых функций. Мы также особо остановимся на стремлении BitMEX предоставлять всем пользователям справедливый и равный доступ и объясним, как оно связано с нашим отказом предлагать колокацию.
Итак, приступим.
Рост
BitMEX —уникальная для криптовалютного пространства платформа. Чтобы предлагать клиентам лучшие в отрасли функции и кредитное плечо, BitMEX используетторговый механизм, который принципиально отличается от большинства механизмов, используемых на криптовалютном и традиционном финансовых рынках. Мы можем предложить исключительно точную торговлю и маржу, но не можем похвастаться особой скоростью —по крайней мере, пока.
В 2017 году среднесуточный объем торгов BitMEX вырос в 129 раз. Этот невероятный рост продолжился и в 2018-2019 гг.
Как показывает график выше, количество ордеров в неделю также резко возросло по сравнению с 2017 г. Особый интерес вызывает тот факт, что абсолютный торговый рекорд по объему торгов в долларах США (8 млрд долларов) был установлен в июле 2018 года, хотя количество торговых ордеров в этот период сократилось! Этот рекорд был побит только на прошлой неделе, 11 мая 2019 года, когда объем торгов достиг 11 миллиардов долларов. Эти объемы торгов по-прежнему считаются рекордными для криптовалютных бирж, а бессрочный своп XBTUSD является самым торгуемым крипто-продуктом, который когда-либо был создан. На сегодняшний день его скопировали более десятка раз, причем как новые криптовалютные биржи, так и уже известные.
В мае 2018 года мы начали целенаправленную работу по оптимизации процессов отмены, внесения изменений и размещения ордеров в торговой системе. Мы изменили внутренние структуры данных, алгоритмы и контрольные проверки, чтобы настроить систему именно на ту скорость, которую может предложить kdb+. Мы хотели, чтобы наша существующая торговая система продолжала работать в привычном режиме, только намного быстрее. Мы очень гордимся тем, что благодаря этим усилиям нам удалось в 10 раз повысить производительность за очень короткое время: улучшение в 4,6 раза было получено уже через первые 30 дней, а 10-кратное — к концу августа. К середине июля благодаря повышению производительности торговой системы нам удалось устранить практически все перегрузки. Мы гордимся нашими технологическими специалистами, которые достигли этого потрясающего результата.
Ниже показан процент запросов, невыполненных в результате перегрузки системы, от общего числа запросов (размещение, изменение и отмена ордеров). Больше красного = больше перегрузок.
5 мая 2018 г.
Рынок отреагировал на увеличение производительности системы, и объемы торгов BitMEX взлетели до заоблачных высот. Мы первыми среди криптовалютных бирж достигли миллионного суточного объема торгов в биткоинах. Резервные мощности позволили нам продолжить выпускать новые инновационные продукты, например, первый в истории бессрочный своп ETHUSD в формате «кванто», который уже через 6 недель после выпуска стал самым популярным продуктом ETHUSD. В ноябре 2018 года наш объем торгов почти достиг двух миллионов биткоинов за 24 часа; в мае 2019 года суточный объем торгов достиг 11 миллиардов долларов.
На июльском графике нет ни единого красного пика, но если вы читаете эту статью, вы знаете, что это продлилось недолго. Почему проблема не была полностью устранена? Почему мы просто не продолжили работать, чтобы достичь 100-процентного отсутствия перегрузок?
Чтобы это понять, нужно узнать больше о нашей системе.
Очередь запросов
В торговой системе BitMEX запросы выполняются в порядке очередности, как в билетной кассе: вы присоединяетесь к очереди, подходит ваша очередь, вы делаете запрос.
Сколько времени нужно на покупку билета? Если очереди нет, это происходит очень быстро. Весь процесс длится ровно столько времени, сколько нужно для обслуживания вашего единственного запроса. Вот почему некоторые другие торговые системы, которые обслуживают значительно меньший трафик и объем торгов, работают быстрее, даже если их максимальная производительность ниже: в их очереди меньше запросов.
Но что происходит, если очередь очень длинная? Вам приходится ожидать обработки не только вашего запроса, но и запросов всех, кто находится впереди. В кассе могут работать самые быстрые и умелые специалисты в мире, но если образовалась очередь, всем ее участникам приходится ждать, и качество обслуживания закономерно ухудшается.
Одни запросы очень простые, поэтому выполняются очень быстро, другие — более сложные, поэтому их выполнение занимает больше времени. Если выполнения запроса можно полностью избежать (скажем, у пользователя недостаточно средств на счете для его выполнения), можно оптимизировать процесс и исключить попадание запроса в очередь, как это происходит в системе автоматической регистрации на рейс и сдачи багажа в некоторых аэропортах.
Аналогичным образом обстоит дело и с трафиком: даже когда каждый отдельный запрос выполняется очень быстро, если к одному ресурсу образуется очередь из запросов, качество обслуживания ухудшается.
Такое случается довольно часто. Amazon и Alibaba страдают от слишком большого наплыва трафика в праздничные дни. Колоссальный кризис Twitter помнят до сих пор. Проблемы с обработкой запросов периодически возникают у многих онлайн-платформ, и BitMEX—не исключение.
Перегрузка системы
Как вы, наверное, знаете, «перегрузка системы» — один из механизмов, который BitMEX используетдля решения описанной выше проблемы.Скептически качаете головой? Как перегрузка может быть решением, а не проблемой? Перегрузка —защитный механизм, более известный в отрасли как «сброс нагрузки», метод, используемый в информационных системах для предотвращения перегрузки системы путем игнорирования некоторых запросов, что позволяет не допустить сбоя системы и отказа от обслуживания любых запросов.
Мы опубликовали документ, в котором наглядно показаны правила в отношении сброса нагрузки и объяснен механизм этого процесса:
Чтобы понять, как это устроено, рассмотрим систему, в которой нет механизма сброса нагрузки. По мере увеличения спроса формируется и начинает расти очередь запросов.
И что в этом страшного? С каждым движением рынка огромное количество трейдеров спешит разместить торговые ордеры, чтобы увеличить или уменьшить свою позицию. Казалось бы, задержка должна регулироваться автоматически, сама собой: по мере снижения качества обслуживания трейдеры медленнее размещают ордеры, так как ожидают подтверждения каждого ордера, прежде чем разместить следующий. Но на самом деле происходит обратное: когда время отклика увеличивается, автоматические арбитражеры не могут быстро вмешаться, чтобы сохранить преобладающую цену, которая держится на других биржах.Другие опытные трейдеры пытаются самостоятельно учесть предполагаемую разницу в цене, что еще больше увеличивает размер очереди.
Без мер безопасности запросы в очереди могут исполняться с задержкой в несколько минут. Величина спредов в биржевой книге увеличивается, так как пользователи не могут эффективно размещать нерыночные ордеры (т. е. ордеры, цена в которых отличается от текущей). К тому времени, когда ордер исполняется после нескольких минут ожидания, хорошая рыночная цена становится ужасной. В такой среде торговать практически невозможно. Это не гипотетические умозаключения; это довольно распространенная проблема, с которой сталкиваются и другие криптовалютные биржи.
Решение BitMEX заключается в том, чтобы ограничить максимальное количество запросов в очереди для выполнения торговой системой. Прежде чем попасть в торговую систему, все запросы проходят через службу, где разделяются на запросы на чтение данных (т. е. поиск данных, например, GET/api/v1/position) и запросы на запись данных (например, размещение/изменение/отмену ордера и изменение кредитного плеча). Только запросы на запись передаются в основную систему и добавляются в очередь. Если эта очередь становится слишком длинной, запрос будет немедленно отклонен, а не добавлен в очередь. Глубина (т.е. количество запросов) очереди зависит от производительности торговой системы, что позволяет гарантировать задержку не более 3-5 секунд.
Как указано в нашей документации по сбросу нагрузки, определенные типы запросов, например, запрос об отмене ордера, добавляются в очередь независимо от ее размера, но, как и любые другие запросы, поступают в конец очереди.
Результат: трейдеры узнают о задержках в работе системы немедленно, а не после того, как ордер уже добавлен в очередь, и на его выполнение уходят десятки секунд. Система не тормозит: фактически, в периоды перегрузки механизм работает на максимальной скорости, а биржевая книга и торговые потоки обновляются очень быстро.
Торговля в периоды перегрузки системы
Некоторые трейдеры недовольны тем, что в периоды перегрузки системы торговля не прекращается. Более того, в Twitter и чатах трейдеров можно найти немало теорий заговора на эту тему — мол, дело в том, что некоторые трейдеры получают приоритетный доступ к системе. Это в корне неверно: каждый трейдер BitMEX имеет равный доступ и попадает в конец одной и той же очереди. Торговая система всегда обрабатывает запросы в очереди с максимальной возможной скоростью.
Если количество ордеров, поступающих в систему, в 5 раз превышает ее возможности, то лишь 20% ордеров будут приняты, а 80% будут отклонены. Решение о том, какие ордеры принимаются, а какие —отклоняются, зависит исключительно от наличия свободного места в очереди в момент поступления запроса. Если ваш запрос попадает в очередь сразу после завершения обработки другого запроса, в результате чего в очереди освобождается место, он будет принят. Следующий запрос, отправленный после вашего, может быть отклонен.
В периоды пиковой нагрузки BitMEX фиксирует увеличение скорости поступления ордеров в 20-30 раз по сравнению со средней! Объемы заключенных сделок превышают более 100 миллионов долларов в минуту. Если постоянно поддерживать такую скорость обработки запросов, объем торгов в час составит 6 млрд долларов, или более 144 млрд долларов в сутки! Это в 13 раз больше суточного рекорда BitMEX или любой другой криптоплатформы.
Чтобы всегда обеспечивать бесперебойную торговлю, BitMEX должна иметь большой резерв мощности для обработки запросов в периоды повышенной нагрузки. Ниже описаны некоторые проблемы, с которыми мы столкнулисьна пути к достижению этой цели.
Высокая масштабируемость и закон Амдала
Как решаются проблемы масштабирования? Существует два типа масштабирования: «вертикальное» и «горизонтальное». Вертикальное масштабирование предполагает ускорение работы существующей системы. Для этого можно купить более быстрый процессор (удачи; если речь идет о процессорах, о законе Мура можно забыть) или найти способ уменьшить нагрузку. С другой стороны, горизонтальное масштабирование —своего рода разновидность «закидывания проблемы деньгами»: установить больше серверов и распределить нагрузку между ними.
Веб-серверы — отличный пример горизонтально масштабируемой системы. В большинство систем с правильной архитектурой можно добавить новые веб-серверы, чтобы удовлетворить растущие потребности клиентов. Когда один отклик не зависит от другого, серверы могут работать параллельно, как, например, кассиры в продуктовом магазине.
Это будет огромным упрощением, но многие решают проблемы масштабируемости, именно «закидывая их деньгами». Многие системы масштабируются горизонтально. В большинстве случаев клиенты обслуживаются полностью независимо друг от друга, поэтому добавление нескольких веб-серверов может решить проблему. Резервные базы данных часто можно масштабировать по горизонтали, дублируя их данные.
Но горизонтальное масштабирование имеет свой предел, что часто выражается законом Амдала. Его можно вкратце изложить так: горизонтальная масштабируемость системы ограничена обязательным количеством последовательных операций (т.е. операций, которые должны выполняться в определенной последовательности). Для наглядности приведем пример: представьте себе простой однопоточный сервис, который вы хотите ускорить, запустив его параллельно на нескольких серверах. В результате анализа производительности вы обнаружите, что только 25% операций должны выполняться по порядку (т.е. последовательно). Остальные операции могут выполняться параллельно. Это означает, что сколько бы ядер или серверов вы не использовали, работу сервисаможно ускоритьтолько в 4 раза, так как 1/25% = 4. Обязательные последовательные операции становятся «узким местом» системы.
Количество обязательных последовательных операций — вот чем BitMEX существенно отличается от большинства веб-сервисов. Торговый механизм BitMEX использует гораздо больше обязательных последовательных операций, что серьезно ограничивает возможности распараллеливания.
Проблемы последовательных операций: ордеры и повторное маржирование
Торговая система BitMEX обрабатывает ордеры в порядке их поступления, т. е. последовательно (FIFO). Как и ваш любимый провайдер, торговый механизм обрабатывает запросы в том порядке, в котором они были получены.
Это основополагающий принцип рынка, который нельзя изменить. Ордеры должны быть зарегистрированы в биржевой книге последовательно— порядок их регистрации имеет значение. Агрессивный ордер оттягивает на себя ликвидность, которая становится недоступной для других ордеров. По этой причине сверку покупок и продаж по отдельному активу невозможно эффективно распределить, но сверку можно делегировать одному процессу по каждому активу.
На момент написания этой статьи BitMEX использует приблизительно 150 API-серверов, которые связываются напрямую с прокси-сервером перед системой. Этот прокси-сервер перенаправляет запросы на чтение данных на зеркала, данные веб-сокетов —в систему pub/sub, а запросы на запись данных —напрямую в торговую систему.
Как и следовало ожидать, обработка запросов на запись является самой дорогой частью системы и самой трудной для масштабирования. Для эффективной работы торговой системы должны выполнятьсяследующие условия:
- Все участники должны получать одинаковые рыночные данные одновременно.
- Любой участник может в любой момент отправить запрос на запись данных.
- Если такой запрос назапись данных действителен и влияет на состояние общедоступной системы, сообщение об изменении состояния общедоступной системы должно отправляться всем участникам после того, как запрос на запись данных будет принят и выполнен.
При отсутствии оптимизации такая система подвергается квадратичному масштабированию: 100 пользователей, отправляющих по 1 ордеру в минуту, генерируют 10 000 (100 * 100) пакетов рыночных данных, по одному на каждого участника. 10-кратное увеличение числа пользователей (до 1000 пользователей) приводит к 100-кратному увеличению объема рыночных данных (1000 x 1000) и т. д.
Как упоминалось в начале этой статьи, в 2017 году объем торгов BitMEX вырос в 129 раз. За это время пропорционально увеличилась наша пользовательская база. Это означает, что 31 декабря 2017 г. мы отправляли примерно в 16 641 (129 * 129) раз больше сообщений, чем 1 января 2017 г.
Согласованность данных в системе
Масштабирование торговой системы BitMEX — сложная задача. Мы— не типичная платформа для торговли спотовыми или производными финансовыми инструментами: мы работаем с клиентами на протяжении всего жизненного цикла, от регистрации и внесения депозита и торговли.
Чтобы клиенты могли безопасно пользоваться 100-кратным кредитным плечом, системы BitMEX должны работать правильно и быстро. BitMEX использует алгоритм маркировки справедливой цены, оригинальную и часто копируемую систему, в которой для маржирования используются составные индексы ценна спотовых биржах, лежащиев основе контракта, а не последняя зафиксированная цена контракта. Это значительно затрудняет манипулирование ценами BitMEX путем привлечения внешней ликвидности.
Чтобы этот алгоритм работал правильно, данные в торговой системе BitMEX должны быть согласованы. При каждом изменении цены маркировки система заново выставляет маржу для всех пользователей с открытыми позициями. При этом вся система проверяется контрольным алгоритмом. Стоимость поддержания всех открытых позиций, всех открытых ордеров и всей оставшейся маржи должна быть точно равна сумме всех депозитов. Ни единый сатоши не должен потеряться, иначе система прекратит работу! Такое пару раз случалось, когда мы только начали работать; и каждый раз из-за ошибки округления сатоши в вознаграждении или комиссии партнеров. Было искушение предусмотреть небольшой запас средств на случай ошибки, но наша команда считает, что платежеспособность системы критически важна: мы придерживаемся самых высоких возможных стандартов. Сегодня система все так же сверяет все суммы с точностью до сатоши после каждого значимого изменения состояния.
Злоумышленник, получивший доступ к базе данных BitMEX, просто не сможет изменить свой баланс: система немедленно распознает, что деньги появились из ниоткуда, выдаст сообщение о неустранимой ошибке и отключится.
Перед проверкой текущая сумма на вашем счете должна быть пересчитана с нуля; стоимость всех ваших открытых позиций и открытых ордеров пересчитывается по новой цене. Это гарантирует, что трейдеры не могут открыть позиции, которые не смогут поддерживать. Таким образом BitMEX защищает трейдеров от отрицательного баланса.
Ускорение работы этой системы —одна из наших основных целей в процессе масштабирования. Сверка занимает сравнительно мало времени и легко масштабируется — в отличие от маржирования. BitMEX всегда старалась соблюдать принцип «сначала правильность, потом—скорость», поэтому так много времени уходит на этот процесс, ведь мы прилагаем максимум усилий, чтобы все сделать правильно. Ошибки недопустимы, поэтому правильно распределенная система должна быть способна обнаруживать медленные и неисправные элементы, перераспределять нагрузку и выполнять необходимую обработку за короткое время. Это требует всестороннего методического внимания и тщательного тестирования.
Наши инженеры определили несколько ключевых областей, которые можно безопасно оптимизировать, и неустанно работают над созданием новой надежной архитектуры, которая значительно увеличит пропускную способность платформы.
Архитектура API First
BitMEX занимает уникальное положение среди криптовалютных брокеров: мы начали внедрение нашей системы с API. Архитектура BitMEX состоит из трех основных частей: торгового механизма, API и веб-интерфейса. Обратите внимание, что мы не использовали термин «внешний интерфейс». Почему?
Создавая архитектуру BitMEX, мы хотели, чтобы наш API был лучшим в своем классе. Отличный API облегчает разработчикам создание надежных инструментов. Он даже позволяет использовать альтернативную визуализацию и интерфейсы, которые мы даже не могли себе представить. В то время, когда мы начинали программировать свой API, API для торговли криптовалютами оставляли желать лучшего, мягко говоря. У многих не было даже подобия регулярности, документации или прописанных переходников, часто отсутствовали важные данные, а критические функции могли выполняться только через веб-сайт. Что еще хуже, у большинства из них даже не было каналов WebSocket, а те немногие, у которых они были, часто оставляли их закрытыми, доступными только через веб-сайт.
BitMEX все изменила и установила новый стандарт API для торговли криптовалютами. Мы придерживались продуманной политики внутреннего тестирования и использования всех разработанных программных продуктов, считая, что наш сайт должен использовать API точно так же, как любая другая программа. Это означает, что нет «внешнего» интерфейса, есть просто официальный интерфейс BitMEX. К веб-сайту BitMEX нельзя получить особый доступ, кроме как через уши разработчиков API и несколько механизмов защиты от злоупотреблений при входе/регистрации.
Это также означает, что ни один механизм доступа к системе BitMEX не работает быстрее или медленнее, чем остальные. Все пользователи вводят один и тот же путь к данным и одни и те же запросы, независимо от того, получают ли они доступ через мобильное устройство, браузер, пользовательский API-коннектор или даже через интеграцию с DTC Sierra Chart. Это гарантирует равные условия для всех.
С самого начала архитектура BitMEX имела следующие характеристики:
- наличие канала изменений WebSocket во всех таблицах, в том числе таблицах ордеров, сделок, биржевой книги, позиций, маржи, инструментови т. д., где все таблицы имеют одинаковый формат;
- API с полным комплектом документации, используемый как людьми, так и машинами посредством спецификации Swagger (теперь называется OpenAPI);
- образцы проектов на GitHub, и
- единый путь к данным для пользователей веб-сайти API.
Передача данных в реальном времени
Ничто так не свидетельствует о приверженности BitMEX архитектуре API First, как реализация функции передачи данных в режиме реального времени через наш веб-сокет. Как упоминалось выше, во всех таблицах есть обновляемые в реальном времени каналы изменений, первые в криптоиндустрии и крайне редкие сегодня. Кроме того, все таблицы имеют одинаковое форматирование, поэтому для обработки любого потока достаточно всего 30 строк кода. Вы также можете воспользоваться нашими готовыми проектами на GitHub.
Эти данные поступают из потока изменений, создаваемого самим механизмом, который фильтруется и распределяется в соответствии с подписками отдельных пользователей. Это гарантирует удобную организацию потока данных при создании интерфейсов на базе BitMEX: вы подписываетесь на интересующие вас таблицы, делаете запросы и получаете уведомления об изменениях. Обычно ответ на HTTP-запрос можно игнорировать, если это не ошибка. Это позволяет избежать распространенной проблемы дублирования данных в приложениях, где потоки WebSocket и ответы на HTTP-запросы должны читаться отдельно и объединяться, что приводит к громоздкому коду и ошибкам.
Мы считаем, что эта философия построения интерфейса приложений высшего уровня не только обеспечивает наилучшую интеграцию с пользовательской средой, но и делает сайт BitMEX и будущие мобильные приложения максимально удобными и быстрыми.
Наши каналы передачи данных в реальном времени критически важны для правильной работы платформы BitMEX, поэтому мы проводим масштабную внутреннюю реорганизацию нашей системы, которая, мы надеемся, значительно снизит задержку и улучшит пропускную способность без каких-либо внешних изменений. О запуске обновленной системы и его результатах будет объявлено в ближайшее время.
Дальнейшие шаги
Мы надеемся, что содержание этой статьи дало вам представление о проблемах, с которыми столкнуласьBitMEX при масштабировании платформы в расчете на следующий виток 100-кратного роста. Мы гордимся успехом нашей платформы и благодарны нашим пользователям, но нам нужно продолжать совершенствоваться, чтобы сохранить жизнеспособность в ближайшие годы.
Группа, работающая над торговой системой BitMEX, выпускает обновления платформы несколько раз в неделю. Эти постепенные изменения —часть непрерывной долгосрочной реструктуризации торговой платформы, а также тактического наращивания производительности торгового механизма. Нашим усилиям, успехами неудачам в этой сфере будет посвящена 3-я часть этой серии.
Наши специалисты по торговой системе регулярно повышают пропускную способность системы. Совсем недавно, 23 мая 2019 года, наша команда провела масштабное обновление инфраструктуры, которое увеличило возможности обработки новых ордеров на 70%. В ближайшие месяцы нас ожидает значительное улучшение пропускной способности торговой системы, при этом параллельно будет продолжаться масштабная реорганизация платформы.
Среднее, среднестатистическое и нестандартное (99-й процентиль) время обработки новых ордеров. Обновленный код был запущен приблизительно в 01:20 (UTC).
Работа по масштабированию нашей торговой системы идет быстрыми темпами, но мы также работаем над расширением своей команды. В BitMEX работают всемирно известные эксперты в области электронных торговых систем, масштабирования, инфраструктуры, безопасности и интернета, но у нас найдется место и для энтузиастов своего дела, которые не боятся учиться и делать грязную работу. Если эта статья вас заинтересовала, возможно, вы именно тот, кто нам нужен; ознакомиться с вакансиями можно на странице «Карьера» на нашем сайте.