Репликация в Reindexer

В Reindexer реализована асинхронная репликация и синхронная с поддержкой RAFT-like алгоритма консенсуса, совместимая с асинхронной.

Журнал упреждающей записи (WAL)

Каждый запрос на изменение данных в Reindexer записывается в журнал упреждающей записи (WAL), который хранится как часть неймспейса. Каждая запись в WAL имеет уникальный 64-битный регистрационный номер (LSN), который также содержит идентификатор сервера.

Журнал упреждающей записи — это кольцевая структура. Список перезаписывается после N обновлений (по умолчанию количество записей в WAL=4000000). По достижении количества записей N самые старые автоматически удаляются.

В WAL записываются только запросы на изменение данных (добавление, обновление, удаление, изменение структуры индексов). Операции добавления/обновления документов не хранятся как выделенные записи в WAL, но каждый документ имеет свой собственный LSN — этого достаточно, чтобы восстановить полный WAL в оперативной памяти при загрузке неймспейса с диска.

Побочным эффектом этого механизма является отсутствие точной последовательности обновлений индексов и данных. Поэтому в случае несовместимой миграции данных (например, при изменении типа индексного поля) Follower вернется к полной синхронизации.

Оверхед WAL равен 18 байтам на каждую запись об изменении данных.

WAL в Reindexer используется исключительно для механизмов репликации. Он не даёт никаких дополнительных гарантий при записи данных на диск и сам попадает в сторадж асинхронно через LevelDB/RocksDB, как и другие данные.

Настройка максимального количества записей в WAL

По умолчанию количество записей в WAL=4000000. Его можно изменить через Reindexer Face, утилиту reindexer_tool или с помощью операции upsert по HTTP или через коннектор. Этот параметр меняется в поле wal_size объекта namespaces служебного неймспейса #config:

{
  "type": "namespaces",
  "namespaces": [
    {
      "namespace": "*",
      "log_level": "none",
      "lazyload": false,
      "unload_idle_threshold": 0,
      "join_cache_mode": "off",
      "start_copy_policy_tx_size": 10000,
      "copy_policy_multiplier": 5,
      "tx_size_to_always_copy": 100000,
      "optimization_timeout_ms": 800,
      "optimization_sort_workers": 4,
      "wal_size": 4000000,
      "min_preselect_size": 1000,
      "max_preselect_size": 1000,
      "max_preselect_part": 0.1
    }
  ]
}

Просмотр WAL неймспейса

Для просмотра содержимого WAL неймспейса используется оператор SELECT со специальным условием для индекса #lsn:

SELECT * FROM test_namespace WHERE #lsn > 1000
curl --location --request POST 'http://127.0.0.1:5000/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
  "namespace": "test_namespace",
  "type": "select",
  "filters": [
    {
      "field": "#lsn",
      "cond": "GT",
      "value": 1000
    }
  ]
}'
Reindexer> SELECT * FROM test_namespace where #lsn > 1000

Для вывода всех записей WAL можно воспользоваться условием #lsn is not null. Также для ограничения выдачи возможно использование параметров LIMIT и OFFSET.

Настройка общих параметров репликации

Эти параметры являются общими, как для асинхронной, так и для синхронной репликации.

Общие параметры репликации можно задать одним из двух способов:

  1. в служебном неймспейсе #config,
  2. в файле конфигурации replication.conf.

Настройка общих параметров репликации в служебном неймспейсе #config

Общие параметры репликации задаются в служебном неймспейсе #config в поле replication:

{
  "type": "replication",
  "replication": {
    "server_id": 0,
    "cluster_id": 2
  }
}

Здесь:

  • server_id — уникальный идентификатор сервера (ноды). Должен быть задан пользователем.

  • cluster_id — номер группы (или кластера), в которой участвует нода. Должен быть одинаковым для всех нод группы (кластера).

Настройка общих параметров репликации в файле конфигурации replication.conf

Общие параметры репликации настраиваются в файле replication.conf в формате YAML. Его необходимо разместить в директории реплицируемой базы данных.

Файл replication.conf считывается при старте СУБД. Если в этот момент он существует, то его содержимое будет синхронизироваться в рантайме со служебным неймспейсом #config: то, что записано в файл, будет перенесено в неймспейс, и наоборот.

Если же файла нет в директории реплицируемой базы данных при старте сервера, будут применяться настройки репликации из неймспейса #config, а содержимое добавленного replication.conf будет игнорироваться до перезапуска. При этом, если файла нет при старте сервера, создаваться автоматически он не будет.

Содержимое файла конфигурации аналогично содержимому поля replication служебного неймспейса config. Пример файла конфигурации для настройки общих параметров репликации.

Проверка целостности данных

Существуют потенциальные риски нарушения согласованности данных между Leader-ом и Follower-ом в ходе репликации. Для их исключения Reindexer вычисляет легкий инкрементный хеш всех данных неймспейса (DataHash), который используется для быстрой проверки, что данные Follower действительно совпадают с Leader. При обнаружении расхождения данных DataHash происходит повторная полная синхронизация.