Как потерять меньше данных за счет более быстрого приема

Наш опыт связан с торговлей с малой задержкой. Мы одержимы производительностью и всегда хотели создать самую быструю технологию.

Но давайте сохраним интригу на минуту и ​​сначала представимся. QuestDB — это база данных временных рядов SQL с открытым исходным кодом. InfluxDB в настоящее время является лидером на рынке временных рядов, и мы подумали, что было бы справедливо, если бы мы попробовали их формат приема под названием Протокол линии потока («ILP»), чтобы сравнить производительность приема данных между QuestDB и InfluxDB. Не будет преувеличением сказать, что InfluxDB использует много ресурсов ЦП. Мы поставили перед собой цель создать приемник для ILP, который хранит данные быстрее, чем InfluxDB, и при этом эффективно использует аппаратное обеспечение.

Мы создали базу данных QuestDB на языке Java с нулевым сборщиком мусора. Надеюсь, сообщество Java будет вами гордиться! Вы можете найти наш репозиторий на GitHub. Приветствуются все ваши вопросы, пулл-реквесты и звездочки 🙂.

Почему InfluxLineProtocol?

Начиная с QuestDB 4.0.4, пользователи могут получать данные через ILP, чтобы использовать SQL для запроса данных Influx наряду с другими таблицами в реляционной базе данных, сохраняя при этом гибкость ILP.

Потеря данных через UDP

Мы проводили тестирование по протоколу UDP, таким образом, ожидая некоторого уровня потери данных. Однако мы не ожидали, что InfluxDB потеряет так много.

Мы создали отправителя, который кэширует исходящие сообщения в небольшом буфере перед их отправкой в ​​сокет UDP. Он отправляет данные как можно быстрее, чтобы в конечном итоге перегрузить потребителей и привести к потере пакетов. Чтобы протестировать различные варианты использования, мы регулировали отправителя, изменяя размер его буфера. Меньший буфер приводит к более частым сетевым вызовам и снижает скорость отправки.

Бенчмарк публикует 50 миллионов сообщений с разной скоростью. Затем мы постфактум измеряем количество записей в каждой БД, чтобы рассчитать подразумеваемую скорость захвата. Мы используем Dell XPS 15 7590, 64 ГБ ОЗУ, 6-ядерный процессор i9, SSD-накопитель на 1 ТБ. В этом эксперименте и отправитель, и экземпляр QuestDB/InfluxDB работают на одном компьютере. Публикация UDP осуществляется через петлю. ОС — Fedora 31, размер буфера UDP ОС (net.core.rmem_max) — 104_857_600.

Это сводится к скорости проглатывания

Производительность базы данных является узким местом, которое приводит к потере пакетов. Сообщениям отказано во входе, а уровень потерь напрямую зависит от скорости базовой базы данных.

Отправив 50 млн сообщений с разной скоростью, мы получим следующий результат. Скорость захвата InfluxDB быстро падает ниже 50%, в конечном итоге приближаясь к однозначным показателям.

Результаты скорости загрузки QuestDB получены с помощью ILP. Наша скорость приема значительно выше при использовании вместо этого наших собственных форматов ввода.

Почему скорость отправителя для InfluxDB ниже, чем для QuestDB?

В этом тесте мы запускаем отправителя и базу данных на одном компьютере, и оказывается, что InfluxDB замедляет работу нашего отправителя UDP, потребляя ресурсы ЦП. Вот что происходит с вашими процессорами при использовании InfluxDB:

При использовании InfluxDB загружает весь ЦП. Как следствие, это замедляет работу любой другой программы на том же компьютере.

Секретный соус QuestDB

Мы максимально используем каждый ЦП, из которого мы извлекаем максимальную производительность. В приведенном ниже примере мы сравнили скорость загрузки InfluxDB с использованием 12 ядер и QuestDB с использованием только одного ядра ЦП. Несмотря на использование одного ядра вместо 12, QuestDB по-прежнему значительно превосходит InfluxDB.

Если возникает свободная мощность ЦП, QuestDB будет выполнять несколько приемов данных параллельно, используя одновременно несколько ЦП, но с одним ключевым отличием; QuestDB использует алгоритмы кражи работы, чтобы гарантировать, что каждый последний бит мощности ЦП используется, и никогда не простаивает. Поясним, почему это так.

Современные сетевые карты имеют гораздо более высокую пропускную способность, чем один приемник. Будучи ограниченным одним приемником по своей конструкции, InfluxDB значительно недоиспользует сетевую карту, которая является ограничивающим фактором в конвейере.

И наоборот, QuestDB может открывать параллельные приемники (каждому требуется по одному ядру), полностью используя возможности сетевой карты. На следующем рисунке предполагается, что в других ядрах должны быть заполнены свободные ресурсы ЦП. В таком сценарии мы получим QuestDB, использующую 12 ядер, причем каждое из них будет значительно быстрее, чем 12 ядер InfluxDB вместе взятых!

Помимо приема, InfluxDB также загружает ЦП запросами. Текущий пользователь потребляет весь ЦП, в то время как другим пользователям приходится ждать своей очереди.

В отличие от этого, QuestDB использует каждое ядро ​​отдельно, что позволяет нескольким пользователям одновременно выполнять запросы или писать без задержки. Разрыв в производительности между QuestDB и InfluxDB значительно увеличивается по мере увеличения количества одновременных пользователей.

Начать

QuestDB поддерживает ILP через многоадресные и одноадресные сокеты UDP. Поддержка TCP последует в ближайшее время. Вам не нужно ничего менять в своем приложении. Для Telegraf вы можете настроить отправителя UDP для адреса и порта QuestDB.

Перейдите по этой ссылке, чтобы загрузить QuestDB. Вы также можете использовать наш sender для QuestDB и InfluxDB, чтобы воспроизвести эксперимент.

Вы можете использовать JOIN, изменяя структуру данных на лету и запрашивая все это в SQL.