Запуск сервера с репликацией
В дополнение к процессу восстановления, описанному в разделе Процесс восстановления, сервер должен выполнить дополнительные шаги и принять меры предосторожности, если включена репликация.
Как и ранее, процедура запуска инициируется запросом box.cfg{}. Одним
из параметров box.cfg может быть
replication, который задаёт источник(и)
репликации. Эту реплику, запускаемую с помощью box.cfg, мы будем
называть «локальной» репликой, чтобы отличать её от других реплик в
наборе реплик, которые мы будем называть «удалёнными» репликами.
Если файл снимка .snap отсутствует и параметр replication пуст и
cfg.read_only=false:
тогда локальная реплика считает себя
нереплицируемым «автономным» экземпляром или первой репликой нового
набора реплик. Она сгенерирует новые UUID для себя и для набора реплик.
UUID реплики хранится в спейсе _cluster; UUID набора реплик хранится в
спейсе _schema. Поскольку снимок содержит все данные во всех спейсах,
снимок локальной реплики будет содержать UUID реплики и UUID набора
реплик. Следовательно, при последующих перезапусках локальная реплика
сможет восстановить эти UUID при чтении файла .snap.
Если файл снимка .snap отсутствует и параметр replication пуст и
cfg.read_only=true:
реплика не может быть первой репликой нового
набора реплик, поскольку первая реплика должна быть ведущей. Поэтому
возникнет сообщение об ошибке: ER_BOOTSTRAP_READONLY. Чтобы избежать
этого, измените настройку для этого (локального) экземпляра на
read_only = false или убедитесь, что другой (удалённый) экземпляр
запускается первым и содержит UUID локального экземпляра в своём спейсе
_cluster. В последнем случае, если ошибка ER_BOOTSTRAP_READONLY всё
ещё возникает, увеличьте значение
box.replication_connect_timeout
для локального экземпляра.
Если файл снимка .snap отсутствует и параметр replication не пуст и
спейс _cluster не содержит других UUID реплик:
тогда локальная
реплика считает, что она не является автономным экземпляром, но ещё не
входит в набор реплик. Теперь она должна присоединиться к набору реплик.
Она отправит свой UUID реплики первой удалённой реплике, указанной в
replication, которая будет действовать как ведущая. Это называется
«запросом на присоединение» (join request). Когда удалённая реплика
получает запрос на присоединение, она отправляет обратно:
- UUID набора реплик удалённой реплики,
- содержимое файла .snap удалённой реплики. Когда локальная реплика
получает эту информацию, она помещает UUID набора реплик в свой спейс
_schema, помещает UUID удалённой реплики и информацию о подключении в свой спейс_clusterи создаёт снимок, содержащий все данные, отправленные удалённой репликой. Затем, если у локальной реплики есть данные в WAL-файлах .xlog, она отправляет эти данные удалённой реплике. Удалённая реплика получает их, обновляет свою копию данных и добавляет UUID локальной реплики в свой спейс_cluster.
Если файл снимка .snap отсутствует и параметр replication не пуст и
спейс _cluster содержит другие UUID реплик:
тогда локальная
реплика считает, что она не является автономным экземпляром и уже входит
в набор реплик. Она отправит свой UUID реплики и UUID набора реплик всем
удалённым репликам, указанным в replication. Это называется
«рукопожатием при подключении» (on-connect handshake). Когда удалённая
реплика получает рукопожатие при подключении:
- удалённая реплика сравнивает свою копию UUID набора реплик с UUID из рукопожатия при подключении. Если они не совпадают, рукопожатие завершается неудачей и на локальной реплике отображается ошибка.
- удалённая реплика ищет запись о подключающемся экземпляре в своём
спейсе
_cluster. Если записи нет, рукопожатие завершается неудачей. В противном случае рукопожатие успешно. Удалённая реплика считывает новую информацию из своих файлов .snap и .xlog и отправляет новые запросы локальной реплике.
В результате локальная реплика знает, к какому набору реплик она принадлежит, удалённая реплика знает, что локальная реплика является членом набора реплик, и обе реплики имеют одинаковое содержимое базы данных.
Если файл снимка существует и источник репликации не пуст:
сначала
локальная реплика проходит процесс восстановления, описанный в
предыдущем разделе, используя собственные файлы .snap и .xlog. Затем она
отправляет запрос «subscribe» всем остальным репликам набора реплик.
Запрос subscribe содержит векторные часы сервера. Векторные часы
содержат набор пар «server id, lsn» для каждой реплики в системном
спейсе _cluster. Каждая удалённая реплика, получив запрос subscribe,
считывает запросы из своих файлов .xlog и отправляет их локальной
реплике, если (lsn запроса из файла .xlog) больше (lsn из векторных
часов в запросе subscribe). После того как все остальные реплики набора
реплик ответили на запрос subscribe локальной реплики, запуск реплики
завершён.
Следующие временные ограничения действовали для версий Tarantool ранее 1.7.7:
- URI в параметре
replicationдолжны быть в одинаковом порядке на всех репликах. Это не обязательно, но способствует согласованности. - Реплики набора реплик должны запускаться в немного разное время. Это не обязательно, но предотвращает ситуацию, когда каждая реплика ожидает готовности другой реплики.
Следующее ограничение по-прежнему действует для текущей версии Tarantool:
- Максимальное количество записей в спейсе
_cluster– 32. Кортежи для устаревших реплик не используются повторно автоматически, поэтому при достижении ограничения в 32 реплики может потребоваться реорганизовать спейс_clusterвручную.