Реплика отстала настолько, что лидер уже удалил нужные записи журнала. Как снимок состояния позволяет безопасно вернуть её в рабочий кластер?
Лидер передаёт реплике согласованный снимок состояния вместе с позицией и термином последней включённой записи. Реплика атомарно устанавливает снимок, удаляет несовместимый локальный хвост и затем применяет записи журнала, появившиеся после позиции снимка. Без проверки метаданных, целостности и актуальности такой перенос может привести к потере подтверждённых данных или к присоединению устаревшего состояния.
Репликация через журнал удобна, пока отставшая реплика может получить все пропущенные записи. Однако журналы обычно периодически архивируются или удаляются, иначе их размер и стоимость хранения постоянно растут.
Снимки появились как способ ограничить объём журнала и ускорить восстановление реплик. Вместо передачи всей истории лидер передаёт компактное состояние на определённой позиции, а журнал используется только для небольшого хвоста после этой позиции.
Пусть реплика остановилась на позиции 100, а лидер уже сократил журнал и хранит записи только начиная с позиции 10 000. Простое продолжение репликации невозможно: у лидера нет данных, которыми можно заполнить промежуток между этими позициями.
Нельзя также безусловно скопировать текущие файлы лидера. Состояние могло быть снято в процессе изменения, относиться к другой версии журнала или содержать данные, не соответствующие выбранной позиции. Ошибка приводит к расхождению реплик, чтению несуществующего состояния или нарушению гарантий консенсуса.
Лидер формирует снимок из согласованного состояния и фиксирует его метаданные: индекс последней включённой записи, термин или версию журнала, контрольную сумму и, если применимо, конфигурацию кластера. Эти данные связывают снимок с конкретной точкой истории.
Перед установкой реплика проверяет, что снимок целостен и относится к допустимой версии журнала. Обычно он принимается частями, временно записывается в отдельное место и после успешной проверки переключается атомарно. Это защищает от сбоя или обрыва сети во время передачи.
После установки реплика считает все записи до позиции снимка уже применёнными. Записи после этой позиции лидер передаёт обычным журналом. Если локальный журнал реплики содержит конфликтующий хвост, он отбрасывается: источником истины для выбранной истории является согласованный снимок и последующий журнал лидера.
Снимок должен отражать не только прикладные данные, но и необходимые метаданные репликации. В системах с консенсусом особенно важны позиция и термин, а также информация о конфигурации участников, если она влияет на безопасность дальнейшего голосования.
Снимок ускоряет восстановление, но не устраняет сетевые и дисковые риски. Передача большого снимка создаёт нагрузку на сеть и диск, а его создание может конкурировать с обычной обработкой запросов. Поэтому применяют инкрементальные снимки, дедупликацию, ограничение скорости передачи или заранее подготовленные копии, если это совместимо с моделью согласованности.
Нельзя считать снимок доказательством того, что реплика актуальна в текущий момент. Он лишь восстанавливает её до определённой позиции; для достижения текущего состояния требуется применить хвост журнала и пройти обычный протокол подтверждения.
Реплика хранилища была недоступна несколько часов. За это время лидер выполнил ротацию журнала, поэтому восстановление по отдельным записям стало невозможным.
Рассматривались три варианта. Хранить журнал до возвращения любой реплики просто, но требует неограниченного или трудно прогнозируемого объёма диска. Полностью копировать базу данных надёжно с точки зрения полноты, однако это создаёт большую нагрузку и увеличивает время восстановления. Передать согласованный снимок, а затем короткий хвост журнала быстрее и дешевле, но требует корректной атомарной установки и проверки версии.
Выбрали третий вариант. Лидер сформировал снимок с позицией журнала и контрольной суммой, реплика проверила его, переключила локальное состояние атомарно и догнала оставшиеся записи. В результате восстановление заняло время передачи снимка и небольшого хвоста, а не время повторной доставки всей истории.
Это зависит от реализации, но безопасное переключение должно быть логически атомарным. Пока снимок загружается, реплика может продолжать обслуживать старое состояние или временно не принимать запросы; нельзя допустить, чтобы читатели увидели смесь старых и новых частей снимка.
Практический вариант — записать снимок во временное хранилище, проверить его целостность, затем выполнить короткое переключение корня состояния. Если данные распределены по нескольким файлам или шардам, атомарность нужна на уровне всего согласованного набора, а не каждого файла отдельно.
Реплика не должна считать восстановление завершённым только потому, что снимок корректен. Она должна продолжить работу по актуальному протоколу репликации: проверить, что снимок совместим с историей нового лидера, и получить записи после позиции снимка.
Если новый лидер подтверждает ту же историю, передаётся соответствующий хвост. Если история расходится, локальные записи после снимка удаляются и применяются записи новой принятой истории. Сам снимок остаётся полезной базовой точкой, но дальнейшее состояние определяется текущим протоколом согласования.
Контрольная сумма показывает целостность переданных байтов, но не доказывает, что снимок относится к правильной истории. Повреждённый или устаревший, но целый снимок может быть внутренне корректным и при этом несовместимым с текущим журналом.
Поэтому проверяют одновременно целостность, индекс, термин или другую версию журнала, а также правила совместимости конфигурации. Без такой привязки реплика может принять старое состояние и ошибочно продолжить его как часть актуальной истории.