Проблематика
В отличие от большей части рынка системного ПО, рынок СУБД в настоящее время так же динамичен, как и десять лет назад. Аппаратная революция, переход с HDD на SSD, а затем с SSD на NVMe, развитие гиперконвергентной архитектуры и мультиоблачных технологий, — и все это в течение всего лишь одного десятилетия, — создают “дивный новый мир” для вендоров и пользователей баз данных.
Одновременно с изменениями в мире аппаратных средств происходит массовый переход на программное обеспечение с открытым исходным кодом. На замену нескольким крупным производителям проприетарных реляционных СУБД пришли сотни открытых и, на первый взгляд, бесплатных решений. Сам рынок СУБД также многократно вырос. Добавим к растущему on-premise рынку массовый переход к использованию нескольких СУБД совместно (polyglot persistence), рост облачного использования СУБД, кратный рост как объема данных, сопровождающих бизнес-процессы предприятий, так и требований к их обработке, и получим основные тренды на рынке СУБД сегодня.
Банки исторически были пионерами внедрения СУБД в свои бизнес процессы, однако, когда речь заходит об использовании NoSQL и облачных технологий, они находятся в последних рядах. Проблемы безопасности, надежности хранения данных и администрирования, присущие NoSQL технологиям, долгое время представляли преграду для использования NoSQL в банковской сфере. Банки оставались внешне консервативными, но внутри разочарованными сторонникам одной хорошо известной вертикально масштабируемой корпоративной СУБД.
Действительно, основным фокусом для вендоров NoSQL СУБД долгое время оставались масштабируемость и простота обработки больших объемов данных. Лишь позднее к этому набору добавились новые, удобные для разработчиков модели данных и доступность СУБД в облаке. Возможности, наиболее востребованные в финансовых учреждениях, такие, как ACID транзакции, внешние ключи, точная арифметика, либо поддерживались слабо, либо отсутствовали вовсе.
После десятилетия активного роста рынок баз данных NoSQL повзрослел. Основанная в 2007 году MongoDB - первый вендор NoSQL СУБД, - в 2020 году добавил поддержку транзакций. CockcroachDB, горизонтально масштабируемая база данных, совместимая с PostgreSQL, основанная в 2017 году, также декларирует транзакционную обработку данных как свой основной приоритет. Третий NoSQL игрок с поддержкой транзакций - FoundationDB, был основан в 2013 году, затем, неожиданно для всех участников рынка выкуплен Apple и лишь относительно недавно (в 2018 году) вновь стал доступен сообществу под открытой лицензией.
Сегодня с появлением более чем одной бесплатной, горизонтально масштабируемой, транзакционной базы данных пользователи, похоже, не в состоянии оценить начало новой эры на NoSQL рынке: теперь No-SQL больше не означает No-ACID, и всё больше продуктов декларируют как полноценную поддержку транзакций, так и горизонтальную масштабируемость.
Существенную роль в признании значительных технологических изменений широким рынком выполняют общепризнанные, независимые тесты и бенчмарки. В экосистему SQL СУБД существует широко используемый набор тестов, который разработал и продолжает поддерживать Transaction Performance Council. Движение NoSQL, хоть и менее организованное, также разработало инструменты для измерения как производительности (YCSB, LinkBench, sysbench), так и согласованности данных (Jepsen). К сожалению, для оценки того, насколько хорошо NoSQL СУБД справляются с классическими задачами SQL: обработкой финансовых транзакций, или, проще говоря, управлением деньгами, - общепринятых тестов нет.
Тестирование
Для того чтобы тест заслуживал доверия, ему недостаточно продемонстрировать, что критерии ACID соблюдаются в распределенной среде; в том числе при сбоях узлов и нарушении сетевой связности; что производительность системы растёт вместе с ростом размера кластера; что общая производительность лучше или аналогична производительности обычной вертикально масштабируемой СУБД, работающей на схожем оборудовании. Тест также должен охватывать различные топологии кластеров, облачные среды и продукты. А главное, необходимо чтобы полученные результаты были объяснимы как с точки зрения архитектуры каждой тестируемой СУБД, так и с точки зрения характера подаваемой нагрузки. Поскольку каждый вендор NoSQL СУБД реализует свой собственный API и язык для стандартных в мире SQL операций, логику приложения необходимо переписать под каждого вендора.
Именно так появился stroppy — тест на производительность и корректность для транзакционных NoSQL СУБД. Тест запускает стандартное финансовое приложение, которое выполняет серию банковских переводов между счетами пользователей. Ключевая идея, которая делает его столь удобным для проверки целостности данных без обращения к оракулу (не считая намеренного каламбура, oracle в мире тестирования на корректность — это сервис, который предоставляет канонический результат тестирования по запросу), заключается в том, что никакие денежные переводы, а также аппаратные, конфигурационные или сетевые сбои не могут изменить общий баланс всех счетов. Итак, тест состоит из трех основных этапов:
-
Генерация данных. На банковские счета батчами загружаются исходные остатки по счетам. Личный счет отличается от корпоративного лишь меньшим исходным остатком.Сумма всех остатков рассчитывается и отдельно сохраняется как канонический / ожидаемый результат.
-
Между счетами осуществляется серия денежных переводов. В качестве переводов использовались, к примеру, выплаты заработной платы в конце месяца по корпоративному счету или одноранговые переводы между личными счетами. Переводы выполняются параллельно и могут использовать один и тот же исходный или целевой счет. При этом, в кластерной базе данных счета списания и начисления, ожидаемо, в подавляющем числе случаев находятся на разных нодах кластера.
-
Конечные сальдо загружаются и сохраняются в регистре. Общий баланс меняться не должен.
На шаге 2 процессы начинают проверять на устойчивость: по скриптам запускаются запланированные сценарии разрывов сети, аппаратные сбои и изменения топологии кластера.
Субъект и среда
FoundationDB — это транзакционная NoSQL СУБД, поддерживаемая компанией Apple и доступная широкому кругу пользователей на условиях лицензии Apache 2.0. Ключевая особенность FoundationDB — это сервис-ориентированная гетерогенная архитектура. Несколько ключевых функций приложения, такие, как хранилище, журнал транзакций, прокси и координатор, можно разместить на разных нодах кластера. Это дает администраторам баз данных возможность конфигурировать СУБД в соответствии с профилем нагрузки (более интенсивная запись, или, например, чтение), а также гарантироватьn высокую доступность даже в небольших кластерах. FoundationDB, однако, лишена большинства расширенных функций SQL СУБД: все данные хранятся в одном глобальном пространстве, нет вторичных ключей или развитого языка запросов. Для Stroppy это вполне приемлемые ограничения, поскольку он реализует собственный прикладной слой, через который работает лишь с небольшим набором основных функций базы данных. По сути, именно это и позволяет Stroppy не зависеть от вендора.
В процессе тестирования FoundationDB мы преследовали три основные цели:
-
проверить, соответствует ли FoundationDB критериям ACID или нет;
-
проверить, не будет ли она слишком требовательна к аппаратным средствам и будет ли работать по крайней мере так же хорошо, как и вертикально-масштабируемые СУБД, конкретно PostgreSQL, на аналогичном оборудовании;
-
проверить, можно ли её масштабировать, например, увеличив в два или четыре раза количество ядер или нод кластера, по крайней мере, удвоить скорость обработки данных.
В качестве эталона из мира реляционных СУБД был выбран PostgreSQL — широко используемая база данных, которая довольно хорошо справляется с финансовыми нагрузками. Два первоначальных кластера для FoundationDB состояли всего из 3 и 5 одноядерных нод и сравнивались с экземпляром PostgreSQL на таком же числе ядер. PostgreSQL может хорошо масштабироваться до 20 или 30 ядер, поэтому предполагалось, что показатели производительности не будут слишком сильно отличаться друг от друга. Последний, “большой” тест FoundationDB выполнялся на 20 нодах с целью проверить масштабируемость.
Помимо приведенных в таблице сравнения конфигураций, в процессе тестирования мы опробовали целый ряд топологий кластеров, чтобы выяснить, зависит ли масштабируемость от размера кластера, рабочей нагрузки или конфигурации FoundationDB. В таблице приведены результаты лишь для наиболее показательных тестов. И, конечно же, параллельно с рабочей нагрузкой кластеры проверялись на устойчивость к сбоям и на сохранение производительности во время разрывов сети. Для проведения тестов была выбрана Oracle Cloud Infrastructure (OCI). Чтобы упростить развертывание и унифицировать сценарии дестабилизирующих действий, управление всеми вендорами осуществлялось с помощью стандартного, предоставляемого вендором, оператора kubernetes.
Во всех тестах скорость сети была ограничена 1 Гбит/с. Для одноядерных инстансов СУБД скорость диска была ограничена 1 Гб/с и пропорционально увеличивалась для многоядерных (в пересчете 1 Гб/с на ядро). Типом инстанса в Oracle Cloud был E3.Flex.
Для моделирования неисправностей был выбран Chaos-mesh — широко используемый инструмент инъекции ошибок используемый вместе с kubernetes.
Результаты
Результаты эталонного тестирования без пояснений выглядят недостоверно. В общей сложности мы провели более ста тестов, корректируя конфигурации баз данных, кластеров и клиентов, и в итоге отобрали наиболее репрезентативные. Мы постарались как можно точнее настроить обе СУБД, опираясь при этом на имеющийся опыт и используя официальный оператор Kubernetes.
Для настройки PostgreSQL сначала запустили пулер pg_bouncer и скорректировали такие конфигурационные параметры, как shared_buffers и max_connections, а в конце оптимизировали само приложение – например, была найдена оптимальная структура схемы БД, уровень сериализации транзакций и структура платежной транзакции.
Для FoundationDB оператор Kubernetes автоматически устанавливает конфигурацию [fdbserver], поэтому мы лишь поэкспериментировали с количеством ядер на инстанс СУБД, количеством подов и облачными параметрами. В частности, мы проверили достаточность IOPS облачного хранилища для нагрузок, создаваемых тестом.
Мы приложили все усилия для того, чтобы настроить FoundationDB или PostgreSQL настолько гранулярно и точно, насколько это возможно при отсутствии специализированных знаний по настройке. Целью, однако, было не выявление недостатков каждой СУБД или максимально оптимальный тюнинг, а проверка корректности их работы и масштабируемости. Мы отдаём себе отчёт в том, что возможно не нашли оптимальных параметров, а лишь устранили типовые ошибки конфигурирования.
Производительность PostgreSQL в большом числе запусков была ограничена издержками на репликацию. Для PostgreSQL это существенно повышает требования как пропускной способности сети, так и диска, так как реплицируется не конкретные изменения (row based logging), а изменённые страницы целиком (physical logging). При тестировании с большим числом параллельно запущенных клиентов узким местом PostgreSQL становилась подсистема транзакций, а IOPS и скорость CPU меньше влияли на производительность.
Производительность FoundationDB была в основном ограничена количеством CPU для таких ключевых ролей, как журнал транзакций и координатор. В наиболее загруженных инстансах использование CPU варьировалось на уровне 50-80% и выше. Отдельный вектор исследований – оптимальная конфигурация облака и БД. Мы полагаем, что низкая производительность FoundationDB для тестов с набором данных, превышающих доступный объём оперативным памяти, связана с увеличением числа операций ввода-вывода, в частности, - операций “паразитных” чтений с диска (например, чтении перед записью), которое, в конечном итоге, упиралось в лимит на IOPS стандартного контейнера Oracle Cloud. Вполне возможно, что при корректировке конфигураций FoundationDB и другом размещении подов Kubernetes производительность могла вырасти.
В ходе многочасовых тестов обе СУБД показали стабильную производительность и при резидентном, и при превышающем размер оперативной памяти (RAM) наборе данных.
Таблица 1: Сводные результаты ключевых тестов: FoundationDB, PostgreSQL (*)
№№ | Вендор | Число узлов | VCPU/ узел | RAM/ узел,GB | HDD/ узел, GB | Кол-во клиентов | Число счетов, млн | Число переводов, млн | Транзакций в секунду |
---|---|---|---|---|---|---|---|---|---|
1 | FDB | 3 | 1 | 8 | 100 | 16 | 10 | 100 | 2263 |
2 | FDB+chaos | 3 | 2 | 8 | 100 | 16 | 10 | 100 | 2189 |
3 | FDB | 5 | 1 | 8 | 100 | 512 | 10 | 100 | 7631 |
4 | FDB+chaos | 5 | 1 | 8 | 100 | 512 | 10 | 100 | 7528 |
5 | FDB | 5 | 1 | 16 | 100 | 512 | 100 | 100 | 5782 |
6 | FDB | 20 | 1 | 16 | 100 | 512 | 100 | 100 | 10854 |
7 | FDB | 5 | 1 | 16 | 100 | 512 | 1000 | 10 | 3369 |
8 | PG | 2 | 3 | 30 | 100 | 128 | 10 | 100 | 2059 |
9 | PG | 2 | 10 | 160 | 100 | 256 | 100 | 100 | 5915 |
(*) Как показано в четвертой колонке, основная разница между тестами заключается в топологии кластера. FoundationDB использует асинхронные операции ввода-вывода и запускает множество акторов в одном потоке, что позволяет использовать один vCPU для одного процесса. Тест № 2 показывает, что дополнительные vCPU не дают прироста в скорости обработки данных.
Зато для достижения максимальной скорости обработки данных важен конкурентный доступ: FoundationDB достигла оптимальной скорости при 512 клиентах, а рост числа клиентов в PostgreSQL снизил производительность и повысил задержку, несмотря на использование pg_bouncer.
При сравнении теста № 5 с тестом № 4 видим, что рабочая нагрузка мало зависит от памяти: при удвоении RAM на инстанс и десятикратном увеличении размера набора данных (но данные всё ещё резидентны в оперативной памяти) скорость обработки данных значительно не изменилась.
Однако при тесте на больших наборах данных производительность упала. Мы полагаем, что дело в ограничениях I/O и скорости сети до 1 Гбит/с у каждого инстанса FoundationDB в Oracle Cloud (для сравнения см. тесты №№ 7, 5).
В тестах №№ 2, 4 мы задействовали дестабилизирующие сценарии и получили стабильную производительность без ухудшений, несмотря на постоянное удаление нод и кратковременные разрывы сети.
В целом производительность обеих СУБД находится в одном диапазоне.
Таблица 2: Задержка(*)
№№ | Вендор | Тест денежных переводов | ||
---|---|---|---|---|
задержка, мс (средняя) | задержка, мс (макс) | задержка, мс 99% персентиль | ||
1 | FDB | 7 | 241 | 45 |
2 | FDB+chaos | 8 | 380 | 52 |
3 | FDB | 67 | 856 | 201 |
4 | FDB+chaos | 71 | 889 | 227 |
5 | FDB | 88 | 934 | 271 |
6 | FDB | 47 | 565 | 82 |
7 | FDB | 151 | 1267 | 588 |
8 | FDB | 62 | 4511 | 203 |
9 | FDB | 43 | 3568 | 133 |
(*) В таблице с показателями задержки приведены предельные значения в тестах № 5 – FoundationDB, и тесте № 8 – PostgreSQL
Таблица 3: Размер набора данных
вендор | Счетов, млн | Трансферов, млн | Размер данных на диске, GB |
FDB | 10 | 100 | 18 Gb |
FDB | 100 | 100 | 32 Gb |
FDB | 100 | 400 | 88 Gb |
FDB | 1000 | 10 | 127 Gb |
FDB | 100 | 1000 | 225 Gb |
PG | 10 | 100 | 71 Gb |
Размер набора данных, т. е. занимаемое им пространство, позволяет понять, почему производительность СУБД низкая или высокая, соотнеся размер на диске с размером оперативной памяти, доступной кластеру.
Тесты с разрывами сети и отказами оборудования проводились на кластере с тремя и пятью нодами. Например, в тесте отключали одну ноду в трех- или пятинодовом кластере каждые две минуты (вместо отказавшей ноды оператор Kubernetes запускает пустую ноду автоматически). В трехнодовом кластере отказывала заранее определенная нода, в пятинодовом – произвольная.
Если не учитывать 5-секундную задержку доступности СУБД после отказа пода, то по результатам тестов получаем адекватную производительность и точный остаток по счету. Во время задержки FoundationDB была занята автоматическим переключением координатора на одну из доступных нод.
Заключение и планы на будущее
За этим кратким отчетом стоят сотни часов тестирования с разными топологиями облаков, кластеров и клиентов и множеством дестабилизирующих факторов. Главный результат – отсутствие показателей, которые могли бы дискредитировать FoundationDB как продукт: у нас не получилось добиться потери транзакций как отдельными отказами нод так и разрывами сети. Мы обнаружили, что СУБД продолжает нормальную работу даже после системных сбоев или многочасовых рабочих нагрузок. Производительность небольшого кластера сравнима с кластером трехъядерной реплицированной PostgreSQL, а при четырехкратном увеличении кластер удваивает производительность стартовой топологии.
Хотя производительность кластера FoundationDB не растет линейно с увеличением числа нод, результаты можно считать удовлетворительными для сильно коррелированной рабочей нагрузки, которую представляют собой денежные переводы. Ряд конфигураций, представляющий интерес, остался за рамками тестов: более крупные кластеры, например, с сотнями или тысячами ядер, более объемные наборы данных, различные типы рабочих нагрузок и фоновой активности, такие, как расширение кластера,резервирование и восстановление данных.
Кроме того, мы не сравнивали отдельные характеристики СУБД, размер сообщества пользователей или разработчиков, схему лицензирования или качество технической поддержки от вендоров, хотя эти параметры крайне важны при выборе СУБД.
Мы считаем, что тесты показывают главное: будущее транзакционных NoSQL СУБД выглядит оптимистично. С расширением рынка все больше вендоров будут пытаться привлечь клиентов из финтех-индустрии, и в конкурентной борьбе лидерам придется совершенствовать свои продукты для задач обработки транзакций, что выгодно как финансовым организациям, так и широкому рынку.
В ближайшее время мы планируем добавить к сравнению ещё несколько вендоров. Среди горизонтально масштабируемых СУБД, поддерживающих транзакции, наиболее очевидными кандидатами являются MongoDB и CockroachDB.