Всем привет!

Наверняка большинство инженеров, работающих с высоконагруженными системами, слышали о 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, в очередной раз, спас!

Спасибо, что дочитали до конца!

Комментарии (1)


  1. MountainGoat
    02.06.2026 12:25

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