- O que são snapshots e onde encontrá-los
- Como o problema se manifesta
- Possíveis estratégias de recuperação e o que cada uma significa
Visão geral dos snapshots do Keeper
O que é um snapshot?
Um snapshot é um estado serializado dos dados internos do Keeper (como metadados sobre clusters, caminhos de coordenação de tabelas e configurações) em um ponto específico no tempo. Snapshots são essenciais para ressincronizar nós do Keeper em um cluster, recuperar metadados durante falhas e dar suporte a processos de inicialização ou reinicialização que dependem de um estado conhecido e íntegro do Keeper.Onde posso encontrar snapshots?
Os snapshots são armazenados como arquivos no sistema de arquivos local dos nós do Keeper. Por padrão, eles ficam em/var/lib/clickhouse/coordination/snapshots/ ou no caminho personalizado definido por snapshot_storage_path no arquivo keeper_server.xml. Os snapshots são nomeados sequencialmente (por exemplo, snapshot.23), e os mais recentes têm números maiores.
Em clusters com vários nós, cada nó do Keeper tem seu próprio diretório de snapshots.
A consistência dos snapshots entre os nós é fundamental para a recuperação.
Principais sintomas e manifestações de snapshots corrompidos do Keeper
A tabela abaixo detalha alguns sintomas e manifestações comuns de snapshots corrompidos do Keeper:
Indicadores nos logs:
Antes de diagnosticar corrupção de snapshot, verifique os logs do Keeper em busca de padrões de erro específicos:
Recuperando snapshots corrompidos do Keeper
Antes de alterar qualquer arquivo, sempre:- Pare todos os nós do Keeper para evitar mais corrupção
- Faça backup de tudo copiando todo o diretório de coordenação para um local seguro
- Verifique o quorum do cluster para garantir que pelo menos um nó tenha dados íntegros
- Restaurar a partir de um backup existente
Você deve seguir este processo se:
- A corrupção dos metadados do Keeper ou dos snapshots tornar os dados atuais irrecuperáveis.
- Houver um backup com um estado íntegro e conhecido do Keeper.
- Localize e valide o backup mais recente quanto à consistência dos metadados.
- Desligue os serviços do ClickHouse e do Keeper.
- Substitua os snapshots e logs com falha pelos do diretório de backup.
- Reinicie o cluster do Keeper e valide a sincronização dos metadados.
- Reverter para um snapshot mais antigo
Você deve seguir este processo quando:
- Snapshots recentes estiverem corrompidos, mas os mais antigos ainda puderem ser usados.
- Os logs incrementais estiverem íntegros para uma recuperação consistente.
- Identifique e selecione um snapshot válido mais antigo (por exemplo, snapshot.19) no diretório do Keeper.
- Remova os snapshots e logs mais recentes.
- Reinicie o Keeper para que ele reaplique os logs e reconstrua o estado dos metadados.
- Restaure os metadados usando
SYSTEM RESTORE REPLICA
Você deve seguir este processo quando:
SYSTEM RESTORE REPLICA- Os metadados do Keeper forem perdidos ou corrompidos, mas os dados da tabela ainda existirem em disco
- As tabelas tiverem passado para o modo somente leitura devido à ausência de metadados do ZooKeeper/Keeper
- Você precisar recriar os metadados no Keeper com base nas partes de dados disponíveis localmente
-
Verifique se os dados da tabela existem localmente no caminho de dados do
clickhouse-server, definido por<path>na config. (/var/lib/clickhouse/data/por padrão) - Para cada tabela afetada, execute:
- Para recuperação no nível do banco de dados (se estiver usando o mecanismo de banco de dados Replicated):
- Aguarde a sincronização ser concluída:
- Verifique a recuperação conferindo
system.replicasparais_readonly = 0e monitorandosystem.detached_parts
Como funciona
SYSTEM RESTORE REPLICA desanexa todas as partes existentes, recria os metadados no Keeper (como se fosse uma nova tabela vazia) e, em seguida, anexa novamente todas as partes. Isso evita baixar os dados novamente pela rede.
- Remover e recriar os metadados da réplica no Keeper
Você deve seguir este processo quando:
- O erro ocorre em uma única réplica do cluster e há metadados corrompidos ou inconsistentes no Keeper
- Você encontrar erros como “Part XXXXX intersects previous part YYYYY”
- Você precisa redefinir completamente os metadados da réplica no Keeper, preservando os dados locais
- Na réplica afetada, desanexe a tabela:
- Remova os metadados da réplica do Keeper (execute em qualquer réplica):
- Anexe novamente a tabela (ela ficará em modo somente leitura):
- Restaure os metadados da réplica:
- Sincronize-se com as outras réplicas:
- Verifique
system.detached_partsem todas as réplicas após a recuperação
- Pare o servidor ClickHouse
- Crie a flag de recuperação:
- Inicie o servidor ClickHouse
- O servidor removerá automaticamente a flag e restaurará todas as tabelas replicadas
- Monitore os logs para acompanhar o progresso da recuperação
- Reconstruir o cluster do Keeper
Você deve seguir este processo quando:
- Não houver snapshots, logs ou backups válidos disponíveis para recuperação.
- For necessário recriar todo o cluster do Keeper e seus metadados.
- Pare completamente os clusters do ClickHouse e do Keeper.
- Redefina cada nó do Keeper limpando os diretórios de snapshot e log.
- Inicialize um nó do Keeper como líder e adicione os outros nós de forma incremental.
- Reimporte os metadados, se estiverem disponíveis em registros externos.
- Remover nós órfãos do snapshot na inicialização
Um nó órfão é um nó cujo pai não está presente no snapshot. O Keeper se recusa a carregar esse
snapshot e registra no log Failure to load from latest snapshot with index.
Siga este procedimento quando:
- O snapshot estiver estruturalmente danificado exatamente dessa forma e
- Não houver nenhum backup válido ou snapshot mais antigo disponível (as estratégias 1 e 2 são preferíveis sempre que forem aplicáveis).
<keeper_server> e reinicie o nó:
Requer o armazenamento de nós em memóriaA limpeza só é implementada pelo armazenamento de nós em memória. Se
use_lsmt_storage estiver habilitado em
<coordination_settings>, o Keeper se recusa a iniciar com remove_orphaned_nodes_on_startup definido: desative
use_lsmt_storage para a reinicialização de recuperação e habilite-o novamente após uma inicialização bem-sucedida.WARNING
em duas linhas: uma com o número total de nós removidos e as raízes das subárvores órfãs removidas,
e outra com os caminhos ausentes do snapshot que delimitam a região danificada. Os descendentes
abaixo dessas raízes também são removidos, mas não são listados individualmente.
Após verificar o final do log local, o Keeper grava a árvore reparada em um novo arquivo de snapshot no mesmo
índice de log antes de iniciar o Raft. Reparos concluídos têm precedência sobre cópias mais antigas nesse índice,
de modo que uma recuperação interrompida pode ser retomada sem selecionar o snapshot danificado. Novos seguidores recebem
o snapshot reparado, e as reinicializações seguintes
não precisam mais da remoção de órfãos habilitada. O snapshot original e quaisquer cópias do mesmo índice são preservados
com o prefixo orphaned_ no nome do arquivo; esses arquivos são ignorados no carregamento de snapshots e na retenção
automática. Mantenha-os para diagnóstico e remova-os manualmente quando não forem mais necessários. A
reinicialização de recuperação exige espaço em disco adicional para o snapshot reparado e para o backup do original.
Se a gravação do snapshot reparado, a sincronização das alterações no diretório local ou a preservação dos originais
falhar, o Keeper se recusa a iniciar. Uma inicialização posterior conclui qualquer arquivamento interrompido.
O Keeper se recusa propositalmente a iniciar se uma entrada de log local acima do snapshot fizer referência à região
danificada: um nó removido, qualquer coisa abaixo dele ou o pai direto de uma subárvore removida. O pai direto
conta como conflito porque seu conjunto de filhos não corresponde mais à árvore sobre a qual o log foi gravado,
de modo que mesmo uma entrada que apenas o afete — incluindo a criação ou remoção de um nó irmão sob ele, o que
atualiza seus contadores de filhos reparados — poderia ser reaplicada de forma diferente. Entradas que consultam apenas a
existência, a versão ou os ids de modificação do pai, como um Check, um CheckNotExists, um CheckStat que não compara numChildren nem cversion,
um Set ou SetACL que reescreve apenas os próprios dados ou a ACL do pai, ou
os watches de dados, de filhos e de existência que um cliente registra novamente após uma reconexão, não são afetadas e não
bloqueiam a recuperação; watches persistentes registrados novamente por um cliente nunca consultam a árvore e nunca a bloqueiam.
Os nós mais acima na cadeia não são
afetados: eles mantêm exatamente os mesmos dados, versão e filhos que têm em um peer saudável, portanto uma entrada que
afete apenas um desses nós é reaplicada de forma idêntica e não bloqueia a recuperação. A exceção é uma entrada que
percorre toda a subárvore abaixo do seu caminho, como uma remoção recursiva ou uma listagem recursiva: essas entradas de fato
enxergam os nós removidos e entram em conflito em qualquer nível, a menos que o Keeper rejeite a requisição antes de consultar
a árvore (por exemplo, uma remoção recursiva de /). O mesmo vale para o encerramento de uma sessão
(Close) no final do log quando essa sessão possuía um nó efêmero removido, ou possui um nó efêmero
remanescente diretamente sob esse pai: encerrar a sessão remove seus nós efêmeros e atualiza os
contadores dos respectivos pais. Reaplicar qualquer uma dessas entradas sobre a
árvore reparada produziria silenciosamente um estado diferente. Nesse caso, recupere o nó a partir de um peer
saudável: pare-o, limpe seu diretório de coordenação e deixe-o ressincronizar a partir do líder, ou use
a estratégia 1 ou 2.