- Дата публикации
Как объединять базы данных разных команд без ETL и серверов: подход Datahike
Что появилось / что изменилось
Datahike предлагает другой способ работать с базами данных между командами:
-
База данных как значение, а не сервис.
- Вы не подключаетесь к живому серверу, а получаете неизменяемый снимок базы по
@conn. - Этот снимок привязан к конкретному ID транзакции и больше не меняется.
- Вы не подключаетесь к живому серверу, а получаете неизменяемый снимок базы по
-
Чтение напрямую из хранилища, без отдельного сервера.
- Все индексы лежат в хранилище (S3, файловая система, JDBC, IndexedDB через konserve).
- Любой процесс с доступом к этому хранилищу может читать и выполнять запросы.
-
Объединение нескольких баз в одном запросе.
- Datalog-запросы в Datahike принимают несколько входных источников.
- Одна команда может держать базу в одном бакете S3, другая — в другом, а аналитики объединяют их в одном выражении.
-
Снимки без блокировок и координации.
- Два потока, прочитавшие один и тот же снимок, всегда видят одинаковые данные.
- Параллельные чтения не блокируют друг друга и не ждут центральный транзактор.
Цифр по производительности и стоимости авторы не приводят. Делают акцент на архитектуре: неизменяемые индексы, структурное разделение чтения и записи, отказ от отдельного слоя для чтения.
Как это работает
Datahike опирается на два ключевых принципа.
1. Неизменяемая база как значение
Идею подсказал Datomic в 2012 году: отделить процесс записи от перцепции — чтения. Один процесс пишет, все остальные читают уже сформированные значения.
В Datomic индексы лежат в хранилище, но транзактор держит в памяти последние сегменты индексов. Читатель обычно должен координироваться с транзактором, чтобы получить полный актуальный снимок.
Datahike убирает этот слой. Писатель при каждой транзакции полностью сбрасывает изменения в хранилище. Хранилище всегда содержит полноценную, авторитетную версию индексов. Чтобы прочитать базу, не нужен транзактор — достаточно доступа к стору.
2. B‑деревья со структурным sharing’ом
Индексы Datahike — это персистентные B‑деревья. Каждый узел:
- неизменяемый;
- хранится как пара ключ–значение в konserve;
- может быть content‑addressed (ключ зависит от содержимого).
При новой транзакции Datahike не переписывает всё дерево. Оно создаёт новые узлы только по затронутым путям от листьев к корню и переиспользует все остальные поддеревья.
Пример из текста:
- база содержит ~1 000 000 датомов и тысячи узлов B‑дерева;
- транзакция добавляет 10 датомов;
- в результате переписывается порядка десятка узлов;
- новый корень указывает на эти новые узлы и тысячи старых.
И старое, и новое дерево — полные снимки базы, которые делят большую часть структуры. Узлы записывают один раз и больше не меняют. Это упрощает кэширование, репликацию и параллельное чтение: процессы не координируются, а просто читают одни и те же ключи из хранилища.
3. Distributed index space
Когда вы вызываете @conn, Datahike запрашивает из konserve один ключ — «голову» ветки, например :db.
Эта структура небольшая. В ней лежат:
- корневые указатели для индексов;
- метаданные схемы;
- текущий ID транзакции.
Это ленивый «дескриптор». При запросе движок по мере необходимости подтягивает узлы дерева по ключам из хранилища и складывает в локальный LRU‑кэш. Повторные запросы, попадающие в те же узлы, уже не платят за I/O.
Читатели не открывают соединение с сервером, не согласуют протокол и не дергают HTTP‑API. У них есть общий «пространство индексов» в хранилище, к которому они обращаются напрямую.
Писатель публикует новый снимок в два шага:
- записывает новые узлы дерева;
- атомарно обновляет «голову» ветки.
Кто прочитает @conn после этого, увидит новый снимок. Те, кто держат старый, продолжают с ним работать — их узлы неизменяемы и не пропадут, пока на них есть ссылки.
Что это значит для вас
Для чего это хорошо:
-
Кросс‑командная аналитика без ETL. Если одна команда держит каталог товаров в S3, а другая — остатки на складе в другом бакете, аналитики могут просто подключить обе базы в одном Datalog‑запросе. Без копирования данных, без отдельного дата‑марта.
-
Лёгкое масштабирование чтения. Чтение не упирается в центральный сервер. Любой сервис, который может прочитать хранилище, может выполнять запросы. Это подходит для воркеров, бэкендов и локальных инструментов разработчика.
-
Повторяемые запросы во времени. Снимки неизменяемы. Можно держать ссылку на «состояние базы на момент X» и уверенно воспроизводить отчёты, не боясь, что данные изменились между запуском скриптов.
-
Минимальная инфраструктура. Не нужен отдельный кластер баз, API‑шлюзы и очередь сообщений только ради объединения данных. Достаточно общего доступа к S3 или другому backend’у konserve.
Где подход слабее:
-
Высокочастотная запись. Запись каждой транзакции полностью сбрасывается в стор. Для систем с экстремальной нагрузкой на запись это может стать узким местом и потребует аккуратной настройки стораджа.
-
Безопасность и права доступа. Концепция «любой, кто может читать хранилище, может читать базу» удобна для внутренних систем, но требует аккуратного разграничения прав: на уровне S3‑бакетов, файловой системы или JDBC.
-
Клиентская сложность. Чтение распределено по множеству процессов. Нужен дисциплинированный подход к кэшам, управлению снимками и времени жизни ссылок.
Если вы строите аналитику и внутренние инструменты, работаете с Clojure и любите Datalog, Datahike выглядит логичным кандидатом. Для высоконагруженных транзакционных систем с жёсткими SLA по записи придётся серьёзно продумать архитектуру стораджа.
Место на рынке
Datahike идейно ближе всего к Datomic: тот же акцент на неизменяемых снимках и разделении записи и чтения. Главное отличие — в пути чтения.
- Datomic держит в памяти у транзактора «верхушку» индексов и координирует читателей через него.
- Datahike пишет все изменения прямиком в стор при каждой транзакции и позволяет читателям работать только со стором.
Это уменьшает инфраструктурные требования: не нужен отдельный транзактор‑как‑сервис для чтения. Но повышает требования к самому хранилищу, через konserve.
По сравнению с классическими реляционными СУБД и документ‑ориентированными хранилищами, Datahike делает ставку не на максимальную скорость единичной операции, а на архитектуру, где:
- индексы живут в общем хранилище;
- клиенты читают напрямую;
- несколько снимков базы сосуществуют без блокировок и сложной координации.
Чётких числовых сравнений с PostgreSQL, MongoDB, Datomic или облачными сервисами авторы не приводят. Акцент полностью на модели данных и подходе к разделению ответственности между писателями и читателями.