diff --git a/docs/cli.md b/docs/cli.md
deleted file mode 100644
index 542a7613115afd4082d29d0cad45863aeb2dd8b5..0000000000000000000000000000000000000000
--- a/docs/cli.md
+++ /dev/null
@@ -1,97 +0,0 @@
-# Описание встроенных команд Picodata
-
-## Общие сведения
-
-Исполняемый файл `picodata` может не только запускать инстансы, но и
-выступать в роли консольной утилиты. Данная утилита позволяет запускать
-дополнительные и служебные команды, не участвующие в кластерном
-взаимодействии.
-
-Общий формат запуска:
-
-```bash
-picodata <command> [<params>]
-```
-Ниже описанные доступные команды `picodata`.
-
-## picodata tarantool
-
-Открывает консоль c Lua-интерпретатором, в котором можно
-взаимодействовать с СУБД аналогично тому как это происходит в обычной
-консоли Tarantool. Никакая логика Picodata поверх Tarantool не
-выполняется, соответственно, кластер не инициализируется и подключение к
-кластеру не производится. Запускается консоль Tarantool, встроенного в
-Picodata (но не установленного обычного Tarantool, если такой есть в
-системе).
-
-## picodata expel
-
-Исключает инстанс из кластера. Применяется чтобы указать кластеру, что
-инстанс больше не участвует в кворуме Raft.
-
-Полный формат:
-
-```bash
-picodata expel --instance-id <instance-id> [--cluster-id <cluster-id>] [--peer <peer>]
-```
-
-Команда подключается к `peer` через протокол _netbox_ и отдаёт ему
-внутреннюю команду на исключение `instance-id` из кластера. Команда
-отправляется в raft-лог, из которого затем будет применена к таблице
-инстансов и установит значение `target_grade=Expelled` для заданного
-инстанса. Затем через какое-то время _governor_ возьмёт в обработку этот
-`target_grade`, выполнит необходимые работы по отключению инстанса и
-установит ему значение `current_grade=Expelled`. Сам инстанс после этого
-остановится, его процесс завершится. В дальнейшем кластер не будет
-ожидать от этого инстанса участия в кворуме. Исключённый из кластера
-инстанс при попытке перезапуститься будет автоматически завершаться.
-
-Параметр `cluster-id` проверяется перед добавлением команды в raft-лог.
-
-Параметр `peer` — это адрес любого инстанса кластера. Формат:
-`[host]:port`. Может совпадать с адресом исключаемого инстанса.
-
-Если исключаемый инстанс является текущим raft-лидером, то лидерство
-переходит другому инстансу.
-
-Обратите внимание, что исключённый инстанс нужно снять из-под контроля
-супервизора.
-
-Значение `instance-id` исключённого инстанса может быть использовано
-повторно. Для этого достаточно запустить новый инстанс с тем же
-`instance-id`.
-
-### Примеры использования picodata expel
-
-Ниже приведены типовые ситуации и подходящие для этого команды.
-
-1. На хосте с инстансом `i4` вышел из строя жёсткий диск, данные
-   инстанса утрачены, сам инстанс неработоспособен. Какой-то из
-   оставшихся инстансов доступен по адресу `192.168.104.55:3301`.
-
-    ```bash
-    picodata expel --instance-id i4 --peer 192.168.104.9:3301
-    ```
-
-2. В кластере `mycluster` из 3-х инстансов, где каждый работает на своём
-   физическом сервере, происходит замена одного сервера. Выключать
-   инстанс нельзя, так как оставшиеся 2 узла кластера не смогут создать
-   стабильный кворум. Поэтому сначала в сеть добавляется дополнительный сервер:
-
-    ```bash
-    picodata run --instance-id i4 --peer 192.168.104.1 --cluster-id mycluster
-    ```
-
-    Далее, если на сервере с инстансом i3 настроен автоматический
-    перезапуск Picodata в Systemd или как-либо иначе, то его нужно
-    предварительно отключить. После этого c любого из уже работающих
-    серверов кластера исключается инстанс i3:
-
-    ```bash
-    picodata expel --instance-id i3 --cluster-id mycluster
-    ```
-
-    Указанная команда подключится к `127.0.0.1:3301`, который
-    самостоятельно найдёт лидера кластера и отправит ему команду на
-    исключение инстанса `i3`. Когда процесс `picodata` на i3 завершится
-    — сервер можно выключать.
diff --git a/docs/cluster_group.svg b/docs/cluster_group.svg
deleted file mode 100644
index 00260c54cbcbeaf872454104e59a5c74008f1fe8..0000000000000000000000000000000000000000
Binary files a/docs/cluster_group.svg and /dev/null differ
diff --git a/docs/clustering.md b/docs/clustering.md
deleted file mode 100644
index a0949f846394cc0c07650efb0b575c68839982c7..0000000000000000000000000000000000000000
--- a/docs/clustering.md
+++ /dev/null
@@ -1,457 +0,0 @@
-# Общая схема инициализации кластера
-Данный раздел содержит описание архитектуры Picodata, а именно —
-высокоуровневый процесс инициализации кластера на основе нескольких
-отдельно запущенных экземпляров (инстансов) Picodata.
-
-Администратор запускает несколько инстансов, передавая в качестве
-аргументов необходимые параметры:
-
-```sh
-picodata run --instance-id i1 --listen i1 --peer i1,i2,i3
-picodata run --instance-id i2 --listen i2 --peer i1,i2,i3
-picodata run --instance-id i3 --listen i3 --peer i1,i2,i3
-# ...
-picodata run --instance-id iN --listen iN --peer i1
-```
-
-Независимо от количества запускаемых инстансов, в опции `--peer` у
-каждого из них следует указать один и тот же набор из нескольких
-инстансов — одного обычно достаточно, но для подстраховки можно взять
-три. Именно на их основе будет произведена инициализация кластера и
-поиск всех работающих инстансов для их включения в состав кластера
-(discovery).
-
-Подробности алгоритма discovery приведены в отдельном
-[документе](discovery.md). В контексте сборки кластера важно лишь
-понимать, что этот алгоритм позволяет не более чем одному инстансу
-(peer'у) создать Raft-группу, т.е. стать инстансом с raft_id=1. Если
-таких инстансов будет несколько, то и Raft-групп, а следовательно и
-кластеров Picodata получится несколько.
-
-Топологией Raft-группы управляет алгоритм Raft, реализованный в виде
-крейта `raft-rs`.
-
-## Этапы инициализации кластера
-На схеме ниже показаны этапы жизненного цикла инстанса в контексте его
-присоединения к кластеру Picodata.
-
-![main.rs](clustering_curves.svg "main.rs control flow")
-
-В контексте операционных систем каждый инстанс соответствует группе из
-двух процессов — родительсого (supervisor) и дочернего (именно он
-выполняет tarantool runtime).
-
-Красным показан родительский процесс, который запущен на всем протяжении
-жизненного цикла инстанса. Вся логика, начиная с присоединения к
-кластеру, и заканчивая обслуживанием клиентских запросов, происходит в
-дочернем процессе (голубой цвет). Единственное предназначение
-родительского процесса — выполнять [ребутстрап](#Ребутстрап) и
-инициализировать дочерний процес повторно (сиреневый цвет).
-
-Данная схема наиболее полно отражает логику кода в файле `main.rs`. Ниже
-описаны детали выполнения каждого этапа и соответствующей программной
-функции.
-
-### fn main()
-
-На этом этапе происходит ветвление (форк) процесса `picodata`.
-Родительский процесс (supervisor) ожидает от дочернего процесса
-сообщения по механизму IPC и при необходимости перезапускает дочерний
-процесс.
-
-Выполнение дочернего процесса начинается с вызова функции
-[`start_discover()`](#fn-start_discover) и далее следует алгоритму. При
-необходимости дочерний процесс может попросить родителя удалить все
-файлы БД (см. раздел ["Ребутстрап"](#Ребутстрап)). Это используется для
-повторной инициализации инстанса с нормальным `replicaset_uuid` вместо
-рандомного.
-
-### Ребутстрап
-
-У тарантула есть две особенности, из-за которых процесс инициализации
-выглядит так как выглядит:
-
-1. Принадлежность инстанса тому или иному репликасету определяется в
-   момент первого вызова `box.cfg()` когда создается первый снапшот.
-   Впоследстии изменить принадлежность репликасету невозможно.
-2. Инициализация iproto сервера, реализующего бинарный сетевой протокол
-   тарантула, выполняется той же функцией `box.cfg()`.
-
-В совокупности эти две особенности создают проблему курицы и яйца:
-
-- Инстанс не может общаться по сети, пока не узнает принадлежность
-  репликасету.
-- Принадлежность репликасету невозможно узнать без общения по сети.
-
-Чтобы эту проблему решить, Picodata инициализируется со случайно
-сгенерированными идентификаторами, а позже перезапускает процесс,
-попутно очищая рабочую директорию.
-
-### fn start_discover()
-
-Дочерний процесс начинает свое существование с функции
-[`init_common()`](#fn-init_common), в рамках которой в т.ч.
-инициализируется модуль `box`. Возможно, что при этом из БД будет ясно,
-что bootstrap данного инстанса уже был произведен ранее и что Raft уже
-знает о вхождении этого инстанса в кластер — в таком случае никакого
-discovery не будет, инстанс сразу перейдет к этапу `postjoin()`. В
-противном случае, если место инстанса в кластере еще не известно,
-алгоритм discovery определяет значение флага `i_am_bootstrap_leader` и
-адрес лидера Raft-группы. Далее инстанс сбрасывает свое состояние (см.
-["Ребутстрап"](#Ребутстрап)), чтобы повторно провести инициализацию
-`box.cfg()`, теперь уже с известными параметрами. Сам лидер
-(единственный с `i_am_bootstrap_leader == true`) выполняет функцию
-`start_boot()`. Остальные инстансы переходят к функции `start_join()`.
-
-### fn start_boot()
-
-В функции `start_boot` происходит инициализация Raft-группы — лидер
-генерирует и сохраняет в БД первые записи в журнале. Эти записи
-описывают добавление первого инстанса в пустую Raft-группу  и создание
-начальной clusterwide-конфигурации. Таким образом достигается
-однообразие кода, обрабатывающего эти записи.
-
-Сам Raft-узел на данном этапе еще не создается. Это произойдет позже, на
-стадии `postjoin()`.
-
-### fn start_join()
-
-Вызову функции `start_join()` всегда предшествует
-[ребутстрап](#Ребутстрап) (удаление всех данных и перезапуск процесса),
-поэтому на данном этапе в БД нет ни модуля `box`, ни пространства
-хранения. Функция `start_join()` имеет простое устройство:
-
-Инстанс отправляет запрос [`rpc::join`](#rpcjoin) лидеру Raft-группы (он
-известен после discovery), который в ответе присылает всю необходимую
-для инициализаии информацию:
-
-Для инициализации Raft-узла:
-- идентификатор `raft_id`,
-- данные таблицы `_picodata_peer_address`.
-
-Для первичного вызова `box.cfg()`:
-- идентификаторы  `instance_uuid`, `replicaset_uuid`,
-- `box.cfg.replication` — список урлов для репликации.
-
-Получив все настройки, инстанс использует их в `box.cfg()` (см.
-[`init_common()`](#fn-init_common)), и затем создает в БД группу
-`_picodata_peer_address` с актуальными адресами других инстансов. Без
-этого инстанс не сможет отвечать на  сообщения от других членов
-Raft-группы.
-
-По завершении этих манипуляций инстанс также переходит к этапу
-`postjoin()`.
-
-### fn postjoin()
-
-Логика функции `postjoin()` одинакова для всех инстансов. К этому
-моменту для инстанса уже инициализированы корректные пространства
-хранения в БД и могут быть накоплены записи в журнале Raft.
-
-Функция `postjoin()` выполняет следующие действия:
-
-- Инициализирует HTTP-сервер в соответствии с параметром `--http-listen`.
-
-- Запускает Lua-скрипт, указанный в аргументе `--script`.
-
-- Инициализирует узел Raft, который начинает взаимодействовать с
-  Raft-группой.
-
-- В случае, если других кандидатов нет, инстанс тут же
-  избирает себя лидером группы.
-
-- Устанавливает `on_shutdown` триггер, который обеспечит
-  [корректное завершение работы инстанса](#Graceful-shutdown).
-
-Последним шагом инстанс оповещает кластер о том, что он готов проходить
-настройку необходимых подсистем (репликации, шардинга, и т.д.). Для
-этого лидеру отправляется запрос на обновление `target_grade` текущего
-инстанса до уровня `Online`, после чего за дальнейшие действия будет
-отвечать специальный поток управления [topology governor](#Topology-governor).
-
-Как только запись с обновленным грейдом будет зафиксирована в Raft, узел
-готов к использованию.
-
-### fn init_common()
-
-Функция `init_common` обобщает действия, необходимые для инициализации
-инстанса во всех трех вышеописанных сценариях — `start_discover`,
-`start_boot`, `start_join`.
-
-Инициализация инстанса сводится к следующим шагам:
-
-- создание `data_dir`,
-- первичный вызов `box.cfg`,
-- инициализация `package.preload.vshard`,
-- инициализация хранимок (`box.schema.func.create`),
-- создание системных спейсов (`_picodata_raft_log` и т.д).
-
-Параметры первичного вызова `box.cfg` зависят от конкретного сценария:
-
-| param       | `start_discover` | `start_boot` | `start_join`                  |
-|-------------|------------------|--------------|-------------------------------|
-| listen      | None             | None         | _from args_                   |
-| read_only   | false            | false        | from `rpc::join` response     |
-| uuids       | _random_         | _given_      | from `rpc::join` response     |
-| replication | None             | None         | from `rpc::join` response     |
-| data_dir    | _from args_      | ...          | ...                           |
-| log_level   | _from args_      | ...          | ...                           |
-
-## Обработка запросов
-
-### rpc::join
-
-Значительная часть всей логики по управлению топологией содержится в
-обработчике запроса `rpc::join`.
-
-Аргументом для нее является следующая структура:
-
-```rust
-struct rpc::join::Request {
-    cluster_id: String,
-    instance_id: Option<String>,
-    replicaset_id: Option<String>,
-    advertise_address: String,
-    failure_domain: FailureDomain,
-}
-```
-
-Ответом служит такая:
-
-```rust
-struct rpc::join::OkResponse {
-    /// Добавленный инстанс (чтобы знать все ID)
-    instance: Instance,
-    /// Голосующие узлы (чтобы добавляемый инстанс мог наладить контакт)
-    peer_addresses: Vec<PeerAddress>,
-    /// Настройки репликации (чтобы инициализировать репликацию)
-    box_replication: Vec<String>,
-}
-
-struct Instance {
-    // всевозможные идентификаторы
-    raft_id: RaftId,
-    instance_id: String,
-    instance_uuid: String,
-    replicaset_id: String,
-    replicaset_uuid: String,
-
-    // текущее местоположение, виртуальное и физическое
-    peer_address: String,
-    failure_domain: FailureDomain,
-
-    // текущий и целевой грейды
-    current_grade: CurrentGrade,
-    target_grade: TargetGrade,
-}
-```
-
-Цель такого запроса сводится к добавлению нового инстанса в Raft-группу.
-Для этого алгоритма справедливы следующие тезисы:
-
-- Запрос `rpc::join` всегда делает инстанс без снапшотов.
-- В процессе обработки запроса в Raft-журнал добавляется запись
-  `op::PersistPeer { peer }`, при этом `current_grade: Offline`,
-  `target_grade: Offline` (подробнее о них в разделе [topology
-  governor](#Topology-governor)).
-- В ответ выдается всегда новый `raft_id`, никому другому ранее не
-  принадлежавший.
-- Помимо идентификаторов нового инстанса, ответ содержит список
-  голосующих членов Raft-группы. Они необходимы новому инстансу для
-  того чтобы отвечать на запросы от Raft-лидера.
-- Также ответ содержит параметр `box_replication`, который требуется для
-  правильной настройки репликации.
-
-## Graceful shutdown
-
-Чтобы выключение прошло штатно и не имело негативных последствий,
-необходимо следить за соблюдением следующих условий:
-
-- Инстанс не должен оставаться голосующим, пока есть другие кандидаты в
-  состоянии `Online`.
-- Инстанс не должен оставаться лидером.
-
-Чтобы этого добиться, каждый инстанс при срабатывании триггера
-`on_shutdown` отправляет лидеру запрос `UpdatePeerRequest {
-target_grade: Offline }`, обработкой которого займется вышеупомянутый
-`governor_loop`. После этого инстанс пытается дождаться применения
-записи о смене своего `current_grade` на `Offline` (о том, почему так
-произойдет см. ниже).
-
-
-## Описание уровней (grades) кластера
-По некоторым причинам коммит записи может не успеть дойти до инстанса в
-срок, отведенный на выполнение триггера `on_shutdown` триггера (например
-в кластере может быть потерян кворум). В таком случае корректное
-завершение работы инстанса (`graceful shutdown`) невозможно.
-
-## Topology governor
-
-В отличие от других кластерных решений (например, того же Tarantool
-Cartridge) Picodata не использует понятие "состояния" для описания
-отдельных инстансов. Вместо этого теперь применяется новое понятие
-«грейд» (grade). Данный термин отражает не состояние самого инстанса, а
-конфигурацию остальных участников кластера по отношению к нему.
-Существуют две разновидности грейдов: текущий (`current_grade`) и
-целевой (`target_grade`). Инициировать изменение `current_grade` может
-только лидер при поддержке кворума, что гарантирует консистентность
-принятого решения (и поддерживает доверие к системе в плане
-отказоустойчивости).
-
-Инициировать изменение `target_grade` может кто угодно — это может быть
-сам инстанс (при его добавлении), или администратор кластера командой
-`picodata expel` либо нажатием Ctrl+C на клавиатуре. `target_grade` —
-это желаемое состояние инстанса, в которое тот должен прийти.
-
-Приведением действительного к желаемому занимается специальный файбер на
-лидере — `governor_loop`. Он управляет всеми инстансами сразу.
-
-С грейдом (как с текущим, так и с целевым) также всегда ассоциирована
-инкарнация (`incarnation`) — порядковое число, отражающее число попыток
-обработать данный инстанс со стороны файбера `governor_loop`. Это
-позволяет реагировать на ситуации, когда инстансы выходят из строя на
-какой-то период времени, после чего их необходимо снова привести в
-актуальное состояние.
-
-
-На основе совокупности грейдов и их инкарнаций `governor_loop` на каждой
-итерации бесконечного цикла генерирует активности (activity) и пытается
-их организовать. Пока не организует, никаких других изменений в текущих
-грейдах не произойдет (но могут измениться целевые). Если активности
-завершатся ошибкой, то на следующей итерации они будут перевычислены с
-учетом новых целей.
-
-Инкарнации грейдов вычисляются по следующему принципу.
-- Каждый раз когда `target_grade` инстанса получает значение `Online`,
-    его инкарнация увеличивается на 1.
-- Все остальные изменения грейдов копируют инкарнацию с противоположного
-    грейда, то есть при изменении `target_grade` инкарнация копируется с
-    `current_grade`, при изменении `current_grade` — с `target_grade`.
-
-Дальше перечислены активности, которыми занимается `governor_loop`, в
-том же порядке, в котором он к ним приступает.
-
-
-![Instance states](fsm.svg "Возможные переходы состояний инстанса")
-
-Ниже перечислены существующие варианты активностей, которые создает
-`topology_governor`.
-
-### 1. Обновить состав голосующих / неголосующих инстансов
-
-Сначала нужно проверить необходимость менять конфигурацию Raft-группы, а
-именно — состав голосующих / неголосующих узлов (`voters` и `learners`).
-
-Правила выбора новой конфигурации описаны в
-`picodata::governor::cc::raft_conf_change` и заключаются в следующем:
-- Любые инстансы, переходящие в грейд `Expelled`, удаляются из
-  Raft-группы;
-- Голосущие инстансы, переходящие в грейд `Offline`, перестают быть
-  голосующими (становятся `learners`) и для них находится замена;
-- Среди свежедобавленных инстансов с текущим грейдом `Online`
-    подбирается необходимое количество голосующих инстансов (`voters`),
-    остальные добавляются как `learners`;
-
-<!-- [TODO](#Предстоит сделать) Новые воутеры должны выбираться с учетом failure
-domain'ов. -->
-
-По этим правилам создается `ConfChangeV2`, и, если он не пуст,
-отправляется в Raft. Далее нужно дождаться события `TopologyChanged`,
-которое будет послано в ответ на успешное применение новой конфигурации.
-
-### 2. target_grade Offline / Expelled.
-
-Ниже рассмотрены два варианта вывода инстанса из строя: временный
-(`target_grade = Offline`) и постоянный (`target_grade = Expelled`).
-Перед тем как выключить инстанс, нужно убедиться, что кластер сможет
-продолжить функционировать без него.
-
-Если уходит лидер Raft-группы, то есть инстанс, на котором в данный
-момент выполняется `governor_loop`, то он снимает с себя полномочия
-(делает `transfer_leadership`) и ждет смены Raft-статуса, дальше
-действовать будет кто-то другой.
-
-Если уходит лидер своего репликасета, то происходят новые выборы такого
-лидера, после чего нужно дождаться соответствующей записи в спейс с
-репликасетами.
-
-Далее следует обновить конфигурацию шардирования (`vshard`) на всех
-инстансах с ролями хранения данных (`storage`) и маршрутизации
-(`routers`), чтобы оповестить их об изменениях в топологии. Если это
-последний узел хранения в репликасете, ему будет выставлен вес 0.
-
-<!-- [TODO](#Пока не сделано)
- Также, если это последний узел хранения в репликасете, ему надо выставить вес в 0. Дожидаться ребалансировки на этом шаге не требуется (да и не получится — слишком долгая блокировка), для этого есть отдельный пункт. -->
-
-Наконец, инстансу присваивается `current_grade`, соответствующей его
-целевому уровню.
-
-### 3. target_grade: Online, current_grade: * -> RaftSynced
-
-Дальше начинается обработка инстансов, которых нужно привести в
-актуальное состояние. Это либо свежедобавленные инстансы, либо инстансы,
-которые были какое-то время неактивны.
-
-Выбираем инстанс, либо имеющий `current_grade: Offline`, либо имеющий
-инкарнацию текущего грейда меньше, чем инкарнацию целевого.
-
-На этом этапе мы синхронизируем Raft-журнал выбранных инстансов. Берем
-текущий `commit_index` лидера и дожидаемся, пока `commit_index` пира его
-не догонит. После этого присваиваем инстансу `current_grade =
-RaftSynced`.
-
-<!-- [TODO](#Пока не сделано) Этот шаг можно распараллелить, отправив запрос сразу
-нескольким подходящим пирам. -->
-
-### 4. target_grade: Online, current_grade: RaftSynced -> Replicated
-
-Этот этап отвечает за настройку репликации внутри одного репликасета, к
-которому относится выбранный инстанс.
-
-Первым делом мы сообщаем всем инстансам репликасета, что необходимо
-применить новую конфигурацию репликации через `box.cfg { replication =
-... }`. Однако, так как конфигурация кластера (в том числе и
-конфигурация репликасетов) распространяется между инстансами через
-Raft-журнал, необходимо убедиться что журнал у всех свежий. Для этого в
-запросе также передаем `commit_index`, которого пиры должны дождаться
-прежде чем выполнять сам запрос.
-
-После этого инстансу, инициировавшему активность, присваивается
-`current_grade: Replicated`.
-
-<!-- [TODO](#Пока не сделано) Можно обновлять грейд сразу всем инстансам в
-репликасете, которым это нужно. -->
-
-На этом же этапе добавляем запись в спейс с репликасетами, если ее там
-еще нет. При этом вес шардирования устанавливается в 0, если только это
-не первый репликасет в кластере.
-
-Последнее что нужно сделать на этом этапе, это обновить значение
-`box.cfg { read_only }` в конфигурации лидера затронутого репликасета.
-<!-- ([TODO](#Пока не сделано) это не обязательно делать каждый раз). -->
-
-### 5. target_grade: Online, current_grade: Replicated -> ShardingInitialized
-
-На данном этапе настраивается шардирование всего кластера, поэтому
-запросы отправляются сразу всем инстансам.
-
-Рассылаем всем запрос на обновление конфигурации шардирования
-(`vshard.router.cfg()` и `vshard.storage.cfg()`) опять вместе с
-`commit_index`, чтобы инстансы получили последние данные.
-
-На этом этапе первый репликасет, наполненный до фактора репликации,
-запускает начальное распределение бакетов (`vshard.router.bootstrap`)
-<!-- ([TODO](#Пока не сделано) пока что это делает первый инстанс в кластере). -->
-
-В конце этого этапа подсистема шардирования данных (`vshard`) на всех
-инстансах знает о топологии всего кластера, но на некоторых репликасетах
-вес все еще проставлен вес 0, поэтому данные на них ребалансироваться
-еще не будут.
-
-### 6. target_grade: Online, current_grade: ShardingInitialized -> Online
-
-Этот этап нужен для того чтобы запустить ребалансировку данных на новые
-репликасеты. Для этого проверяем, есть ли у нас репликасеты с весом 0 и
-достигнутым фактором репликации. Если есть, то обновляем их вес и
-повторно обновляем конфигурацию шардирования на всем кластере, чтобы
-данные начали ребалансироваться.
diff --git a/docs/clustering.svg b/docs/clustering.svg
deleted file mode 100644
index cdf2e9e9da954cfaa2c876431218e7c3bcabfb95..0000000000000000000000000000000000000000
Binary files a/docs/clustering.svg and /dev/null differ
diff --git a/docs/clustering_curves.svg b/docs/clustering_curves.svg
deleted file mode 100644
index b08865da3cc48d3934961b57bcea16a354c83e39..0000000000000000000000000000000000000000
Binary files a/docs/clustering_curves.svg and /dev/null differ
diff --git a/docs/discovery.md b/docs/discovery.md
deleted file mode 100644
index f74db79135f87b5da8d16532e522a38dda1e76c7..0000000000000000000000000000000000000000
--- a/docs/discovery.md
+++ /dev/null
@@ -1,92 +0,0 @@
-# Discovery algorithm
-
-## Входные данные:
-
-- `N` узлов, пока не связанных друг с другом по сети. Связать их предстоит алгоритму.
-- Тем не менее, каждый узел обладает на старте информацией о некоторых его соседях - массиве `initial_peers`, содержащем сетевые адреса узлов (не менее одного).
-
-Алгоритм налагает некоторые ограничение на входные данные, в противном случае результат работы алгоритма может оказаться некорректным. Чтобы обеспечить выполнение результата, у любой пары узлов должен существовать как минимум один общий элемент `initial_peers`.
-
-Здесь стоит сказать пару слов о том, как именно мы будем моделировать сеть. Алгоритм специально составлен таким образом, чтобы его легко было адаптировать под конкретный транспортный протокол, хоть TCP, хоть UDP.
-
-Чтобы не прослыть инфантильными, мы также сразу допускаем, что связность сети может спонтанно нарушаться. Любое сообщение может:
-- быть доставлено получателю спустя неопределённое время,
-- возможно бесконечно малое,
-- а возможно и бесконечно никогда.
-
-Мы хотим, чтобы алгоритм был полезен на практике. И такое предположение, несомненно, благоприятно скажется на способностях алгоритма не разбиться о суровую реальность, где сервера иногда ~~простужаются~~ перегреваются и выгорают целыми датацентрами.
-
-В тоже время алгоритм совершенно не подготовлен к решению задачи о византийских генералах. Акцент в первую очередь делается на отказоустойчивости к ошибкам пользователя, а не злонамеренности генералов. Это призвано упростить процесс инициализации рафт группы (который в худшем случае можно и перезапустить на этапе подготовки к эксплуатации, в отличие от генералов). Византийская отказоустойчивость, если это необходимо, должна обеспечиваться другим протоколом.
-
-## Результат:
-
-Результатом работы этого распределенного алгоритма является единственное булево значение `i_am_bootstrap_leader`. Мы ожидаем (и заверяем вас), что, пока входные параметры не нарушают наложенных ограничений, не более одного узла будущего кластера присвоят себе эту медальку. Я бы хотел, чтобы "не меньше" тоже было равно одному, но, увы, в условиях полной сетевой изоляции ответ будет ноль, и никакой онлайн-вечеринки не состоится.
-
-И опять, в угоду пользовательского опыта, алгоритм не пытается заполучить больше информации о будущем кластере. В противном случае это потребовало бы делать дополнительные предположения о сетевой связности, и это могло негативно сказаться на удобстве эксплуатации решения. Данный алгоритм надеется на лучшее (один бутстрап лидер), оставаясь готовым к худшему (ноль бутстрап лидеров).
-
-## Собственно сам алгоритм
-
-### **Шаг 0.1**
-
-Как уже упоминалось раньше, каждый узел _i_ инициализирует массив известных адресов `known_peers[i] = initial_peers[i]` (со значениями, предоставленными пользователем).
-
-### **Шаг 0.2**
-
-Каждый узел _i_ генерирует случайный идентификатор (`guid[i]`), вероятность коллизии которых мы предполагаем равной нулю. Это требование совсем не сложно выполнить на практике.
-
-### **Шаг 1**
-
-Каждый узел _i_ проводит раунд запросов номер `r` - отправляет по всем известным адресам `known_peers[i][m]` сообщение `("discovery_req", m, known_peers[i])`. Параметр `m` представляет собой всего лишь индекс адресата в массиве `known_peers[i]`. Единственная его роль в алгоритме - быть возвращённым в ответе, чтобы можно было сопоставить ответ с конкретным адресом. Впрочем, его можно вообще опустить, если эту функциональность предоставляет используемый транспортный протокол.
-
-### _Меж двух шагов_
-
-Получив сообщение `("discovery_req", m, known_peers[i])`, узел (_j_) проверяет своё состояние.
-
-Если на данный момент лидер уже выбран и известен, то отправляет в ответ сообщение `("discovery_finished")`.
-
-В противном случае обновляет свой массив `known_peers[j] = known_peers[i] \/ known_peers[j]`. Ответ содержит `("discovery_resp", m, known_peers[j], guid[j])`.
-
-Здесь делается ещё одно допущение о том, что используемый транспортный протокол обладает функцией "отправки ответа". Оба TCP и UDP такой функциональностью обладают.
-
-### **Шаг 2** (Возвращаясь к узлу _i_ - отправителю запроса)
-
-Yaroslav Dynnikov, [08/04/2022 22:18]
-
-
-Получив ответ `("discovery_finished")` алгоритм завершает свою работу - задача выполнена. `i_am_bootstrap_leader[i] = false`.
-
-Получив ответ `("discovery_resp", m, known_peers[j], guid[j])`, узел (_i_), как и в случае обработки `discovery_req`, обновляет свой массив `known_peers[i] = known_peers[i] \/ known_peers[j]`. Далее полученный ответ сопоставляется с адресатом `known_peers[i][m]`. Если в массиве `known_peers[i]` остались ещё не ответившие адресаты, алгоритм приостанавливается до получения следующего сообщения.
-
-Если ответ содержит ошибку протокола транспортного уровня, запрос повторяется с некоторым интервалом до тех пор, пока не будет получен внятный ответ.
-
-Если к концу этого шага были обнаружены новые адресаты, алгоритм начинает новый раунд запросов `r+1` и возвращается к шагу 1.
-
-### **Шаг 3**
-
-Если вдруг лидер до сих пор не известен, то к этому моменту каждому узлу _i_ становится известна полная карта `known_peers[i][m] -> guid[m]`.
-
-Если вдруг `guid[i] == min(guid)`, то узел понимает, что `i_am_bootstrap_leader[i] = true`, и с этих пор перестаёт изменять внутреннее состояние, и отвечает на все запросы `("discovery_finished")`.
-
-Если же, напротив, `guid[i] != min(guid)`, то `i_am_bootstrap_leader[i] = false`.
-
-### Доказательство
-
-Корректность алгоритма проще всего доказать от противного. Предположим, что в какой-то момент узел _i_ решил, что `i_am_bootstrap_leader[i] == true`, в то время как уже существовал `i_am_bootstrap_leader[j] == true` (и при этом `i != j`).
-
-Так как на третьем шаге оба узла вычисляют `min(guid)` идентичным оразом, то отличаться должны были сами таблицы `guid`.
-
-При этом массив `known_peers[j]` заведомо не содержал адрес _i_ в момент принятия решения, но содержал свой адрес _j_, иначе бы не выполнилось условие `guid[j] == min(guid)`. Аналогично, `known_peers[i]` точно содержал _i_.
-
-В то же время `known_peers[i]` не мог содержать _j_, иначе _i_ не смог бы получить от _j_ ответ `("discovery_resp")` и не “выдать” себя.
-
-Таким образом _i_ и _j_ не должны были в момент принятия решения ничего знать друг о друге.
-
-Но так как у _i_ и _j_ по условию должен быть как минимум один общий "сосед", назовём его _z_, он также должен был обоим _i_ и _j_ дать ответы `("discovery_resp")`. Противоречие заключается в том, что _z_ пришлось бы одному из двух узлов в ответе `("discovery_resp")` сообщить о существовании второго, покуда обработка запросов выполняется атомарно.
-
-### Возможные оптимизации
-
-Основная часть алгоритма изложена так, чтобы быть максимально простой. Тем не менее, это не исключает наличия нескольких полезных оптимизаций, которые нисколько не влияют на результат, хотя позволяют сделать пользовательский опыт приятнее.
-
-Начинать новый раунд на втором шаге не возбраняется сразу после обнаружения нового адресата. Не обязательно для этого дожидаться всех ожидаемых ответов.
-
-После завершения работы алгоритма, с сообщениями `("discovery_finished")` можно рассылать информацию об адресе лидера, о `known_peers`, или любую другую необходимую, которую хотелось бы синхронизировать. Так как единственность лидера доказана, остальные узлы могут ему верить, если конечно никто больше не возьмётся её модифицировать, а мы договорились не рассматривать византийские сценарии.
diff --git a/docs/fsm.svg b/docs/fsm.svg
deleted file mode 100644
index 62e5cb9a10d497c3ea87bfadcddf886b3fd61b6b..0000000000000000000000000000000000000000
Binary files a/docs/fsm.svg and /dev/null differ
diff --git a/docs/glossary.md b/docs/glossary.md
deleted file mode 100644
index f26b56d36fbd6e0d9633c5b754bd9933afe56c88..0000000000000000000000000000000000000000
--- a/docs/glossary.md
+++ /dev/null
@@ -1,248 +0,0 @@
-# Глоссарий
-## Общие сведения
-Данный раздел содержит описание основных терминов, используемых в Picodata.
-
-## Подсистемы
-### Raft
-**Raft** является алгоритмом распределенного консенсуса, который нужен, чтобы несколько участников могли совместно решить, произошло ли событие или нет, и что за чем следовало. Raft используется в Picodata для согласования работы узлов и поддержания консистентности в кластере. Концепция распределенного консенсуса предполагает, что в кластере всегда есть только один лидер и некоторое количество голосующих узлов. Эти узлы в нормальном состоянии подтверждают легитимность лидера, а при отказе текущего лидера организуют выборы нового.
-См. [подробнее](https://raft.github.io/raft.pdf).
-
-### Терм (term)
-Период между выборами лидера в raft-группе называется **термом** (term). Каждый терм начинается в момент объявления выборов нового лидера. Обычно это происходит после потери связи с прежним лидером. Терм состоит из двух частей: выборов и периода нормальной работы raft-группы. Исключением служат термы, в течение которых не удалось выбрать лидера группы: у таких термов есть только первая часть (выборы).
-Важно помнить, что в одном терме не может существовать более одного лидера raft-группы.
-
-### Состояния узлов в Raft-группе <a name="raft-group"></a>
-В raft-группе любой узел может быть в одном из трех состояний:
-
-**Пассивный узел (follower)** — состояние по умолчанию для каждого инстанса после запуска. Follower — обычный голосующий узел, который лишь отвечает на запросы, но не генерирует их.
-
-**Кандидат в лидеры (candidate)** — состояние инстанса во время выборов лидера. Когда начинается новый терм, инстансы в статусе follower увеличивают значение терма и переходят в статус кандидатов, голосуют сами за себя и затем ждут результатов выбора. Выходов из этого состояния три: 
-
-- Кандидат побеждает в выборах и становится лидером.
-- Кандидат возвращается в статус follower, так как другой инстанс становится лидером.
-- Кандидат остается кандидатом, так как не удается выбрать лидера. Raft увеличивает терм еще раз и организует повторные выборы.
-
-**Лидер raft-группы (leader)** — избранный узел, который отвечает за обработку запросов и репликацию raft-журнала.
-
-### Raft-лидер	
-**Лидер в raft-группе** — это один из узлов, который несет ответственность за репликацию raft-журнала. Лидер избирается на голосовании и признается таковым всеми участниками голосования. Задача лидера состоит в приеме сообщений от клиентов кластера и отправке сообщений на узлы кластера таким образом, чтобы в любой момент времени все узлы имели консистентную, непротиворечивую версию raft-журнала. Лидерство в Raft предполагает, что все остальные узлы признают приоритет версии журнала, предлагаемую лидером.
-
-Если лидер становится недоступным, то алгоритм Raft организует выборы нового лидера среди оставшихся участников. Если после этих выборов прежний лидер снова присоединится к кластеру, он уже будет иметь права обычного голосующего узла (но не лидера).
-
-### Репликация raft-журнала
-**Репликация raft-журнала** нужна для того, чтобы на каждом узле кластера (raft-группы) была одинаковая история команд. Когда лидеру группы нужно добавить в журнал новую команду, он сначала отправляет ее всем узлам, ждет подтверждения записи (commit), и лишь затем добавляет эту команду в собственный журнал. В случае, если журнал обычного узла отличается от журнала лидера, то лидер настаивает на приоритете своего журнала и перезаписывает журнал обычного узла, считая его устаревшим.
-Для упрощения репликации алгоритм Raft придерживается двух правил при сравнении журналов разных узлов:
-
-- Если записи имеют одинаковые индексы и термы, то они содержат одинаковые команды.
-- Если записи имеют одинаковые индексы и термы, то считается, что все предыдущие записи соответствующих журналов одинаковы.
-
-Так как а) записи в журнале не могут менять порядок и б) каждой записи соответствует только один индекс и терм, то указанные выше правила гарантирует консистентность журнала.
-
-
-
-### Web UI
-**Веб-консоль** — это вариант графического интерфейса к функциям Picodata. Данная подсистема находится в разработке и будет представлена в следующем релизе Picodata. Веб-консоль в наглядном виде отображает и позволяет менять конфигурацию и состав кластера, параметры отдельных узлов, схему данных и т.д. Веб-консоль является удобным инструментов локального и удаленного администрирования Picodata.
-
-### CLI (Command-line interface)
-**CLI** — это интерфейс командной строки для запуска и управления как отдельными инстансами, так и всем кластером Picodata.
-
-### Дискавери (discovery)
-**Discovery** —  алгоритм, по которому инстансы обнаруживают друг друга. Этот шаг необходим на старте каждого инстанса для корректной работы кластера.
-
-### Vshard
-**Vshard** — библиотека из экосистемы СУБД Tarantool, используемая в Picodata для горизонтального масштабирования — сегментирования данных по нескольким узлам в кластере. Это становится важным по мере увеличения объема хранимых данных, ввода в строй новых узлов — т.е. роста кластера.
-Библиотека Vshard встроена в Picodata и является неотъемлемой ее частью. 
-В клиентских интерфейсах Vshard желательно прятать за фасадом, но при острой необходимости ничто не помешает им воспользоваться.
-
-## Сущности
-В начале идет общее обозначение термина, затем в скобках указан предпочтительный вариант употребления в коде (без пробелов в “змеином регистре”). 
-
-### Инстанс (instance) <a name="instance"></a>
-**Обозначение единицы кластера СУБД и сервера приложений**
-При описании кластера мы различаем программный и логический уровни.
-
-На программном уровне единицей кластера является экземпляр приложения Picodata, также на техническом жаргоне называемый инстансом. Среда выполнения приложения может быть как виртуальной, так и физической. В разрезе операционных систем каждый инстанс порождает два процесса: собственно экземпляр приложения и вспомогательный процесс (supervisor), управляющий жизненным циклом первого. 
-
-На логическом уровне единицей кластера является узел. Под узлом, в зависимости от контекста, может пониматься как отдельная вычислительная единица, обладающая пулом ресурсов (физический сервер, виртуальная машина, контейнер), так и программный экземпляр Picodata, уже входящий в состав кластера.
-
-Также инстанс является репликой в составе репликасета и может входить в указанную при его запуске группу инстансов.
-
-### Кластер (cluster) <a name="cluster"></a>
-**Кластер** — набор логических и программных узлов, составляющих отдельную централизованно управляемую группу с общим пространством хранения.
-
-**Кластер** является наиболее крупной сущностью в системе хранения, в некотором смысле он и есть система хранения. Внутри кластера находятся инстансы, объединенные в репликасеты (см. ниже). Дополнительно, в Picodata используется понятие групп инстансов — отдельного способа более гибко управлять большим числом инстансов в зависимости от их ролей, характера нагрузки и топологии сети.
-
-Схематичное представление кластера, в составе которого есть некоторое число инстансов, репликасетов и групп инстансов, показано ниже.<a name="cluster_group"></a>
-
-![Cluster](cluster_group.svg)
-
-### Репликасет (replicaset) <a name="replicaset"></a>
-**Репликасет** — буквально «набор реплик», экземпляров приложений, в которых хранится один и тот же набор данных. Реплика в составе репликасета может быть в одном из двух состояний:
-
-- активная (active) — доступная на запись, иногда ее называют мастером или лидером репликасета.
-- резервная (standby) — доступная только на чтение, read-only.
-В нормальных условиях в репликасете активной является ровно одна реплика, но в отдельных случаях их может быть несколько или не быть вообще.
-
-### Лидер (leader)
-<p name="leader">В Picodata есть две разновидности лидеров:</p>
-
-- “raft-лидер” — лидер raft-группы,
-- и “репликасет-лидер” — лидер репликасета.
-
-Термин _лидер_ часто путают с _мастером_ применительно к репликации Tarantool. В Picodata они хоть и близки, но все же отличаются по смыслу. Под _мастером_ следует понимать инстанс, который выполняет пользовательские DML-операции (insert / update / delete). На практике чаще всего такой инстанс один, и в таком случае оба термина описывают один и тот же инстанс (отсюда и путаница), но в Tarantool архитектурно заложена возможность вести запись на нескольких узлах репликасета одновременно — т.н. режим мультимастера (multi-master). Даже в таком режиме операции DDL (`create_space` и т.д.) должен выполнять лишь один инстанс из всех, и здесь становится важно отличать _лидера_ от _мастера_. Несмотря на то, что в Picodata режим мультимастера пока не реализован, документация и код должны использовать эти термины корректно.
-
-### Группа инстансов (instance_group)
-**Группа инстансов** — это логическое объединение инстансов с общим фактором репликации и ролями. Каждая группа шардируется индивидуально.
-
-Концепция групп является аналогом [vshard_group](https://www.tarantool.io/ru/doc/latest/book/cartridge/cartridge_cli/commands/replicasets/#list-vshard-groups) из Cartridge, но дополнительно позволяет назначать роли группам (в Cartridge роли настраивались индивидуально для каждого репликасета). 
-
-**Группа инстансов** является более крупным образованием, чем репликасет. См пояснительную [картинку](glossary.md#cluster_group).
-
-Каждый шардированный спейс принадлежит одной конкретной инстанс-группе. На инстансах из других групп спейс физически не создается. Но т.к. схема данных является общей на весь кластер, создавать два спейса с одинаковым именем в разных группах не разрешается. Принадлежность инстанс-группе определяется только для шардированных спейсов, глобальные спейсы создаются повсюду.
-
-### Домен отказа (failure_domain)
-**Домен отказа** является признаком физического расположения сервера, на котором запущен инстанс. Указание домена отказа позволяет обозначить наличие единой точки отказа у двух инстансов. Смысл данного параметра состоит в том, чтобы в один репликасет попадали инстансы из разных физических локаций, что повышает отказоустойчивость кластера.
-
-**Домен отказа** представляет собой набор пар “ключ=значение”, которые соответствуют отдельным зонам (географический регион, датацентр, стойка и т.д.). Зоны задаются пользователем исходя из фактической конфигурации оборудования, будь то виртуальные машины в облаке (`“region=eu”`) или физические сервера (`“dc=msk”`). Домен отказа может включать несколько зон (`“dc=msk,srv=msk-1”`).
-
-Можно использовать любые ключи и значения. Picodata не делает предположений об иерархии зон или их физическом смысле и просто сравнивает строки. Тем не менее, чтобы избежать человеческих ошибок, Picodata требует, чтобы набор зон (ключей) на всех инстансах был одинаковым.
-
-Если домены отказа двух инстансов имеют хотя бы одну общую зону (и ключ, и значение), то допускается возможность одновременной потери связи с обоими. Поэтому инстансы, делящие общую зону, не будут объединены в репликасет. Picodata также стремится распределить голосующие raft-узлы таким образом, чтобы их домены отказа имели по минимуму общих зон.
-
-### Фактор репликации (replication_factor)
-**Фактор репликации** — число инстансов в репликасете. Задается общим на группу инстансов (так же как и набор ролей). Отредактировать фактор репликации, сохраненный в конфигурации кластера, можно командой `picodata set-replication-factor`. Редактирование конфигурации сказывается только на вновь добавляемых инстансах, но не затрагивает уже работающие.
-
-
-### Бакет (bucket) <a name="bucket"></a>
-**Bucket (бакет)** — виртуальная неделимая единица хранения данных, обеспечивающая их локальность (т. е. нахождение на каком-то одном репликасете).
-
-### Спейс (space)
-**Space (спейс)** — пространство хранения данных. В резидентных СУБД спейс является синонимом таблицы из реляционных СУБД. В Picodata есть следующие виды спейсов:
-
-1. Глобальные (_global_) — их содержимое реплицируется на весь кластер.
-2. Шардированные (_sharded_) — каждый репликасет хранит лишь часть общего
-   набора данных. Данные реплицируются внутри репликасета.
-
-Метаданные всех спейсов Picodata присутствуют на всех узлах кластера.
-Фактически для пользователя не существует понятия “не кластерных”
-спейсов, он лишь выбирает между стратегиями шардирования и репликации
-тех спейсов, с которыми он работает.
-
-### Индекс (index)
-**Индекс** — это специальная структура данных, которая хранит группу ключевых значений и указателей. Индекс строится по какому-либо одному столбцу таблицы и используется для эффективного поиска значений этого столбца. У каждого спейса обязательно должен быть первичный индекс и опционально некоторое число вторичных индексов. 
-
-### LSN (log sequence number)
-Термин **LSN** (log sequence number) относится к архитектурным особенностям Tarantool, в котором все обновления БД фиксируются в журнале упреждающей записи (WAL, write-ahead log) в виде отдельных записей. Каждая запись представляет собой запрос на изменение данных (`insert` | `update` | `delete`) и маркируется монотонно возрастающим номером LSN. Наибольший номер обозначает номер наиболее свежей записи, находящейся в конце журнала WAL. 
-
-### Vclock (vector clock)
-Репликация в Tarantool предполагает обмен записями между репликами в репликасете. Благодаря этому обмену, на каждой отдельной реплике имеется специальный набор записей, полученный от разных реплик с разными LSN — это и есть **Vclock** (vector clock, векторные часы). Vclock описывает состояние БД для отдельного инстанса в репликасете.
-
-Vclock репликасет-лидера играет важную роль в поддержании консистентности при переключении лидера (consistent switchover). В случае аварийного переключения (фейловера, failover), когда консистентность сохранить невозможно и она жертвуется в угоду доступности, отслеживание vclock позволяет строить метрики точек восстановления (RPO, recovery point objective).
-
-### Сетевой адрес (address) <a name="address"></a>
-**Сетевой адрес** — это комбинация `host:port`, используемая для связи инстансов друг с другом по сети. Другие названия для связки `host:port` (например URL, URI) мы стараемся искоренить. Расширенная версия `user:pass@host:port` все равно определяется термином _адрес_.
-
-### Грейд (grade)
-**Grade (грейд)** — специфичный для Picodata способ обозначения состояния инстанса. Грейд отражает то, как инстанс сконфигурирован его соседями. Существуют текущий (`current`) и целевой (`target`) типы грейдов. За приведение первого ко второму отвечает governor (губернатор).
-
-### Губернатор (governor)
-**Governor (губернатор)** — внутренняя централизованная сущность, управляющая конфигурациями и жизненными циклами инстансов в соответствие с изменениями их грейдов. "Губернатор" выполняется на лидере raft-группы.
-
-### Крейт (crate)
-**Крейт** (буквально “ящик”) — наименьшая логическая единица проекта, написанного на Rust. С точки зрения компилятора rustc, любой отдельный фрагмент кода является крейтом. Из одного крейта может быть скомпилирован бинарный исполняемый файл, либо разделяемая библиотека. Несколько крейтов могут вместе составлять пакет (package). Пакет может состоять также и из одного крейта. Если крейтов в пакете несколько, то из них только один может предоставлять разделяемую библиотеку.
-
-### Снапшот (snapshot) <a name="snapshot"></a>
-**Снапшот**, в самом широком смысле этого слова — это снимок состояния распределенного конечного автомата. В контексте Picodata можно говорить о двух независимых (почти) распределенных конечных автоматах, и, соответственно, о двух видах снапшотов — Tarantool и Raft.
-
-Picodata прилагает все усилия, чтобы эти состояния были одинаковыми на каждом узле кластера, но т.к. изменения на нодах происходят через применение команд из журнала (WAL или raft), то даже в штатном режиме случаются не одновременно.
-
-Более детально, состояние инстанса включает в себя две части:
-
-- персистентные данные, которые можно сериализовать и сохранить на диск;
-- транзиторное (transient) состояние — все структуры, которые Tarantool строит в оперативной памяти для обработки DML-запросов.
-
-См. также:
-
-- [RFC — Storage schema — Raft snapshot](https://docs.google.com/document/d/1MEpGnpKKj6WezLKytvvonZzbpy1tlWtAK5ccxaeAOrE/edit#heading=h.687c3wywf9ub)
-- [Tarantool — Persistence](https://www.tarantool.io/en/doc/latest/concepts/data_model/persistence/)
-
-
-## Процессы и алгоритмы
-### Компактизация raft-журнала (raft log compaction)
-**Компактизация** — процесс, не допускающий бесконтрольного роста журнала записей Raft. Компактизация заключается в удалении части журнала, относящейся к сделанному ранее снапшоту.
-
-### Создание снапшотов (snapshotting)
-**Создание снапшотов** — процесс периодического сохранения состояния инстанса на жесткий диск. Наличие снапшотов (т.е. снимков состояния) позволяют восстановить инстанс в прежнем виде после его перезапуска.
-
-### Фенсинг (fencing)
-**Фенсинг** — это подпись всех запросов в кластере номером эпохи или терма, и отказ обслуживать запросы с устаревшей эпохой. Данный инструмент используется для корректной работы распределенной блокировки, т.е. ситуации, когда из нескольких узлов нужно гарантированно выбрать один для выполнения запроса.
-
-### CaS (compare and swap) <a name="cas"></a>
-**Compare and swap** — особый алгоритм в составе Picodata. Он обеспечивает уровень изоляции транзакций [serializable](glossary.md#isolation), тем самым не допуская случаев несогласованности данных в результате выполнения конкурирующих запросов/транзакций. Таким случаем, например, может быть ситуация, когда одна транзакция затирает результат действия другой, выполняющейся в тоже время. _Compare and swap_ решает эту проблему с помощью проверки предиката, т.е. меняет данные какого-либо параметра кластера только в том случае, если исходное ожидаемое значение этого параметра соответствует исходному фактическому. 
-Технически данный алгоритм реализован в виде хранимой процедуры `proc_cas()`. 
-
-### Бутстрап (bootstrap) <a name="bootstrap"></a>
-**Bootstrap** — процесс первоначального объединения разрозненных инстансов в единый кластер. В контексте Picodata речь обычно идет о бутстрапе инстанса, когда инстанс запускается в чистой директории без снапшотов. При необходимости можно уточнить, бутстрапится _лидер реплиасета_ или _read-only-реплика_ — алгоритмы для них отличаются.
-
-Случай, когда инстанс запускается на существующих снапшотах, называется _восстановлением из снапшота_ (recovery from a snapshot). Этот процесс сопутствует перезапуску инстанса.
-
-Другой эксплуатационный сценарий, когда при перезапуске удаляются все данные инстанса, называют _ребутстрапом_ (rebootstrap), т.е. повторным запуском. Ребутстрап всегда сопровождается сменой `raft_id`, хотя `instance_id` может при этом переиспользоваться.
-
-_Бутстрап кластера_ — бутстрап первого инстанса + [присоединение](#joining) некоторого количества других. 
-
-_Бутстрап репликасета_ — бутстрап лидера репликасета + присоединение к нему реплик.
-
-### Присоединение (joining) инстанса к кластеру <a name="joining"></a>
-_Присоединение инстанса_ близко по смыслу к [бутстрапу](#bootstrap), но делает акцент на процессах, происходящих в самом кластере. Чтобы инстанс мог присоединиться, другие (уже существующие) члены кластера должны сначала сохранить информацию о нем в raft-журнал.
-
-### Репликация (replication) <a name="replication"></a>
-**Репликация** — один из механизмов [актуализации](#actualization) данных между инстансами. В Picodata существует два вида репликации: Tarantool (внутри [репликасета](#replicaset)) и Raft (глобальная на весь кластер). Под термином репликация обычно имеют в виду пересылку записей журналов (`wal` или `raft` в зависимости от того, о каком виде репликации идет речь).
-
-### Актуализация (catch-up) инстанса <a name="actualization"></a>
-Актуализация — это по сути синхронизация данных между инстансами. Существует два механизма актуализации: посредством [репликации](#replication) журнала (catch-up by log replication), и посредством применения [снапшота](#snapshot) (catch-up by snapshot).
-
-Актуализация снапшотом поддерживается только для Raft, но не для Tarantool. Она требуется, когда на raft-лидере отсутствуют нужные записи в raft-журнале. Если аналогичная ситуация происходит с WAL Tarantool, пользователю не остается выбора кроме как делать [ребутстрап](#bootstrap) инстанса.
-
-### Proc API
-
-**Proc API** — Stored Procedures API (хранимые процедуры). Хранимыми процедурам являются Rust-функции с аттрибутом `#[tarantool::proc]`. Процедуры могут быть вызваны с помощью любого тарантул-коннектора, в частности, с помощью Lua-модуля `net.box` или Rust-модуля `tarantool::network::client`. В Picodata хранимые процедуры используются для коммуникации между инстансами. 
-
-Примерами хранимых процедур в Picodata могут служить:
-- `.proc_cas`  (низкоуровневый вызов механизма [Compare and Swap](#cas) на выбранном инстансе);
-- `.proc_read_index` (получение текущего значения raft-индекса выбранного инстанса).
-
-## Общие концепции
-### Отказоустойчивость <a name="failsoft"></a>
-**Отказоустойчивость** — свойство кластера сохранять наличие и доступность данных при выходе из строя части узлов. В Picodata отказоустойчивость обеспечивается репликацией и грамотным проектированием алгоритмов.
-
-### Горизонтальное масштабирование <a name="sharding"></a>
-**Горизонтальное масштабирование** (оно же сегментирование или шардирование, sharding) — подход, предполагающий разделение данных на сегменты (бакеты, buckets), которые могут храниться на отдельных репликасетах кластера. С точки зрения набора хранимых данных, каждый репликасет называется шардом. Деление на шарды — это еще один вариант логического деления кластера, но без привязки к серверам, на которых выполняются инстансы.
-
-### Линеаризуемость <a name="linearizability"></a>
-В контексте распределенных баз данных **линеаризуемость** обозначает свойство хранилища обеспечивать целостность и согласованность данных на разных репликах БД. Линеаризуемость в Picodata обеспечивается алгоритмом консенсуса Raft, который обновляет данные на мастер-реплике только после того, как они записаны на резервные реплики.
-
-
-В схеме данных кластера для каждого шардированного спейса (таблицы) задается параметр распределения — _ключ шардирования_, состоящий из одной или нескольких колонок. Пример:
-
-```
-sharding_key:
-    - id
-    - name
-```
-### Уровень изоляции транзакций <a name="isolation"></a>
-Уровень изоляции транзакций является одним из компонентов ACID (_atomicity, consistency, isolation, durability_), который представляет собой набор требований к СУБД согласно стандарту [ANSI/ISO SQL](https://en.wikipedia.org/wiki/ISO/IEC_9075). Уровень изоляции транзакций определяет степень строгости, которую СУБД применяет к возможной несогласованности данных при исполнении нескольких транзакций одновременно. Различают следующие уровни (по мере повышения строгости и усиления блокировок):
-
-- **Read uncommitted**. Низший уровень изоляции, допускающий чтение незафиксированных данных. В результат чтения могут попасть данные от других, еще не завершившихся операций записи.
-- **Read committed.** Чтение уже зафиксированных данных. Данный уровень гарантирует, что в момент чтения данные были ранее зафиксированы, однако позволяет изменять данные сразу после этого. Т.е. повторное чтение внутри транзакции уже не гарантирует получение такого же набора данных.
-- **Repeatable read**. Повторяемое чтение данных, при которых нельзя изменять данные до тех пор, пока читающая их транзакция не завершилась.
-- **Serializable**. Наивысший уровень изоляции, предполагающий полное упорядочивание (сериализацию) транзакций. Результат выполнения нескольких параллельных транзакций должен быть таким, как если бы они выполнялись последовательно.
-
-### Read phenomena (проблемы чтения данных)
-Уровни изоляции транзакций существуют для учета и решения следующих проблем, возникающих при одновременном (параллельном) чтении данных:
-
-- **Lost update** (потерянное обновление). При одновременном изменении данных разными транзакциями теряются все изменения, кроме последнего.
-- **Dirty read** (неточное чтение). В результат чтения добавятся данные, привнесенные другой транзакцией, которая впоследствие будет отменена (не получит статуса committed).
-- **Non-repeatable read** (проблема однократного чтения). Несколько последовательных операций чтения одних и тех же данных дают разный результат, т.к. между ними вклинилась сторонняя операция записи.
-- **Phantom read** (фантомное чтение). Проблема схожа с предыдущей и также касается изменения данных после начала операции чтения. Однако, “фантомное чтение” предполагает изменение самой выборки (параллельная операция записи добавляет/удаляет строки).
-
-
diff --git a/docs/sharding.md b/docs/sharding.md
deleted file mode 100644
index 39061f1fd6ab8890cb370874cb70ace1e3aeb525..0000000000000000000000000000000000000000
--- a/docs/sharding.md
+++ /dev/null
@@ -1,68 +0,0 @@
-# Шардирование данных в кластере
-
-В данном разделе рассматривается пример шардирования данных в кластере Picodata.
-
-1. Запустим кластер из двух экземпляров
-
-    ```sh
-    picodata run --data-dir tmp/i1 --listen localhost:3301 --instance-id i1 --peer localhost:3301,localhost:3302
-    picodata run --data-dir tmp/i2 --listen localhost:3302 --instance-id i2 --peer localhost:3301,localhost:3302
-    ```
-
-1. Создадим шардированную таблицу. На любом инстансе выполним команды
-
-    ```lua
-    pico.add_migration(1, 'create table t2(a int, "bucket_id" unsigned, primary key (a));')
-    pico.add_migration(2, 'create index "bucket_id" on t2 ("bucket_id");')
-    pico.migrate(2)
-    ```
-
-    Ключевым моментом является создание индекса `bucket_id` в спейсе
-    (его наличие помечает спейс как шардированный). Важно не забыть
-    кавычки, т.к. vshard ожидает увидеть его в нижнем регистре.
-
-    На текущий момент в Picodata используется предопределенное количество бакетов - 3000.
-
-1. Заполним шардированный спейс тестовыми данными. На любом инстансе
-   выполним команды.
-
-    ```lua
-    for i=1,3000 do vshard.router.callrw(i, 'box.space.T2:insert', {{i, i}}) end
-    ```
-
-1. Проверим, что данные поровну распределились между экземплярами. На
-   каждом из них (`i1`, `i2`) выполним запрос:
-
-    ```lua
-    box.space.T2:len()
-    ```
-
-    В результате мы получим по 1500 бакетов (и столько же таплов) на
-    каждом экземпляре:
-
-    ```yaml
-    ---
-    - 1500
-    ...
-    ```
-
-1. Добавим еще один экземпляр
-
-    ```sh
-    picodata run --data-dir tmp/i3 --listen localhost:3303 --instance-id i3 --peer localhost:3301,localhost:3302
-    ```
-
-1. Проверим, что данные перераспределились между тремя экземплярами. На
-   каждом из них (`i1`, `i2` и `i3`) выполним запрос:
-
-    ```lua
-    box.space.T2:len()
-    ```
-
-    В результате мы получим по 1000 бакетов на каждом экземпляре:
-
-    ```yaml
-    ---
-    - 1000
-    ...
-    ```
diff --git a/docs/topology.md b/docs/topology.md
deleted file mode 100644
index 276455362399b832fa64ec8d89404674221b7e22..0000000000000000000000000000000000000000
--- a/docs/topology.md
+++ /dev/null
@@ -1,247 +0,0 @@
-# Топология кластера Picodata
-
-В данном документе рассматриваются различные сценарии работы с кластером. Все они основаны на одном и том же принципе: запуске и объединении отдельных экземпляров Picodata в распределенный кластер. При этом сложность развертывания и поддержания работоспособности кластера зависит только от сложности его топологии.
-
-[TOC]
-
----
-
-## Минимальный вариант кластера
-
-Picodata может создать кластер, состоящий всего из одного экземпляра/инстанса. Обязательных параметров у него нет, что позволяет свести запуск к выполнению всего одной простой команды:
-
-```
-picodata run
-```
-
-Можно добавлять сколько угодно последующих инcтансов — все они будут подключаться к этому кластеру. Каждому интансу следует задать отдельную рабочую директорию (параметр `--data-dir`), а также указать адрес и порт для приема соединений (параметр `--listen`) в формате `<HOST>:<PORT>`. Фактор репликации по умолчанию равен 1 — каждый инстанс образует отдельный репликасет. Если для `--listen` указать только порт, то будет использован IP-адрес по умолчанию (127.0.0.1):
-
-```
-picodata run --data-dir i1 --listen :3301
-picodata run --data-dir i2 --listen :3302
-picodata run --data-dir i3 --listen :3303
-```
-
-## Кластер на нескольких серверах
-
-Выше был показан запуск Picodata на одном сервере, что удобно для тестирования и отладки, но не отражает сценариев полноценного использования кластера. Поэтому пора запустить Picodata на нескольких серверах. Предположим, что их два: `192.168.0.1` и `192.168.0.2`. Порядок запуска будет следующим:
-
-На `192.168.0.1`:
-```shell
-picodata run --listen 192.168.0.1:3301
-```
-
-На `192.168.0.2`:
-```shell
-picodata run --listen 192.168.0.2:3301 --peer 192.168.0.1:3301
-```
-
-На что нужно обратить внимание:
-
-Во-первых, для параметра `--listen` вместо стандартного значения `127.0.0.1` надо указать конкретный адрес. Формат адреса допускает упрощения — можно указать только хост `192.168.0.1` (порт по умолчанию `:3301`), или только порт, но для наглядности лучше использовать полный формат `<HOST>:<PORT>`.
-
-Значение параметра `--listen` не хранится в кластерной конфигурации и может меняться при перезапуске инстанса.
-
-Во-вторых, надо дать инстансам возможность обнаружить друг друга для того чтобы механизм [discovery](discovery.md) правильно собрал все найденные экземпляры Picodata в один кластер. Для этого в параметре `--peer` нужно указать адрес какого-либо соседнего инстанса. По умолчанию значение параметра `--peer` установлено в `127.0.0.1:3301`. Параметр `--peer` не влияет больше ни на что, кроме механизма обнаружения других инстансов.
-
-Параметр `--advertise` используется для установки публичного IP-адреса и порта инстанса. Параметр сообщает, по какому адресу остальные инстансы должны обращаться к текущему. По умолчанию он равен `--listen`, поэтому в примере выше не упоминается. Но, например, в случае `--listen 0.0.0.0` его придется указать явно:
-
-```shell
-picodata run --listen 0.0.0.0:3301 --advertise 192.168.0.1:3301
-```
-
-Значение параметра `--advertise` анонсируется кластеру при запуске инстанса. Его можно поменять при перезапуске инстанса или в процессе его работы командой `picodata set-advertise`.
-
-## Питомцы против стада
-
-Чтобы проще было отличать инстансы друг от друга, им можно давать имена:
-
-```
-picodata run --instance-id barsik
-```
-
-Если имя не дать, то оно будет сгенерировано автоматически в момент добавления в кластер. Имя инстанса задается один раз и не может быть изменено в дальнейшем (например, оно постоянно сохраняется в снапшотах инстанса). В кластере нельзя иметь два инстанса с одинаковым именем — второй инстанс сразу после запуска получит ошибку при добавлении в кластер. Тем не менее, имя можно повторно использовать если предварительно исключить первый инстанс с таким именем из кластера. Это делается командой `picodata expel barsik`.
-
-## Группы и роли
-
-До сих пор рассматриваемый кластер был гомогенным. Все инстансы были одинаковы по функциональности — хранили данные, обрабатывали запросы. В промышленной эксплуатации эти роли почти всегда требуется разделять, чтобы эффективнее использовать ресурсы оборудования. Под хранение выделяются серверы с большим объемом памяти, для обработки запросов это не требуется.
-
-В Picodata для этих целей служит понятие групп инстансов. Принадлежность инстанса той или иной группе задается при добавлении в кластер параметром `--group` и впоследствии не может быть изменена. По умолчанию кластер состоит из одной группы "common".
-
-Функциональность инстансов определяется набором ролей. На данный момент существует две роли:
-
-- storage — позволяет хранить шардированные данные на инстансе.
-- router — реализует логику доступа к шардированным данным.
-
-По умолчанию инстанс исполняет обе роли одновременно, но его можно ограничить явным указанием одной из них:
-
-```
-picodata run --role storage
-picodata run --role router
-```
-
-Важно то, что обе эти роли относятся только к шардированию. Так, отключение роли storage ничем не мешает хранить данные локально.
-
-Также инстанс можно запустить без ролей вовсе, в результате чего он будет функционировать исключительно как не-шардированное локальное хранилище:
-
-```
-picodata run --no-role
-```
-
-Все инстансы в группе имеют одинаковый набор ролей и одинаковый фактор репликации.
-
-## Репликация и зоны доступности (failure domains)
-
-Количество инстансов в репликасете определяется значением переменной `replication_factor`. Внутри группы инстансов используется один и тот же `replication_factor`.
-
-Для ее инициализации служит параметр `--init-replication-factor`. Этот параметр играет роль только в момент создания группы (добавления первого инстанса). В этот момент значение из аргументов командной строки записывается в конфигурацию кластера. В дальнейшем значение параметра `--init-replication-factor` игнорируется.
-
-Отредактировать фактор репликации, сохраненный в конфигурации кластера, можно командой `picodata set-replication-factor`. Редактирование конфигурации сказывается только на вновь добавляемых инстансах, но не затрагивает уже работающие.
-
-По мере усложнения топологии возникает еще один вопрос — как не допустить объединения в репликасет инстансов из одного и того же датацентра. Для этого введен параметр `--failure-domain` — _зона доступности_, отражающая признак физического размещения сервера, на котором выполняется инстанс Picodata. Это может быть как датацентр, так и какое-либо другое обозначение расположения: регион (например, `eu-east`), стойка, сервер, или собственное обозначение (blue, green, yellow). Ниже показан пример запуска инстанса Picodata с указанием зоны доступности:
-
-```
-picodata run --init-replication-factor 2 --failure-domain region=us,zone=us-west-1
-```
-
-Добавление инстанса в репликасет происходит по следующим правилам:
-
-- Если в каком-либо репликасете количество инстансов меньше необходимого фактора репликации, то новый инстанс добавляется в него при условии, что их параметры `--failure-domain` отличаются (регистр символов не учитывается).
-- Если подходящих репликасетов нет, то Picodata создает новый репликасет.
-
-Параметр `--failure-domain` играет роль только в момент добавления инстанса в кластер. **Принадлежность инстанса репликасету впоследствии не меняется**.
-
-Как и параметр `--advertise`, значение параметра`--failure-domain` каждого инстанса можно редактировать:
-
-- Либо перезапустив инстанс с новыми параметрами.
-- Либо в процессе его работы командой `picodata set-failure-domain`.
-
-Добавляемый инстанс должен обладать тем же набором параметров, которые уже есть в кластере. Например, инстанс `dc=msk` не сможет присоединиться к кластеру с `--failure-domain region=eu/us` и вернет ошибку.
-
-Как было указано выше, сравнение зон доступности производится без учета
-регистра символов, поэтому, к примеру, два инстанса с аргументами
-`--failure-domain region=us` и `--failure-domain REGION=US` будут относиться
-к одному региону и, следовательно, не попадут в один репликасет (исключения
-описаны ниже).
-
-## Кейс: два датацентра по две реплики
-
-Picodata старается не объединять в один репликасет инстансы, у которых совпадает хотя бы один домен. Но иногда это все же необходимо. Чтобы ограничить Picodata в бесконечном создании репликасетов, можно воспользоваться флагом `--max-replicaset-count` (по умолчанию `inf`).
-
-Как и `--init-replication-factor`, параметр `--max-replicaset-count` может быть разным для разных групп.
-
-Как и другие параметры, `--max-replicaset-count` редактируется в любой момент:
-
-- При добавлении нового инстанса
-- В процессе его работы командой `picodata set-max-replicaset-count`
-
-Важно учитывать, что параметр `--max-replicaset-count` нельзя сделать меньше существующего количества репликасетов.
-
-## Файлы конфигурации
-
-Существует три способа передать Picodata параметры конфигурации. Они приведены ниже в порядке возрастания приоритета:
-
-1. Файл конфигурации (yaml / toml)
-2. Переменные окружения `PICODATA_<PARAM>=<VALUE>`
-3. Аргументы командной строки `--param value`
-
-Мы перечислили достаточно много разнобразных параметров, некоторые из которых делают команду запуска достаточно длинной. Вместо отдельных команд можно использовать файл конифгурации. Пример:
-
-<h5 a><strong><code>storage.toml</code></strong></h5>
-
-```toml
-group = "storages"
-max-replicaset-count = 30
-replication-factor = 4
-roles = ["storage"]
-```
-
-<h5 a><strong><code>storage.toml</code></strong></h5>
-
-```toml
-group = "routers"
-roles = ["router"]
-```
-
-Пример запуска кластера Picodata c использованием файла конфигурации:
-
-```
-picodata run --cfg storage.toml --listen :3301
-picodata run --cfg router.toml --listen :3302
-```
-
-## Динамическое переключение голосующих узлов в Raft (Raft voter failover)
-
-Все узлы Raft в кластере делятся на два типа: голосующие (`voter`) и неголосующие (`learner`). За консистентность Raft-группы отвечают только узлы первого типа. Для коммита каждой транзакции требуется собрать кворум из `N/2 + 1` из голосующих узлов. Неголосующие узлы в кворуме не участвуют.
-
-Чтобы сохранить баланс между надежностью кластера и удобством его эксплуатации, в Picodata предусмотрена удобная функция — динамическое переключение типа узлов. Если один из голосующих узлов становится недоступен или прекращает работу (что может нарушить кворум в Raft), то тип `voter` автоматически присваивается одному из доступных неголосующих узлов. Переключение происходит незаметно для пользователя.
-
-Количество голосующих узлов в кластере не настраивается и зависит только от общего количества инстансов. Если инстансов 1 или 2, то голосующий узел один. Если инстансов 3 или 4, то таких узлов три. Для кластеров с 5 или более инстансами — пять голосующих узлов.
-
-## Configuration reference
-
-> `--cfg <path>`
-: Read configuration parameters from file (toml / yaml).
-*env*: `PICODATA_CFG`
-*default*: *none*
-
-`--data-dir`
-: Here the instance persists all of its data.
-*env*: `PICODATA_DATA_DIR`
-*default*: `.`
-
-`--listen`
-: Socket bind address.
-*env*: `PICODATA_LISTEN`
-*default*: `localhost:3301`
-
-`--peer <[host][:port],...>`
-: Address of other instance(s).
-*env*: `PICODATA_PEER`
-*default*: `localhost:3301`
-
-`--advertise <[host][:port]>`
-: Address the other instances should use to connect to this instance.
-*env*: `PICODATA_ADVERTISE`
-*default*: `%listen%`
-
-`--cluster-id <name>`
-: Name of the cluster. The instance will refuse to join the cluster with a different name.
-*env*: `PICODATA_CLUSTER_ID`
-*default*: `demo`
-
-`--instance-id <name>`
-: Name of the instance.
-*env*: `PICODATA_INSTANCE_ID`
-*default*: `i%raft_id%`, e.g. `i1`, `i42`, etc.
-
-`--failure-domain <key=value,...>`
-: Comma-separated list describing physical location of the server. Each domain is a key-value pair. Until max replicaset count is reached, picodata will avoid putting two instances into the same replicaset if at least one key of their failure domains has the same value. Instead, new replicasets will be created. Replicasets will be populated with instances from different failure domains until the desired replication factor is reached.
-*env*: `PICODATA_FAILURE_DOMAIN`
-*default*: *none*
-
-`--group <name>`
-: Name of the instance group. It's an error to run instance with a group changed.
-*env*: `PICODATA_GROUP`
-*default*: `default`
-
-`--role <name,...>`
-: Valid roles are `"storage"` and `"router"`.
-*env*: `PICODATA_ROLE`
-*default*: `storage,router`
-
-`--init-replication-factor <number>`
-: Total number of replicas (copies of data) for each replicaset in the current group. It's only accounted upon the group creation (adding the first instance in the group), and ignored aftwerwards.
-*env*: `PICODATA_INIT_REPLICATION_FACTOR`
-*default*: `1`
-
-`--init-storage-weight <number>`
-: Proportional capacity of current instance. Common for each instance in the current group. Only valid for instances with "storage" role enabled.
-*env*: `PICODATA_INIT_STORAGE_WEIGHT`
-*default*: `1`
-
-`--max-replicaset-count`
-: Maximum number of replicasets in the current group.
-*env*: `PICODATA_MAX_REPLICASET_COUNT`
-*default*: don't modify
-:hammer_and_wrench: Если меньше текущего размера группы, то игнорируется. Если в текущей группе нет места, то ошибка. Если больше — настройка применяется к текущей группе репликасетов.