Всем привет!
Наверняка большинство инженеров, работающих с высоконагруженными системами, слышали о Aerospike.
Для тех, кто всё ещё не знает, что это, приведу короткую цитату из документации:
The high-performance, distributed,
NoSQL database designed for real-time applications requiring low latency and high availability.
Вообще-то, Aerospike — это платный продукт, причём он стоит немалых денег. Настолько немалых, что наша небольшая компания не может его себе позволить.
Однако Aerospike распространяется как в коммерческой сборке, так и в версии Community Edition.
Community Edition, хоть и урезана по возможностям, но в старых версиях была вполне пригодна для использования в продакшене. Именно в тот период, когда лимиты Aerospike CE были щадящими, наша компания “подсела” на эту БД и успешно её использовала.
Однако годы шли, и с каждой новой версией бесплатной сборки лимиты становились всё жёстче. В итоге их урезали до такой степени, что обновляться мы больше не смогли и застряли примерно на версии 5 (актуальная сейчас — 8). В результате сейчас у нас используются очень старые версии Aerospike CE.
Какие именно лимиты имеются в виду:
-
лимит на размер кластера — 8 нод;
-
не более двух неймспейсов на кластер;
-
лимит на количество уникальных данных на хранилище в ноде (в новых версиях — всего 640 ГБ).
Всё это мешает горизонтальному масштабированию и добавляет проблем как команде эксплуатации, так и разработке. А лимит в 640 ГБ на ноду вместе с лимитом кластера в 8 нод — это как раз та причина, по которой такую БД невозможно полноценно использовать в продакшене.
Кроме того, из-за очень старых версий Aerospike, возникают проблемы с поддержкой кластера, и, что печальнее всего, со временем эти проблемы только усугубляются.
В прошлом у нас были попытки купить платный Aerospike, но оказалось, что под наши задачи они выкатывают чудовищный ценник. И еще им сложно продавать в РФ, а нам сложно притворяться, что мы не из РФ.
Таким образом, компания оказалась “заблокирована” на старом ПО, а кодовая база наших сервисов настолько завязана на Aerospike, что “съехать” на альтернативу мы сможем примерно никогда.
Ситуация, казалось бы, патовая. Но мы нашли решение.
Как мы с этим справились
Aerospike — это коммерческое ПО, но, внезапно, исходные коды community-edition опубликованы.
Причём это не классический open source, а код, распространяемый под лицензией AGPLv3.
Это даёт надежду, что нужные лимиты мы сможем ослабить или снять.
Перед тем, как нырять с головой в исходники, чётко сформулируем цели:
-
Кластер должен масштабироваться до 64 нод (для наших задач этого достаточно).
-
Кластер должен поддерживать больше двух неймспейсов (32 — с запасом).
-
Не должно быть искусственного лимита по объёму уникальных данных в хранилище.
-
Хочется изменить название сборки, чтобы на серверах сразу видеть, что это наша версия.
Теперь можно скачать исходники и попытаться найти нужные места (в примере используется версия 8.1.2.1 — актуальная на момент написания):
% git clone https://github.com/aerospike/aerospike-server.git% cd aerospike-server% git fetch --all --tags% git checkout 8.1.2.1
Размер кластера
Попробуем найти лимит по размеру кластера:
% grep -r "CLUSTER" ./* | grep 8./as/include/fabric/hb.h:#define AS_CLUSTER_SZ 8./as/include/fabric/partition_balance.h:COMPILER_ASSERT(AS_CLUSTER_SZ_MASKN >> (sizeof(sl_ix_t) * 8) == 0);./as/include/fabric/partition.h: uint8_t align_3[AS_CLUSTER_SZ == 8 ? 56 : 0];./as/src/fabric/skew_monitor.c: uint8_t buffer[AS_CLUSTER_SZ * sizeof(cf_node)];./as/src/fabric/skew_monitor.c: uint8_t buffer[AS_CLUSTER_SZ * sizeof(cf_node)];./as/src/fabric/skew_monitor.c: uint8_t buffer[AS_CLUSTER_SZ * sizeof(cf_node)];./as/src/fabric/skew_monitor.c: uint8_t buffer[AS_CLUSTER_SZ * sizeof(cf_node)];
Из результата сразу бросается в глаза директива:
#define AS_CLUSTER_SZ 8
Если посмотреть, где эта директива используется, становится понятно, что именно она определяет максимальный размер кластера.
Количество неймспейсов
Аналогично ищем лимит по количеству namespace:
% grep -r "NAMESPACE" ./* | grep 2$./as/include/base/datamodel.h:#define AS_ID_NAMESPACE_SZ 32./as/include/base/cfg.h:#define AS_NAMESPACE_SZ 2
В результате находим строку:
#define AS_NAMESPACE_SZ 2
Вчитываемся в код и убеждаемся, что это ровно то, что нам надо.
Замена названия сборки
Здесь всё просто: ищем по слову “community” и меняем упоминания в Makefile-ах на желаемое название сборки — например, unchained.
Лимит на количество уникальных данных
А вот тут действительно пришлось повозиться, чтобы найти необходимую директиву в коде.
Во-первых, директива называется не совсем очевидным образом.
И, во-вторых, декларируется она следующим образом AS_NODE_STORAGE_SZ (5L * 1024 * 1024 * 1024 * 1024 / 8).
Если посчитать это выражение, то получим те самые 640Гб, которыми лимитированы уникальные данные.
Если судить по коду, то такая декларация ничем не мотивирована. Кроме того, если выставить AS_NODE_STORAGE_SZ 0, то у нас вообще лимита не будет.
Автоматизация
Как вы видите, лимиты снимаются довольно просто. То есть изменения в кода можно внести несколькими sed-ами.
В такой ситуации форкать код и потом поддерживать его измененную версию нет никакой необходимости.
Тут достаточно запилить Doker-файл, который будет вносить изменения и собирать необходимые пакетики для установки в систему или готовый для использования docker-образ.
Собственно по этому пути мы и пошли.
С результатом можно ознакомиться здесь.
Тестирование
Во-первых, надо проверить что лимиты действительно удалось раздвинуть. Для этого надо просто поднять кластер больше чем из 8-ми нод, добавить в конфигурацию больше чем два нэймспэйса и напихать в каждую ноду больше чем 640Гб уникальных данных.
Сделано
Во-вторых, надо убедиться что производительность кластера не стала хуже. Тоже ничего сложного — находим кластер (НЕ В ПРОДЕ!!!) производительность которого известна, деплоим туда нашу сборку (версии должны совпадать) и убеждаемся, что с производительностью ничего не изменилось.
Cделано
В-третьих, надо убедиться, что наши изменения не привели к какому-нибудь странному поведению кластера (потеря данных или внезапное падение сервиса). Для этого надо куда-то деплоить нашу версию и уже смотреть. Например, задеплоить на несколько хорошо нагруженных кластеров в дев-окружении и погонять месяц — другой.
В процессе
Итоги
Aerospike Community Edition — отличный продукт, но за последние годы его бесплатная версия получила жесткие ограничители, несовместимые с нуждами продакшн-систем.
Благодаря открытости исходников под лицензией AGPLv3 мы смогли самостоятельно снять искусственные лимиты и масштабировать кластеры под свои задачи.
Вмешательство оказалось минимальным: несколько строк изменяются автоматически при сборке — без необходимости поддерживать отдельный форк.
Все основные проверки на лимиты, производительность и стабильность показали, что снятие ограничений не ведёт к “поломке” или ухудшению работы (конечно, с поправкой на то, что Aerospike не виноват, если железо под нагрузкой не вывозит).
Весь процесс автоматизирован и воспроизводим, код изменений и инструкции доступны для всех желающих.
Open Source, в очередной раз, спас!
Спасибо, что дочитали до конца!
ссылка на оригинал статьи https://habr.com/ru/articles/1042530/