No ClickHouse Cloud, a replicação é gerenciada para você. Crie suas tabelas sem adicionar argumentos. Por exemplo, no texto abaixo, você substituiria:por:
- ReplicatedSummingMergeTree
- ReplicatedCoalescingMergeTree
- ReplicatedVersionedCollapsingMergeTree
- ReplicatedCollapsingMergeTree
- ReplicatedGraphiteMergeTree
- ReplicatedMergeTree
- ReplicatedReplacingMergeTree
- ReplicatedAggregatingMergeTree
INSERT e ALTER são replicados (para mais informações, consulte a documentação de ALTER.
As consultas CREATE, DROP, ATTACH, DETACH e RENAME são executadas em um único servidor e não são replicadas:
- A consulta
CREATE TABLEcria uma nova tabela replicável no servidor em que é executada. Se essa tabela já existir em outros servidores, ela adiciona uma nova réplica. - A consulta
DROP TABLEexclui a réplica localizada no servidor em que a consulta é executada. - A consulta
RENAMErenomeia a tabela em uma das réplicas. Em outras palavras, tabelas replicadas podem ter nomes diferentes em réplicas diferentes.
Não deixe de configurar a segurança. O ClickHouse oferece suporte ao esquema ACL
digest do subsistema de segurança do ZooKeeper.SELECT, porque a replicação não afeta o desempenho de SELECT, e as consultas são executadas tão rapidamente quanto em tabelas não replicadas. Ao consultar tabelas replicadas distribuídas, o comportamento do ClickHouse é controlado pelas configurações max_replica_delay_for_distributed_queries e fallback_to_stale_replicas_for_distributed_queries.
Para cada consulta INSERT, aproximadamente dez entradas são adicionadas ao ZooKeeper por meio de várias transações. (Mais precisamente, isso ocorre para cada bloco de dados inserido; uma consulta INSERT contém um bloco, ou um bloco a cada max_insert_block_size = 1048576 linhas.) Isso resulta em latências um pouco maiores para INSERT em comparação com tabelas não replicadas. Mas, se você seguir a recomendação de inserir dados em batches de no máximo um INSERT por segundo, isso não causará problemas. Todo o cluster ClickHouse usado para coordenar um cluster ZooKeeper tem, no total, várias centenas de INSERTs por segundo. A taxa de transferência nas inserções de dados (o número de linhas por segundo) é tão alta quanto a de dados não replicados.
Para clusters muito grandes, você pode usar diferentes clusters ZooKeeper para diferentes shards. No entanto, com base em nossa experiência, isso não se mostrou necessário em clusters de produção com aproximadamente 300 servidores.
A replicação é assíncrona e multi-master. Consultas INSERT (assim como ALTER) podem ser enviadas para qualquer servidor disponível. Os dados são inseridos no servidor em que a consulta é executada e, em seguida, copiados para os outros servidores. Como ela é assíncrona, os dados inseridos recentemente aparecem nas outras réplicas com alguma latência. Se parte das réplicas não estiver disponível, os dados serão gravados quando elas voltarem a ficar disponíveis. Se uma réplica estiver disponível, a latência será o tempo necessário para transferir o bloco de dados comprimidos pela rede. O número de threads que executam tarefas em segundo plano para tabelas replicadas pode ser definido pela configuração background_schedule_pool_size.
O motor ReplicatedMergeTree usa um pool de threads separado para fetches replicados. O tamanho do pool é limitado pela configuração background_fetches_pool_size, que pode ser ajustada com uma reinicialização do servidor.
Por padrão, uma consulta INSERT aguarda a confirmação da gravação dos dados de apenas uma réplica. Se os dados tiverem sido gravados com sucesso em apenas uma réplica e o servidor com essa réplica deixar de existir, os dados armazenados serão perdidos. Para habilitar a confirmação da gravação de dados por várias réplicas, use a opção insert_quorum.
Cada bloco de dados é gravado atomicamente. A consulta INSERT é dividida em blocos de até max_insert_block_size = 1048576 linhas. Em outras palavras, se a consulta INSERT tiver menos de 1048576 linhas, ela será executada atomicamente.
Blocos de dados são desduplicados. Em várias gravações do mesmo bloco de dados (blocos de dados do mesmo tamanho contendo as mesmas linhas na mesma ordem), o bloco é gravado apenas uma vez. O motivo é que, em caso de falhas de rede, a aplicação cliente pode não saber se os dados foram gravados no DB, então a consulta INSERT pode simplesmente ser repetida. Não importa para qual réplica os INSERTs foram enviados com dados idênticos. INSERTs são idempotentes. Os parâmetros de desduplicação são controlados pelas configurações de servidor merge_tree.
Durante a replicação, apenas os dados de origem a serem inseridos são transferidos pela rede. A transformação posterior dos dados (merging) é coordenada e executada da mesma forma em todas as réplicas. Isso minimiza o uso da rede, o que significa que a replicação funciona bem quando as réplicas ficam em diferentes datacenters. (Observe que duplicar dados em diferentes datacenters é o principal objetivo da replicação.)
Você pode ter qualquer número de réplicas dos mesmos dados. Com base em nossa experiência, uma solução relativamente confiável e conveniente pode usar replicação dupla em produção, com cada servidor usando RAID-5 ou RAID-6 (e RAID-10 em alguns casos).
O sistema monitora a sincronização dos dados nas réplicas e é capaz de se recuperar após uma falha. O failover é automático (para pequenas diferenças nos dados) ou semiautomático (quando os dados diferem demais, o que pode indicar um erro de configuração).
Criando tabelas replicadas
No ClickHouse Cloud, a replicação é gerenciada automaticamente.Crie tabelas usando
MergeTree sem argumentos de replicação. Internamente, o sistema converte MergeTree em SharedMergeTree para fins de replicação e distribuição de dados.Evite usar ReplicatedMergeTree ou especificar parâmetros de replicação, pois ela é gerenciada pela plataforma.Parâmetros do Replicated*MergeTree
Exemplo:
{}. Os valores substituídos são obtidos na seção macros do arquivo de configuração.
Exemplo:
/clickhouse/tables/ é o prefixo comum. Recomendamos usar exatamente este.
{shard} será expandido para o identificador do shard.
table_name é o nome do nó da tabela no ClickHouse Keeper. É uma boa ideia que ele seja o mesmo que o nome da tabela. Ele é definido explicitamente porque, ao contrário do nome da tabela, não muda após uma consulta RENAME.
DICA: você também pode adicionar um nome de banco de dados antes de table_name. Por exemplo, db_name.table_name
As duas substituições internas {database} e {table} podem ser usadas; elas se expandem, respectivamente, para o nome da tabela e o nome do banco de dados (a menos que essas macros estejam definidas na seção macros). Portanto, o caminho do ZooKeeper pode ser especificado como '/clickhouse/tables/{shard}/{database}/{table}'.
Tenha cuidado ao renomear tabelas ao usar essas substituições internas. O caminho no ClickHouse Keeper não pode ser alterado e, quando a tabela é renomeada, as macros serão expandidas para um caminho diferente; a tabela passará a apontar para um caminho que não existe no ClickHouse Keeper e entrará em modo somente leitura.
O nome da réplica identifica diferentes réplicas da mesma tabela. Você pode usar o nome do servidor para isso, como no exemplo. O nome só precisa ser único dentro de cada shard.
Você pode definir os parâmetros explicitamente em vez de usar substituições. Isso pode ser conveniente para testes e para configurar clusters pequenos. No entanto, nesse caso, você não pode usar consultas DDL distribuídas (ON CLUSTER).
Ao trabalhar com clusters grandes, recomendamos usar substituições porque elas reduzem a probabilidade de erro.
Você pode especificar argumentos padrão para o motor de tabela Replicated no arquivo de configuração do servidor. Por exemplo:
CREATE TABLE em cada réplica. Essa consulta cria uma nova tabela replicada ou adiciona uma nova réplica a uma tabela já existente.
Se você adicionar uma nova réplica depois que a tabela já contiver dados em outras réplicas, os dados serão copiados das outras réplicas para a nova após a execução da consulta. Em outras palavras, a nova réplica se sincroniza com as demais.
Para excluir uma réplica, execute DROP TABLE. No entanto, apenas uma réplica é excluída — aquela que está no servidor em que você executa a consulta.
Recuperação após falhas
INSERT, ou se ocorrer um erro ao interagir com o ClickHouse Keeper, será gerada uma exceção.
Depois de se conectar ao ClickHouse Keeper, o sistema verifica se o conjunto de dados no sistema de arquivos local corresponde ao conjunto esperado de dados (o ClickHouse Keeper armazena essas informações). Se houver pequenas inconsistências, o sistema as corrige sincronizando os dados com as réplicas.
Se o sistema detectar partes de dados corrompidas (com tamanho de arquivo incorreto) ou partes não reconhecidas (partes gravadas no sistema de arquivos, mas não registradas no ClickHouse Keeper), ele as move para o subdiretório detached (elas não são excluídas). Quaisquer partes ausentes são copiadas das réplicas.
Observe que o ClickHouse não executa nenhuma ação destrutiva, como excluir automaticamente uma grande quantidade de dados.
Quando o servidor é iniciado (ou estabelece uma nova sessão com o ClickHouse Keeper), ele verifica apenas a quantidade e os tamanhos de todos os arquivos. Se os tamanhos dos arquivos corresponderem, mas alguns bytes tiverem sido alterados em algum ponto no meio, isso não será detectado imediatamente, mas apenas ao tentar ler os dados para uma consulta SELECT. A consulta gera uma exceção informando que há incompatibilidade de checksum ou no tamanho de um bloco comprimido. Nesse caso, as partes de dados são adicionadas à fila de verificação e copiadas das réplicas, se necessário.
Se o conjunto local de dados diferir demais do esperado, um mecanismo de segurança é acionado. O servidor registra isso no log e se recusa a iniciar. O motivo é que esse caso pode indicar um erro de configuração, por exemplo, se uma réplica em um shard tiver sido configurada acidentalmente como uma réplica em outro shard. No entanto, os limites desse mecanismo são definidos em um nível relativamente baixo, e essa situação pode ocorrer durante a recuperação normal após falhas. Nesse caso, os dados são restaurados de forma semiautomática — “apertando um botão”.
Para iniciar a recuperação, crie o nó /path_to_table/replica_name/flags/force_restore_data no ClickHouse Keeper com qualquer conteúdo ou execute o comando para restaurar todas as tabelas replicadas:
Recuperação após perda completa dos dados
- Instale o ClickHouse no servidor. Defina corretamente as substituições no arquivo de config que contém o identificador do shard e as réplicas, se você as usar.
- Se você tinha tabelas não replicadas que precisam ser duplicadas manualmente nos servidores, copie os dados delas de uma réplica (no diretório
/var/lib/clickhouse/data/db_name/table_name/). - Copie as definições das tabelas localizadas em
/var/lib/clickhouse/metadata/de uma réplica. Se um identificador de shard ou de réplica estiver definido explicitamente nas definições das tabelas, corrija-o para que corresponda a esta réplica. (Como alternativa, inicie o servidor e execute todas as consultasATTACH TABLEque deveriam estar nos arquivos .sql em/var/lib/clickhouse/metadata/.) - Para iniciar a recuperação, crie o nó do ClickHouse Keeper
/path_to_table/replica_name/flags/force_restore_datacom qualquer conteúdo ou execute o comando para restaurar todas as tabelas replicadas:sudo -u clickhouse touch /var/lib/clickhouse/flags/force_restore_data
/path_to_table/replica_name) e, em seguida, criar a réplica novamente, conforme descrito em “Criando tabelas replicadas”.
Não há restrição de largura de banda da rede durante a recuperação. Tenha isso em mente se estiver restaurando muitas réplicas ao mesmo tempo.
Convertendo de MergeTree para ReplicatedMergeTree
MergeTree para nos referirmos a todos os motores de tabela da família MergeTree, da mesma forma que fazemos com ReplicatedMergeTree.
Se você tiver uma tabela MergeTree replicada manualmente, poderá convertê-la em uma tabela replicada. Isso pode ser necessário se você já tiver coletado uma grande quantidade de dados em uma tabela MergeTree e agora quiser habilitar a replicação.
A instrução ATTACH TABLE … AS REPLICATED permite anexar uma tabela MergeTree desanexada como ReplicatedMergeTree.
Uma tabela MergeTree pode ser convertida automaticamente na reinicialização do servidor se a flag convert_to_replicated estiver definida no diretório de dados da tabela (/store/xxx/xxxyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy/ para o banco de dados Atomic).
Crie um arquivo convert_to_replicated vazio, e a tabela será carregada como replicada na próxima reinicialização do servidor.
Esta consulta pode ser usada para obter o caminho dos dados da tabela. Se a tabela tiver vários caminhos de dados, você deverá usar o primeiro.
default_replica_path e default_replica_name.
Para criar uma tabela convertida em outras réplicas, será necessário especificar explicitamente o caminho dela no primeiro argumento do motor ReplicatedMergeTree. A consulta a seguir pode ser usada para obter esse caminho.
ReplicatedMergeTree com o nome antigo.
Mova os dados da tabela antiga para o subdiretório detached dentro do diretório com os dados da nova tabela (/var/lib/clickhouse/data/db_name/table_name/).
Em seguida, execute ALTER TABLE ATTACH PARTITION em uma das réplicas para adicionar essas partes de dados ao conjunto ativo.
Convertendo de ReplicatedMergeTree para MergeTree
ReplicatedMergeTree desanexada como MergeTree em um único servidor.
Outra maneira de fazer isso envolve reiniciar o servidor. Crie uma tabela MergeTree com um nome diferente. Mova todos os dados do diretório que contém os dados da tabela ReplicatedMergeTree para o diretório de dados da nova tabela. Em seguida, exclua a tabela ReplicatedMergeTree e reinicie o servidor.
Se você quiser remover uma tabela ReplicatedMergeTree sem iniciar o servidor:
- Exclua o arquivo
.sqlcorrespondente no diretório de metadados (/var/lib/clickhouse/metadata/). - Exclua o caminho correspondente no ClickHouse Keeper (
/path_to_table/replica_name).
MergeTree, mover os dados para o diretório dela e, em seguida, reiniciar o servidor.