FoundationDB — распределённое хранилище «ключ — значение» с полноценными ACID-транзакциями. Оно не пытается быть универсальной SQL-базой: вместо этого даёт строгий, предсказуемый фундамент, поверх которого строят слои — документные модели, очереди, каталоги, графы и специализированные API. Такой подход ценят за то, что транзакции, отказоустойчивость и масштабирование решаются на нижнем уровне, а прикладная логика не обрастает самодельными блокировками.

Типичные задачи для такой базы — метаданные кластера, конфигурации сервисов, учётные записи, очереди заданий и счётчики. Аналитику и отчёты поверх неё не строят: для сканирования таблиц и сложных соединений лучше подходит отдельное хранилище.

Модель данных и транзакции

Ключи и значения — произвольные байтовые строки. Ключи упорядочены лексикографически, поэтому диапазонный поиск работает как в B-дереве. Декоратор транзакции повторяет её при конфликте, но только если код оформлен как идемпотентная функция. Транзакция короткая: по умолчанию действует лимит в пять секунд и 10 МБ изменённых данных, а длинные операции нужно разбивать на части.

import fdb

fdb.api_version(730)
db = fdb.open()

key = fdb.tuple.pack(("user", 42))

@fdb.transactional
def save(tr, key, value):
    tr[key] = value

save(db, key, "Анна".encode("utf-8"))
print(db[key].decode("utf-8"))

Слой tuple превращает кортеж в ключ с сохранением порядка, а слой directory даёт именованные пространства. Для горячих ключей добавляйте случайный префикс или используйте хеширование: FoundationDB любит равномерное распределение, а не последовательные идентификаторы. Клиент повторяет транзакцию при конфликте, поэтому функция не должна иметь побочных эффектов вне базы: отправка письма или запрос к внешнему API внутри блока приведут к дублям.

Чтение внутри транзакции видит собственные записи, а снимок данных остаётся согласованным. Если операция только читает, не добавляйте в неё записи: лишние конфликтные диапазоны увеличивают число повторов.

Установка и создание базы

Пакеты foundationdb-clients и foundationdb-server ставятся из официального репозитория. После установки служба foundationdb управляет процессами через fdbmonitor. Файл /etc/foundationdb/fdb.cluster содержит описание кластера, а конфигурация процессов лежит в /etc/foundationdb/foundationdb.conf.

sudo apt install foundationdb-clients foundationdb-server
sudo systemctl enable --now foundationdb
sudo fdbcli --exec "configure new single ssd"
sudo fdbcli --exec "status minimal"

Команда configure new инициализирует пустую базу и уничтожает прежние данные, поэтому её выполняют только на новом кластере. Для отказоустойчивой конфигурации из нескольких узлов используют режимы double или triple и указывают тип диска. Перед этим задайте одинаковый кластерный файл на всех машинах.

Кластер и обслуживание

В кластере есть координаторы, transaction servers, storage servers и logs. Координаторы хранят метаданные и выбирают лидера; их число должно быть нечётным. Команда status json отдаёт подробную картину, которую удобно фильтровать через jq.

sudo fdbcli --exec "status json" | jq '.cluster.processes | length'
sudo fdbcli --exec "status details"
sudo fdbcli --exec "exclude 192.0.2.21"
sudo fdbcli --exec "include 192.0.2.21"

Перед обслуживанием узел исключают из кластера, дожидаются перераспределения данных и потом выключают. Возврат делают командой include. Не выводите несколько узлов одновременно: режим double переживёт потерю одной машины, но не большинства.

Диапазоны и прикладные ключи

Чтение диапазона возвращает пары в отсортированном порядке. Внутри транзакции можно делать несколько чтений и записей — они увидят согласованный снимок. Если операция только читает, не добавляйте в неё записи: конфликтные диапазоны увеличивают число повторов.

@fdb.transactional
def list_users(tr, prefix):
    start, end = fdb.tuple.range((prefix,))
    for key, value in tr.get_range(start, end):
        print(fdb.tuple.unpack(key), value.decode("utf-8"))

list_users(db, "user")

Не храните в одном значении мегабайты: крупные объекты выносите в отдельное хранилище, а в базе держите ссылку и метаданные. Так проще соблюдать лимиты и обслуживать кластер.

Резервное копирование

Утилита fdbbackup делает непрерывную резервную копию, а fdbrestore восстанавливает её на другой кластер. Для аварийного переключения между площадками предусмотрен fdbdr. Проверяйте восстановление на тестовом кластере: наличие файлов бэкапа ещё не гарантирует успешный возврат данных.

sudo -u foundationdb fdbbackup start -z -d file:///srv/fdb-backup
sudo -u foundationdb fdbbackup status
sudo -u foundationdb fdbrestore start -r file:///srv/fdb-backup/<timestamp> --dest-cluster-file /etc/foundationdb/fdb.cluster -w
sudo -u foundationdb fdbbackup discontinue

При восстановлении из локального каталога указывают не базовый путь, а конкретный подкаталог, созданный заданием; его имя покажет fdbbackup list -b file:///srv/fdb-backup. Для восстановления на момент времени добавляют подходящую отметку, а после завершения проверяют status minimal и целостность приложения, а не только код возврата. Резервную копию удобно хранить отдельно, но путь file:// должен быть доступен процессу foundationdb для записи.

Эксплуатация и диагностика

Следите за свободным местом, задержками и синхронизацией времени. FoundationDB чувствительна к рассинхронизации часов и нехватке файловых дескрипторов. Журналы процессов лежат в /var/log/foundationdb, сводные сообщения — в journald.

sudo journalctl -u foundationdb -n 100 --no-pager
df -h /var/lib/foundationdb
sudo chronyc tracking
sudo fdbcli --exec "status minimal"

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

  • status minimal показывает доступность и режим репликации.
  • Рост data lag указывает на медленный диск или перегрузку сети.
  • Ошибки клиента при конфликте — норма; проверьте, что транзакция повторяется.
  • После замены диска убедитесь, что узел вернулся в include и данные перераспределились.

Когда выбирать FoundationDB

База хорошо подходит для систем с большим числом коротких транзакций, строгими требованиями к согласованности и собственной моделью данных. Отдельно оцените объём значений и профиль нагрузки: небольшие записи и частые операции переносятся легче, чем редкие многомегабайтные обновления. Она требует дисциплины в проектировании ключей и не заменяет аналитическое хранилище: сложные JOIN и отчёты поверх неё строят отдельно. Если нужен обычный SQL и знакомые инструменты, проще взять PostgreSQL; если нужна именно транзакционная основа для своего слоя, FoundationDB даёт предсказуемое поведение.

Итог

FoundationDB — это низкоуровневый, но надёжный фундамент для распределённых приложений. Начните с одного узла, создайте базу, проверьте status, затем добавьте репликацию и резервное копирование. Ключевые правила: короткие идемпотентные транзакции, равномерные ключи, контроль часов и регулярная проверка восстановления.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте