- Что такое снимки и где их найти
- Как проявляется проблема
- Возможные стратегии восстановления и что означает каждая из них
Обзор снимков Keeper
Что такое снимок?
Снимок — это сериализованное состояние внутренних данных Keeper (таких как метаданные о кластерах, путях координации таблиц и конфигурациях) на определённый момент времени. Снимки крайне важны для повторной синхронизации узлов Keeper в кластере, восстановления метаданных при сбоях, а также для процессов запуска и перезапуска, которым требуется заведомо корректное состояние Keeper.Где найти снимки?
Снимки хранятся в виде файлов в локальной файловой системе узлов Keeper. По умолчанию они находятся в/var/lib/clickhouse/coordination/snapshots/ либо по пользовательскому пути, заданному параметром snapshot_storage_path в файле keeper_server.xml. Снимки именуются последовательно (например, snapshot.23): чем новее снимок, тем больше его номер.
В многоузловых кластерах у каждого узла Keeper есть свой каталог снимков.
Для восстановления критически важно, чтобы снимки на разных узлах были согласованными.
Основные симптомы и проявления поврежденных снимков Keeper
В таблице ниже перечислены некоторые распространенные симптомы и проявления поврежденных снимков Keeper:
Признаки в журналах:
Прежде чем диагностировать повреждение снимка, проверьте журналы Keeper на наличие характерных шаблонов ошибок:
Восстановление после повреждения снимков Keeper
Прежде чем работать с какими-либо файлами, обязательно:- Остановите все узлы Keeper, чтобы предотвратить дальнейшее повреждение данных
- Сделайте резервную копию всего содержимого, скопировав весь каталог coordination в безопасное место
- Проверьте кворум кластера, чтобы убедиться, что хотя бы на одном узле сохранились корректные данные
- Восстановление из существующей резервной копии
Используйте этот способ, если:
- Повреждение метаданных Keeper или снимков делает текущие данные невосстановимыми.
- Существует резервная копия с заведомо корректным состоянием Keeper.
- Найдите и проверьте самую новую резервную копию на согласованность метаданных.
- Остановите сервисы ClickHouse и Keeper.
- Замените повреждённые снимки и журналы версиями из каталога резервной копии.
- Перезапустите кластер Keeper и проверьте синхронизацию метаданных.
- Откат к более старому снимку
Используйте этот процесс в следующих случаях:
- Недавние снимки повреждены, но более старые всё ещё пригодны к использованию.
- Инкрементальные журналы не повреждены, что позволяет выполнить согласованное восстановление.
- Найдите и выберите корректный старый снимок (например, snapshot.19) в каталоге Keeper.
- Удалите более новые снимки и журналы.
- Перезапустите Keeper, чтобы он заново воспроизвёл журналы и восстановил состояние метаданных.
- Восстановление метаданных с помощью
SYSTEM RESTORE REPLICA
Следуйте этому процессу, если:
SYSTEM RESTORE REPLICA- метаданные Keeper утрачены или повреждены, но данные таблицы по-прежнему есть на диске
- таблицы перешли в режим только для чтения из-за отсутствия метаданных ZooKeeper/Keeper
- вам нужно заново создать метаданные в Keeper на основе локально доступных частей данных
-
Убедитесь, что данные таблицы локально присутствуют в пути к данным вашего clickhouse-server, заданном параметром
<path>в конфигурации. (по умолчанию/var/lib/clickhouse/data/) - Для каждой затронутой таблицы выполните:
- Для восстановления на уровне базы данных (если используется движок базы данных Replicated):
- Дождитесь завершения синхронизации:
- Проверьте восстановление: убедитесь, что в
system.replicasзначениеis_readonly = 0, и следите заsystem.detached_parts
Как это работает
SYSTEM RESTORE REPLICA отсоединяет все существующие части, заново создает метаданные в Keeper (как будто это новая пустая таблица), а затем снова присоединяет все части. Это позволяет избежать повторной загрузки данных по сети.
- Удаление и повторное создание метаданных реплики в Keeper
Используйте этот порядок действий, если:
- Ошибка возникает только на одной реплике кластера, и её метаданные в Keeper повреждены или несогласованы
- Вы сталкиваетесь с ошибками вида “Part XXXXX intersects previous part YYYYY”
- Вам нужно полностью сбросить метаданные реплики в Keeper, сохранив локальные данные
- На затронутой реплике отсоедините таблицу:
- Удалите метаданные реплики из Keeper (выполните на любой реплике):
- Повторно выполните ATTACH таблицы (она будет в режиме только для чтения):
- Восстановите метаданные реплики:
- Синхронизируйтесь с другими репликами:
- Проверьте
system.detached_partsна всех репликах после восстановления
- Остановите сервер ClickHouse
- Создайте флаг восстановления:
- Запустите сервер ClickHouse
- Сервер автоматически удалит флаг и восстановит все реплицированные таблицы
- Следите за ходом восстановления в журналах
- Пересборка кластера Keeper
Используйте этот процесс в следующих случаях:
- Для восстановления недоступны пригодные снимки, Log или резервные копии.
- Необходимо заново создать весь кластер Keeper и его метаданные.
- Полностью остановите кластеры ClickHouse и Keeper.
- Сбросьте каждый узел Keeper, очистив каталоги снимков и Log.
- Инициализируйте один узел Keeper в качестве лидера и постепенно добавляйте остальные узлы.
- Повторно импортируйте метаданные, если они доступны из внешних записей.
- Удаление осиротевших узлов из снимка при запуске
Осиротевший узел — это узел, родительский узел которого отсутствует в снимке. Keeper отказывается загружать такой
снимок и записывает в Log сообщение Failure to load from latest snapshot with index.
Используйте этот способ, только если:
- снимок повреждён именно таким образом и
- нет ни корректной резервной копии, ни более старого снимка (если применимы стратегии 1 и 2, лучше воспользоваться ими).
<keeper_server> и перезапустите узел:
Требуется хранилище узлов в памятиОчистка реализована только для хранилища узлов в памяти. Если в
<coordination_settings> включён use_lsmt_storage, Keeper не запустится при установленном remove_orphaned_nodes_on_startup: отключите
use_lsmt_storage на время восстановительного перезапуска, а после успешного запуска включите его снова.WARNING
двумя строками: в первой указываются общее число удалённых узлов и корни удалённых осиротевших
поддеревьев, во второй — отсутствующие в снимке пути, которые ограничивают повреждённую область. Потомки
этих корней также удаляются, но по отдельности не перечисляются.
Проверив конец локального Log, Keeper до запуска Raft записывает исправленное дерево в новый файл снимка с тем же
индексом Log. Результаты завершённых исправлений имеют приоритет над более старыми копиями с этим индексом,
поэтому прерванное восстановление можно продолжить, не выбирая повреждённый снимок. Новые узлы-follower получают
исправленный снимок, а при последующих перезапусках
включать удаление осиротевших узлов больше не требуется. Исходный снимок и все копии с тем же индексом сохраняются
с префиксом имени файла orphaned_; эти файлы не используются при загрузке снимков и не удаляются автоматически
по сроку хранения. Сохраните их для диагностики, а когда они станут не нужны, удалите вручную.
Для восстановительного перезапуска требуется дополнительное место на диске под исправленный снимок и резервную копию исходного.
Если не удаётся записать исправленный снимок, синхронизировать изменения в локальном каталоге или сохранить исходные файлы,
Keeper отказывается запускаться. При следующем запуске прерванная архивация будет завершена.
Keeper намеренно отказывается запускаться, если локальная запись в Log после снимка ссылается на повреждённую
область: на удалённый узел, на что-либо ниже него или на непосредственного родителя удалённого поддерева. Непосредственный родитель
считается конфликтом, поскольку набор его дочерних узлов больше не соответствует дереву, для которого был записан Log,
поэтому даже запись, затрагивающая только его, — в том числе создание или удаление соседнего узла под ним, которое
обновляет его восстановленные счётчики дочерних узлов, — может воспроизвестись иначе. Записи, которые проверяют только
существование родителя, его версию или идентификаторы изменений, например Check, CheckNotExists, CheckStat, не сравнивающий ни numChildren, ни cversion,
Set или SetACL, перезаписывающие только собственные данные или ACL родителя, а также
наблюдения за данными, дочерними узлами и существованием, которые клиент повторно регистрирует после переподключения, на это не влияют и не
блокируют восстановление; постоянные наблюдения, повторно регистрируемые клиентом, вообще не обращаются к дереву и никогда не блокируют восстановление.
Узлы выше по цепочке не
затрагиваются: у них ровно те же данные, версия и дочерние узлы, что и на исправном peer-узле, поэтому запись, которая
затрагивает только такой узел, воспроизводится идентично и не блокирует восстановление. Исключение составляют записи, которые
обходят всё поддерево ниже своего пути, например рекурсивное удаление или рекурсивное получение списка узлов: они
видят удалённые узлы и конфликтуют на любом уровне, если только Keeper не отклонит запрос до обращения
к дереву (например, рекурсивное удаление /). То же относится к закрытию сеанса
(Close) в конце Log, если этому сеансу принадлежал удалённый эфемерный узел или принадлежит сохранившийся эфемерный
узел непосредственно под таким родителем: при закрытии сеанса удаляются его эфемерные узлы и обновляются счётчики их
родителей. Воспроизведение любой такой записи на
восстановленном дереве незаметно привело бы к другому состоянию. В этом случае восстановите узел с исправного
peer-узла: остановите его, очистите его каталог coordination и дайте ему заново синхронизироваться с лидером либо воспользуйтесь
стратегией 1 или 2.