O ClickHouse Keeper fornece o sistema de coordenação para a replicação de dados e a execução de consultas de DDL distribuído. O ClickHouse Keeper é compatível com o ZooKeeper.
Detalhes de implementação
O ZooKeeper é um dos primeiros sistemas de coordenação open-source amplamente conhecidos. Ele é implementado em Java e tem um modelo de dados simples e poderoso. O algoritmo de coordenação do ZooKeeper, ZooKeeper Atomic Broadcast (ZAB), não fornece garantias de linearizabilidade para leituras, porque cada nó do ZooKeeper atende às leituras localmente. Diferentemente do ZooKeeper, o ClickHouse Keeper é escrito em C++ e usa a implementação do algoritmo RAFT. Esse algoritmo permite linearizabilidade para leituras e escritas e tem várias implementações open-source em diferentes linguagens.
Por padrão, o ClickHouse Keeper fornece as mesmas garantias que o ZooKeeper: escritas linearizáveis e leituras não linearizáveis. Ele tem um protocolo cliente-servidor compatível, portanto qualquer cliente ZooKeeper padrão pode ser usado para interagir com o ClickHouse Keeper. Snapshots e logs têm um formato incompatível com o ZooKeeper, mas a ferramenta clickhouse-keeper-converter permite converter dados do ZooKeeper em snapshots do ClickHouse Keeper. O protocolo entre servidores no ClickHouse Keeper também é incompatível com o ZooKeeper, portanto um cluster misto de ZooKeeper / ClickHouse Keeper é impossível.
O ClickHouse Keeper oferece suporte a listas de controle de acesso (ACLs) da mesma forma que o ZooKeeper. O ClickHouse Keeper oferece suporte ao mesmo conjunto de permissões e tem os mesmos esquemas internos: world, auth e digest. O esquema de autenticação digest usa o par username:password; a senha é codificada em Base64.
Configuração
O ClickHouse Keeper pode ser usado como um substituto independente do ZooKeeper ou como uma parte interna do servidor ClickHouse. Em ambos os casos, a configuração usa praticamente o mesmo arquivo .xml.
Configurações do Keeper
A principal tag de configuração do ClickHouse Keeper é <keeper_server> e tem os seguintes parâmetros:
| Parâmetro | Descrição | Padrão |
|---|---|---|
tcp_port |
Porta para um cliente se conectar. | 2181 |
tcp_port_secure |
Porta segura para uma conexão SSL entre o cliente e o servidor Keeper. | - |
server_id |
ID exclusivo do servidor; cada participante do cluster ClickHouse Keeper deve ter um número exclusivo (1, 2, 3…). | - |
log_storage_path |
Caminho para os logs de coordenação; assim como no ZooKeeper, é melhor armazenar os logs em nós pouco sobrecarregados. | - |
snapshot_storage_path |
Caminho para os snapshots de coordenação. | - |
enable_reconfiguration |
Ativa a reconfiguração dinâmica do cluster via reconfig. |
False |
max_memory_usage_soft_limit |
Soft limit, em bytes, para o uso máximo de memória do Keeper. | max_memory_usage_soft_limit_ratio * physical_memory_amount |
max_memory_usage_soft_limit_ratio |
Se max_memory_usage_soft_limit não estiver definido ou estiver definido como zero, usaremos esse valor para definir o soft limit padrão. |
0.9 |
cgroups_memory_observer_wait_time |
Se max_memory_usage_soft_limit não estiver definido ou estiver definido como 0, usaremos esse intervalo para observar a quantidade de memória física. Quando essa quantidade mudar, recalcularemos o soft limit de memória do Keeper com base em max_memory_usage_soft_limit_ratio. |
15 |
http_control |
Configuração da interface de controle HTTP. | - |
digest_enabled |
Ativa a verificação de consistência de dados em tempo real. | True |
create_snapshot_on_exit |
Cria um snapshot durante o desligamento. | - |
hostname_checks_enabled |
Ativa verificações de consistência de hostname para a configuração do cluster (por exemplo, se localhost for usado com endpoints remotos). |
True |
four_letter_word_white_list |
Lista de permissões de comandos 4lw. | conf, cons, crst, envi, ruok, srst, srvr, stat, wchs, dirs, mntr, isro, rcvr, apiv, csnp, lgif, rqld, ydld |
enable_ipv6 |
Ativa o IPv6. | True |
Outros parâmetros comuns são herdados da configuração do servidor ClickHouse (listen_host, logger e assim por diante).
Configurações internas de coordenação
As configurações internas de coordenação ficam na seção <keeper_server>.<coordination_settings> e têm os seguintes parâmetros:
| Parâmetro | Descrição | Padrão |
|---|---|---|
operation_timeout_ms |
Tempo limite para uma única operação do cliente (ms) | 10000 |
min_session_timeout_ms |
Tempo limite mínimo da sessão do cliente (ms) | 10000 |
session_timeout_ms |
Tempo limite máximo da sessão do cliente (ms) | 100000 |
dead_session_check_period_ms |
Com que frequência o ClickHouse Keeper verifica sessões expiradas e as remove (ms) | 500 |
heart_beat_interval_ms |
Com que frequência um líder do ClickHouse Keeper envia heartbeats aos seguidores (ms) | 500 |
election_timeout_lower_bound_ms |
Se o seguidor não receber um heartbeat do líder dentro desse intervalo, ele pode iniciar uma eleição de líder. Deve ser menor ou igual a election_timeout_upper_bound_ms. O ideal é que não sejam iguais. |
1000 |
election_timeout_upper_bound_ms |
Se o seguidor não receber um heartbeat do líder dentro desse intervalo, ele deverá iniciar uma eleição de líder. | 2000 |
rotate_log_storage_interval |
Quantos registros de log armazenar em um único arquivo. | 100000 |
reserved_log_items |
Quantos registros de log de coordenação armazenar antes da compactação. | 100000 |
snapshot_distance |
Com que frequência o ClickHouse Keeper criará novos snapshots (em número de registros nos logs). | 100000 |
snapshots_to_keep |
Quantos snapshots manter. | 3 |
stale_log_gap |
Limite a partir do qual o líder considera o seguidor desatualizado e envia o snapshot para ele em vez dos logs. | 10000 |
fresh_log_gap |
Quando o nó passa a ser considerado atualizado. | 200 |
max_requests_batch_size |
Tamanho máximo do batch em número de requisições antes de ser enviado ao RAFT. | 100 |
force_sync |
Chama fsync a cada gravação no log de coordenação. |
true |
quorum_reads |
Executa requisições de leitura como gravações em todo o consenso RAFT, com velocidade semelhante. | false |
raft_logs_level |
Nível de logging em texto sobre coordenação (trace, debug etc.). | system default |
auto_forwarding |
Permite encaminhar requisições de gravação dos seguidores para o líder. | true |
shutdown_timeout |
Aguarda a conclusão das conexões internas e o desligamento (ms). | 5000 |
startup_timeout |
Se o servidor não se conectar aos outros participantes do quórum dentro do tempo limite especificado, ele será encerrado (ms). | 30000 |
async_replication |
Habilita a replicação assíncrona. Todas as garantias de gravação e leitura são preservadas, com melhor desempenho. Essa configuração fica desabilitada por padrão para não quebrar a compatibilidade com versões anteriores | false |
latest_logs_cache_size_threshold |
Tamanho total máximo do cache em memória das entradas de log mais recentes | 1GiB |
commit_logs_cache_size_threshold |
Descontinuado. Usado para log_readahead_commit_window_bytes caso essa configuração não esteja definida. |
- |
commit_logs_cache_entry_count_threshold |
Descontinuado, não tem efeito. Use log_readahead_commit_window_bytes em vez disso. |
- |
log_readahead_enabled |
Habilita a leitura antecipada decodificada por par para leituras de recuperação do changelog (replicação de seguidores). | false |
log_readahead_window_bytes |
Máximo de bytes de entradas decodificadas armazenadas em buffer por leitor de par. Deve ser pelo menos tão grande quanto um batch típico de append-entries. | 64MiB |
log_readahead_max_peer_readers |
Número máximo de leitores de leitura antecipada simultâneos por par. | 8 |
log_readahead_eviction_timeout_ms |
Tempo limite de inatividade após o qual um leitor de leitura antecipada por par inativo, ou o leitor de commit, é removido (uma ausência subsequente o recria). | 30000 |
log_readahead_pool_threads |
Número de threads no pool de threads dedicado à leitura antecipada. 0 deriva o valor de log_readahead_max_peer_readers. |
0 |
log_readahead_serve_wait_timeout_ms |
Tempo máximo de espera pelo preenchimento da leitura antecipada em segundo plano antes de recorrer a uma leitura direta. | 200 |
log_readahead_chunk_size |
Número de entradas de log decodificadas por fragmento na tarefa de preenchimento de pré-leitura. | 16 |
log_readahead_commit_window_bytes |
Tamanho total máximo das entradas de log decodificadas armazenadas em buffer à frente da thread de commit. 0 desabilita a pré-leitura de commit (o commit lê as entradas do disco uma a uma). |
500MiB |
log_startup_read_max_streams |
Número máximo de arquivos de changelog lidos simultaneamente durante a inicialização do Keeper. 0 = usa automaticamente o número de núcleos de CPU. 1 = usa a leitura de inicialização serial (pré-paralela). O paralelismo efetivo é limitado pelo número de arquivos de changelog que precisam ser lidos; considere reduzir esse valor em armazenamentos limitados por buscas (HDDs, volumes com IOPS limitadas). |
0 |
log_startup_read_buffer_size |
Tamanho do buffer de leitura por fluxo (bytes) usado ao ler changelogs durante a inicialização do Keeper. Deve ser maior que 0. O buffer também é limitado ao tamanho do arquivo. |
8MiB |
disk_move_retries_wait_ms |
Quanto tempo esperar entre retries após uma falha ocorrida enquanto um arquivo estava sendo movido entre discos | 1000 |
disk_move_retries_during_init |
Quantidade de retries após uma falha ocorrida enquanto um arquivo estava sendo movido entre discos durante a inicialização | 100 |
experimental_use_rocksdb |
Usa rocksdb como armazenamento backend | 0 |
A configuração de quórum está localizada na seção <keeper_server>.<raft_configuration> e contém a descrição dos servidores.
O único parâmetro para todo o quórum é secure, que habilita uma conexão criptografada para a comunicação entre os participantes do quórum. O parâmetro pode ser definido como true se uma conexão SSL for necessária para a comunicação interna entre os nós ou deixado sem especificação caso contrário.
Os principais parâmetros de cada <server> são:
id— Identificador do servidor em um quórum.hostname— Hostname em que este servidor está localizado.port— Porta na qual este servidor aceita conexões.can_become_leader— Defina comofalsepara configurar o servidor comolearner. Se omitido, o valor serátrue.
Exemplos de configuração de quórum com três nós podem ser encontrados nos testes de integração com o prefixo test_keeper_. Exemplo de configuração para o servidor #1:
<keeper_server>
<tcp_port>2181</tcp_port>
<server_id>1</server_id>
<log_storage_path>/var/lib/clickhouse/coordination/log</log_storage_path>
<snapshot_storage_path>/var/lib/clickhouse/coordination/snapshots</snapshot_storage_path>
<coordination_settings>
<operation_timeout_ms>10000</operation_timeout_ms>
<session_timeout_ms>30000</session_timeout_ms>
<raft_logs_level>trace</raft_logs_level>
</coordination_settings>
<raft_configuration>
<server>
<id>1</id>
<hostname>zoo1</hostname>
<port>9234</port>
</server>
<server>
<id>2</id>
<hostname>zoo2</hostname>
<port>9234</port>
</server>
<server>
<id>3</id>
<hostname>zoo3</hostname>
<port>9234</port>
</server>
</raft_configuration>
</keeper_server>Como executar
O ClickHouse Keeper vem incluído no pacote do servidor ClickHouse; basta adicionar a configuração de <keeper_server> ao seu /etc/your_path_to_config/clickhouse-server/config.xml e iniciar o servidor ClickHouse como de costume. Se você quiser executar o standalone ClickHouse Keeper, poderá iniciá-lo de forma semelhante com:
clickhouse-keeper --config /etc/your_path_to_config/config.xmlSe você não tiver o link simbólico (clickhouse-keeper), poderá criá-lo ou especificar keeper como argumento para clickhouse:
clickhouse keeper --config /etc/your_path_to_config/config.xmlComandos de quatro letras
O ClickHouse Keeper também oferece comandos 4lw que são praticamente os mesmos do ZooKeeper. Cada comando é composto por quatro letras, como mntr, stat etc. Há outros comandos interessantes: stat fornece informações gerais sobre o servidor e os clientes conectados, srvr fornece detalhes adicionais sobre o servidor, e cons fornece detalhes adicionais sobre as conexões.
Os comandos 4lw têm uma configuração de lista de permissões, four_letter_word_white_list, cujo valor padrão é conf,cons,crst,envi,ruok,srst,srvr,stat,wchs,dirs,mntr,isro,rcvr,apiv,csnp,lgif,rqld,ydld.
Você pode enviar os comandos ao ClickHouse Keeper via telnet ou nc, pela porta do cliente.
echo mntr | nc localhost 9181Abaixo estão os comandos 4lw detalhados:
ruok: Testa se o servidor está em execução sem apresentar erros. O servidor responderá comimokse estiver em execução. Caso contrário, não responderá de forma alguma. Uma respostaimoknão indica necessariamente que o servidor entrou no quórum, apenas que o processo do servidor está ativo e associado à porta de cliente especificada. Use "stat" para ver detalhes sobre o estado em relação ao quórum e informações sobre conexões de clientes.
imokmntr: Gera uma lista de variáveis que podem ser usadas para monitorar o estado de saúde do cluster.
zk_version v21.11.1.1-prestable-7a4a0b0edef0ad6e0aa662cd3b90c3f4acf796e7
zk_avg_latency 0
zk_max_latency 0
zk_min_latency 0
zk_packets_received 68
zk_packets_sent 68
zk_num_alive_connections 1
zk_outstanding_requests 0
zk_server_state leader
zk_znode_count 4
zk_watch_count 1
zk_ephemerals_count 0
zk_approximate_data_size 723
zk_open_file_descriptor_count 310
zk_max_file_descriptor_count 10240
zk_leader_uptime 1234
zk_sum_leader_unavailable_time 1234
zk_cnt_leader_unavailable_time 1
zk_sum_election_time 1234
zk_cnt_election_time 1
zk_followers 0
zk_synced_followers 0zk_sum_leader_unavailable_time, zk_cnt_leader_unavailable_time, zk_sum_election_time e zk_cnt_election_time são métricas cumulativas exclusivas do líder. Elas representam observações por servidor, não medições de disponibilidade de todo o cluster: o rastreamento começa quando esse servidor deixa de observar um líder ativo. Durante uma partição de rede, isso pode incluir o período em que um líder antigo permanece ativo em outra partição. As métricas de eleição registram apenas uma eleição bem-sucedida que ocorre após uma janela sem líder observada localmente; uma transferência de liderança que não expõe um estado sem líder amostrado não é contabilizada intencionalmente.
O Keeper amostra seu estado local de líder no NuRaft uma vez a cada heart_beat_interval_ms, mas nunca em intervalos menores que 100 milissegundos. Cada limite pode diferir dessa transição de estado local em até o intervalo efetivo, e janelas menores que esse intervalo podem não ser detectadas. O Keeper registra a conclusão da eleição local em BecomeLeader do NuRaft. srst zera todos os quatro valores.
A duração da janela mais recente observada localmente de cada tipo também é exportada para system.asynchronous_metrics como KeeperLastLeaderElectionTime e KeeperLastLeaderUnavailableTime, em milissegundos. KeeperLastLeaderElectionTime segue a mesma definição de janela sem líder que zk_sum_election_time. Ambas também são exclusivas do líder: um nó que não é o líder ativo ou que ainda não concluiu uma janela informa 0. srst as zera juntamente com os contadores cumulativos.
srvr: Lista todos os detalhes do servidor.
ClickHouse Keeper version: v21.11.1.1-prestable-7a4a0b0edef0ad6e0aa662cd3b90c3f4acf796e7
Latency min/avg/max: 0/0/0
Received: 2
Sent : 2
Connections: 1
Outstanding: 0
Zxid: 34
Mode: leader
Node count: 4stat: Exibe detalhes resumidos do servidor e dos clientes conectados.
ClickHouse Keeper version: v21.11.1.1-prestable-7a4a0b0edef0ad6e0aa662cd3b90c3f4acf796e7
Clients:
192.168.1.1:52852(recved=0,sent=0)
192.168.1.1:52042(recved=24,sent=48)
Latency min/avg/max: 0/0/0
Received: 4
Sent : 4
Connections: 1
Outstanding: 0
Zxid: 36
Mode: leader
Node count: 4srst: Zera as estatísticas do servidor. O comando afetará o resultado desrvr,mntrestat.
Server stats reset.conf: Exibe detalhes sobre a configuração de serviço.
server_id=1
tcp_port=2181
four_letter_word_white_list=*
log_storage_path=./coordination/logs
snapshot_storage_path=./coordination/snapshots
max_requests_batch_size=100
session_timeout_ms=30000
operation_timeout_ms=10000
dead_session_check_period_ms=500
heart_beat_interval_ms=500
election_timeout_lower_bound_ms=1000
election_timeout_upper_bound_ms=2000
reserved_log_items=1000000000000000
snapshot_distance=10000
auto_forwarding=true
shutdown_timeout=5000
startup_timeout=240000
raft_logs_level=information
snapshots_to_keep=3
rotate_log_storage_interval=100000
stale_log_gap=10000
fresh_log_gap=200
max_requests_batch_size=100
quorum_reads=false
force_sync=false
compress_logs=true
compress_snapshots_with_zstd_format=true
configuration_change_tries_count=20cons: Liste os detalhes completos de conexão/sessão de todos os clientes conectados a este servidor. Inclui informações como o número de pacotes recebidos/enviados, ID da sessão, latências das operações, última operação executada etc…
192.168.1.1:52163(recved=0,sent=0,sid=0xffffffffffffffff,lop=NA,est=1636454787393,to=30000,lzxid=0xffffffffffffffff,lresp=0,llat=0,minlat=0,avglat=0,maxlat=0)
192.168.1.1:52042(recved=9,sent=18,sid=0x0000000000000001,lop=List,est=1636454739887,to=30000,lcxid=0x0000000000000005,lzxid=0x0000000000000005,lresp=1636454739892,llat=0,minlat=0,avglat=0,maxlat=0)crst: Zera as estatísticas de conexão/sessão de todas as conexões.
Connection stats reset.envi: Exibe detalhes sobre o ambiente do servidor
Environment:
clickhouse.keeper.version=v21.11.1.1-prestable-7a4a0b0edef0ad6e0aa662cd3b90c3f4acf796e7
host.name=ZBMAC-C02D4054M.local
os.name=Darwin
os.arch=x86_64
os.version=19.6.0
cpu.count=12
user.name=root
user.home=/Users/JackyWoo/
user.dir=/Users/JackyWoo/project/jd/clickhouse/cmake-build-debug/programs/
user.tmp=/var/folders/b4/smbq5mfj7578f2jzwn602tt40000gn/T/dirs: Mostra o tamanho total, em bytes, dos arquivos de snapshot e de log
snapshot_dir_size: 0
log_dir_size: 3875isro: Verifica se o servidor está em modo somente leitura. O servidor responderá comrose estiver em modo somente leitura ourwcaso contrário.
rwwchs: Exibe informações resumidas sobre os watches do servidor.
1 connections watching 1 paths
Total watches:1wchc: Lista informações detalhadas sobre watches do servidor, por sessão. Isso gera uma lista de sessões (conexões) com os watches (caminhos) associados. Observe que, dependendo do número de watches, essa operação pode ser custosa (afetar o desempenho do servidor); use-a com cuidado.
0x0000000000000001
/clickhouse/task_queue/ddlwchp: Lista informações detalhadas sobre watches do servidor, por caminho. A saída é uma lista de caminhos (znodes) com as sessões associadas. Observe que, dependendo do número de watches, essa operação pode ser custosa (ou seja, pode impactar o desempenho do servidor); use-a com cuidado.
/clickhouse/task_queue/ddl
0x0000000000000001dump: Lista as sessões em aberto e os nós efêmeros. Isso só funciona no nó líder.
Sessions dump (2):
0x0000000000000001
0x0000000000000002
Sessions with Ephemerals (1):
0x0000000000000001
/clickhouse/task_queue/ddlcsnp: Agenda uma tarefa de criação de snapshot. Em caso de sucesso, retorna o último índice do log confirmado do snapshot agendado; em caso de falha, retornaFailed to schedule snapshot creation task.. O comandolgifpode ajudar a determinar se o snapshot foi concluído.
100lgif: informações de log do Keeper.first_log_idx: meu primeiro índice de log no armazenamento de logs;first_log_term: meu primeiro termo do log;last_log_idx: meu último índice de log no armazenamento de logs;last_log_term: meu último termo do log;last_committed_log_idx: meu último índice de log confirmado na máquina de estado;leader_committed_log_idx: índice de log confirmado do líder, do meu ponto de vista;target_committed_log_idx: índice de log de destino que deve ser confirmado;last_snapshot_idx: o maior índice de log confirmado no último snapshot.
first_log_idx 1
first_log_term 1
last_log_idx 101
last_log_term 1
last_committed_log_idx 100
leader_committed_log_idx 101
target_committed_log_idx 101
last_snapshot_idx 50rqld: Solicita tornar-se o novo líder. RetornaSent leadership request to leader.se a solicitação for enviada ouFailed to send leadership request to leader.caso não seja enviada. Se o nó já for o líder, o resultado será o mesmo de quando a solicitação é enviada.
Sent leadership request to leader.ftfl: Lista todos os feature flags e informa se estão habilitados na instância do Keeper.
filtered_list 1
multi_read 1
check_not_exists 0ydld: Solicita a cessão da liderança e a transição para seguidor. Se o servidor que receber a solicitação for o líder, ele primeiro pausará as operações de escrita, aguardará até que o sucessor (o líder atual nunca pode ser o sucessor) conclua a sincronização do log mais recente e, então, renunciará à liderança. O sucessor será escolhido automaticamente. RetornaSent yield leadership request to leader.se a solicitação for enviada ouFailed to send yield leadership request to leader.se não for enviada. Se o nó já for um seguidor, o resultado será o mesmo de quando a solicitação é enviada.
Sent yield leadership request to leader.pfev: Retorna os valores de todos os eventos coletados. Para cada evento, retorna o nome, o valor e a descrição.
FileOpen 62 Number of files opened.
Seek 4 Number of times the 'lseek' function was called.
ReadBufferFromFileDescriptorRead 126 Number of reads (read/pread) from a file descriptor. Does not include sockets.
ReadBufferFromFileDescriptorReadFailed 0 Number of times the read (read/pread) from a file descriptor have failed.
ReadBufferFromFileDescriptorReadBytes 178846 Number of bytes read from file descriptors. If the file is compressed, this will show the compressed data size.
WriteBufferFromFileDescriptorWrite 7 Number of writes (write/pwrite) to a file descriptor. Does not include sockets.
WriteBufferFromFileDescriptorWriteFailed 0 Number of times the write (write/pwrite) to a file descriptor have failed.
WriteBufferFromFileDescriptorWriteBytes 153 Number of bytes written to file descriptors. If the file is compressed, this will show compressed data size.
FileSync 2 Number of times the F_FULLFSYNC/fsync/fdatasync function was called for files.
DirectorySync 0 Number of times the F_FULLFSYNC/fsync/fdatasync function was called for directories.
FileSyncElapsedMicroseconds 12756 Total time spent waiting for F_FULLFSYNC/fsync/fdatasync syscall for files.
DirectorySyncElapsedMicroseconds 0 Total time spent waiting for F_FULLFSYNC/fsync/fdatasync syscall for directories.
ReadCompressedBytes 0 Number of bytes (the number of bytes before decompression) read from compressed sources (files, network).
CompressedReadBufferBlocks 0 Number of compressed blocks (the blocks of data that are compressed independent of each other) read from compressed sources (files, network).
CompressedReadBufferBytes 0 Number of uncompressed bytes (the number of bytes after decompression) read from compressed sources (files, network).
AIOWrite 0 Number of writes with Linux or FreeBSD AIO interface
AIOWriteBytes 0 Number of bytes written with Linux or FreeBSD AIO interface
...Controle HTTP
O ClickHouse Keeper fornece uma interface HTTP para verificar se uma réplica está pronta para receber tráfego. Ela pode ser usada em ambientes de Cloud, como o Kubernetes.
Exemplo de configuração que habilita o endpoint /ready:
<clickhouse>
<keeper_server>
<http_control>
<port>9182</port>
<readiness>
<endpoint>/ready</endpoint>
</readiness>
</http_control>
</keeper_server>
</clickhouse>Feature flags
O Keeper é totalmente compatível com o ZooKeeper e seus clientes, mas também introduz alguns recursos e tipos de requisição exclusivos que podem ser usados pelo ClickHouse client.
Como esses recursos podem introduzir alterações incompatíveis com versões anteriores, a maioria deles vem desativada por padrão e pode ser ativada usando a configuração keeper_server.feature_flags.
Todos os recursos podem ser desativados explicitamente.
Se você quiser ativar um novo recurso no seu cluster do Keeper, recomendamos primeiro atualizar todas as instâncias do Keeper no cluster para uma versão que ofereça suporte ao recurso e só então ativar o próprio recurso.
Exemplo de configuração de feature flag que desativa multi_read e ativa check_not_exists:
<clickhouse>
<keeper_server>
<feature_flags>
<multi_read>0</multi_read>
<check_not_exists>1</check_not_exists>
</feature_flags>
</keeper_server>
</clickhouse>Os seguintes recursos estão disponíveis:
| Recurso | Descrição | Padrão |
|---|---|---|
multi_read |
Suporte para requisição de leitura múltipla | 1 |
filtered_list |
Suporte para requisição de listagem que filtra os resultados pelo tipo de nó (efêmero ou persistente) | 1 |
check_not_exists |
Suporte para a requisição CheckNotExists, que garante que o nó não exista |
1 |
create_if_not_exists |
Suporte para a requisição CreateIfNotExists, que tentará criar um nó caso ele não exista. Se ele já existir, nenhuma alteração será aplicada e ZOK será retornado |
1 |
remove_recursive |
Suporte para a requisição RemoveRecursive, que remove o nó junto com sua subárvore |
1 |
Migração do ZooKeeper
A migração sem interrupção do ZooKeeper para o ClickHouse Keeper não é possível. É preciso parar o cluster do ZooKeeper, converter os dados e iniciar o ClickHouse Keeper. A ferramenta clickhouse-keeper-converter converte logs e snapshots do ZooKeeper em um snapshot do ClickHouse Keeper. Ela requer o ZooKeeper 3.4 ou posterior.
Preparação para a migração
A migração exige interromper a ingestão de dados. Planeje uma janela de manutenção antes de começar.
Antes de parar o ZooKeeper, interrompa as tarefas em segundo plano do ClickHouse que modificam os metadados de coordenação. Por exemplo:
SYSTEM STOP MERGES;Registre as métricas de comparação antes da migração para poder verificar a consistência depois.
Etapas da migração
-
Interrompa a ingestão de dados em todos os nós do ClickHouse.
-
Interrompa todas as tarefas em segundo plano em todos os nós do ClickHouse (veja acima).
-
Interrompa todos os nós do ZooKeeper.
-
Opcional, mas recomendado: identifique o nó líder do ZooKeeper, inicie-o e interrompa-o novamente. Isso força o ZooKeeper a gravar um snapshot consistente em disco antes da conversão.
-
Execute
clickhouse-keeper-converterno nó líder. Se você tiver o binário completo do ClickHouse instalado, use o subcomandokeeper-converter(clickhouse keeper-converter). Se nenhum dos dois estiver disponível, baixe o binário.
clickhouse-keeper-converter \
--zookeeper-logs-dir /var/lib/zookeeper/version-2 \
--zookeeper-snapshots-dir /var/lib/zookeeper/version-2 \
--output-dir /path/to/clickhouse/keeper/snapshots-
Copie o snapshot para todos os nós do ClickHouse Keeper. O snapshot deve estar presente em todos os nós antes de qualquer um ser iniciado — se um nó for iniciado sem um snapshot, ele poderá se eleger líder com estado vazio.
-
Atualize a configuração do ClickHouse para apontar para o novo cluster do Keeper.
-
Inicie o ClickHouse Keeper em todos os nós e, em seguida, reinicie o ClickHouse.
-
Compare as métricas com sua linha de base pré-migração para verificar a consistência.
-
Retome as tarefas em segundo plano e reinicie a ingestão de dados.
Consolidando vários clusters do ZooKeeper
Se você usa vários clusters do ZooKeeper — por exemplo, um por grupo de shards — pode consolidá-los em um único cluster do ClickHouse Keeper. A ferramenta oficial clickhouse-keeper-converter só oferece suporte a conversões um para um (um cluster do ZooKeeper para um snapshot do Keeper), portanto a consolidação exige modificar o código-fonte do conversor para mesclar vários snapshots:
- Execute
clickhouse-keeper-converterseparadamente em cada cluster do ZooKeeper, gravando cada saída em um diretório distinto. - Desserialize os arquivos de snapshot sequencialmente. Ao mesclar, recalcule os valores de
numChildrenpara evitar conflitos de IDs de nós entre espaços de nomes de diferentes clusters de origem. - Grave a saída mesclada no diretório de snapshots de destino do ClickHouse Keeper.
Como lidar com criptografia e ACLs
O ClickHouse Keeper oferece suporte aos mesmos esquemas de ACL do ZooKeeper (world, auth, digest). A forma de lidar com ACLs durante a conversão depende da sua configuração do ZooKeeper:
- Totalmente criptografado ou totalmente sem criptografia: Converta diretamente. O conversor preserva as informações de ACL existentes.
- Parcialmente criptografado: Antes de converter, atribua privilégios de superadministrador a uma conta e limpe as ACLs com
setAcl -Rnos paths afetados. Converta e, em seguida, reative a criptografia no ClickHouse Keeper, se necessário.
Verificando a migração
Após iniciar o ClickHouse Keeper e reiniciar o ClickHouse, compare suas principais métricas com a linha de base pré-migração para confirmar que a migração foi bem-sucedida.
Ao consolidar vários clusters do ZooKeeper, distinga entre:
- Caminhos comuns: caminhos presentes em vários clusters de origem com dados idênticos — eles devem ser deduplicados no resultado consolidado.
- Caminhos diferenciados: caminhos que existem apenas em clusters específicos (por exemplo, em
/clickhouse/tablespara cada grupo de shards) — eles devem ser preservados a partir da origem correta.
Evite percorrer diretamente grandes árvores do ZooKeeper para fazer essa comparação. Em vez disso, grave todos os caminhos convertidos em um arquivo durante a conversão.
Ajustes pós-migração
Após a migração, considere ajustar estas configurações para clusters maiores ou com maior vazão:
| Configuração | Padrão | Recomendado | Observações |
|---|---|---|---|
max_requests_batch_size |
100 |
10000 |
Aumente para clusters com muitas partes ou muitos shards |
force_sync |
true |
false |
Gravações assíncronas de logs melhoram a vazão |
compress_logs |
false |
true |
Comprime arquivos de log do Raft para reduzir I/O de disco |
compress_snapshots_with_zstd_format |
true |
— | Já habilitado por padrão; comprime snapshots com zstd |
Essas configurações são definidas em coordination_settings na sua configuração do Keeper.
Recuperação após perder quórum
Como o ClickHouse Keeper usa Raft, ele pode tolerar uma certa quantidade de falhas de nós, dependendo do tamanho do cluster. Por exemplo, em um cluster de 3 nós, ele continuará funcionando corretamente se apenas 1 nó falhar.
A configuração do cluster pode ser alterada dinamicamente, mas há algumas limitações. A reconfiguração também depende do Raft, portanto, para adicionar/remover um nó do cluster, você precisa ter quórum. Se muitos nós do cluster falharem ao mesmo tempo, sem nenhuma chance de iniciá-los novamente, o Raft deixará de funcionar e não permitirá reconfigurar seu cluster da forma convencional.
Ainda assim, o ClickHouse Keeper tem um modo de recuperação que permite reconfigurar o cluster à força com apenas 1 nó. Isso deve ser feito apenas como último recurso, se você não conseguir iniciar seus nós novamente nem iniciar uma nova instância no mesmo endpoint.
Pontos importantes antes de continuar:
- Certifique-se de que os nós com falha não possam se conectar ao cluster novamente.
- Não inicie nenhum dos novos nós até que isso seja especificado nas etapas.
Depois de garantir que tudo acima está correto, você precisa fazer o seguinte:
- Escolha um único nó Keeper para ser seu novo líder. Lembre-se de que os dados desse nó serão usados em todo o cluster, por isso recomendamos usar um nó com o estado mais atualizado.
- Antes de fazer qualquer outra coisa, faça um backup das pastas
log_storage_pathesnapshot_storage_pathdo nó escolhido. - Reconfigure o cluster em todos os nós que você pretende usar.
- Envie o comando de quatro letras
rcvrpara o nó escolhido, o que colocará o nó em modo de recuperação, OU pare a instância do Keeper no nó escolhido e inicie-a novamente com o argumento--force-recovery. - Um por um, inicie as instâncias do Keeper nos novos nós, garantindo que
mntrretorneseguidorparazk_server_stateantes de iniciar o próximo. - Enquanto estiver em modo de recuperação, o nó líder retornará uma mensagem de erro para o comando
mntraté atingir quórum com os novos nós e recusará quaisquer solicitações do cliente e dos seguidores. - Depois que o quórum for atingido, o nó líder voltará ao modo normal de operação, aceitando todas as solicitações usando a verificação do Raft com
mntr, que deve retornarleaderparazk_server_state.
Usando discos com Keeper
O Keeper oferece suporte a um subconjunto de discos externos para armazenar snapshots, arquivos de log e o arquivo de estado.
Os tipos de disco compatíveis são:
- s3_plain
- s3
- local
A seguir, um exemplo de definições de disco contidas em uma configuração.
<clickhouse>
<storage_configuration>
<disks>
<log_local>
<type>local</type>
<path>/var/lib/clickhouse/coordination/logs/</path>
</log_local>
<log_s3_plain>
<type>s3_plain</type>
<endpoint>https://some_s3_endpoint/logs/</endpoint>
<access_key_id>ACCESS_KEY</access_key_id>
<secret_access_key>SECRET_KEY</secret_access_key>
</log_s3_plain>
<snapshot_local>
<type>local</type>
<path>/var/lib/clickhouse/coordination/snapshots/</path>
</snapshot_local>
<snapshot_s3_plain>
<type>s3_plain</type>
<endpoint>https://some_s3_endpoint/snapshots/</endpoint>
<access_key_id>ACCESS_KEY</access_key_id>
<secret_access_key>SECRET_KEY</secret_access_key>
</snapshot_s3_plain>
<state_s3_plain>
<type>s3_plain</type>
<endpoint>https://some_s3_endpoint/state/</endpoint>
<access_key_id>ACCESS_KEY</access_key_id>
<secret_access_key>SECRET_KEY</secret_access_key>
</state_s3_plain>
</disks>
</storage_configuration>
</clickhouse>Para usar um disco para logs, a configuração keeper_server.log_storage_disk deve ser definida com o nome do disco.
Para usar um disco para snapshots, a configuração keeper_server.snapshot_storage_disk deve ser definida com o nome do disco.
Além disso, keeper_server.latest_log_storage_disk pode ser usado para os logs mais recentes, e keeper_server.latest_snapshot_storage_disk, para os snapshots mais recentes.
Nesse caso, o Keeper moverá automaticamente os arquivos para os discos corretos quando novos logs ou snapshots forem criados.
Para usar um disco para o arquivo de estado, a configuração keeper_server.state_storage_disk deve ser definida com o nome do disco.
Mover arquivos entre discos é seguro, e não há risco de perda de dados se o Keeper parar no meio da transferência. Até que o arquivo seja completamente movido para o novo disco, ele não é excluído do disco antigo.
O Keeper com keeper_server.coordination_settings.force_sync definido como true (true por padrão) não consegue atender a algumas garantias em todos os tipos de disco.
No momento, apenas discos do tipo local oferecem suporte à sincronização persistente.
Se force_sync for usado, log_storage_disk deverá ser um disco local se latest_log_storage_disk não for usado.
Se latest_log_storage_disk for usado, ele deverá ser sempre um disco local.
Se force_sync estiver desabilitado, discos de todos os tipos poderão ser usados em qualquer configuração.
Uma possível configuração de armazenamento para uma instância do Keeper poderia ser a seguinte:
<clickhouse>
<keeper_server>
<log_storage_disk>log_s3_plain</log_storage_disk>
<latest_log_storage_disk>log_local</latest_log_storage_disk>
<snapshot_storage_disk>snapshot_s3_plain</snapshot_storage_disk>
<latest_snapshot_storage_disk>snapshot_local</latest_snapshot_storage_disk>
</keeper_server>
</clickhouse>Esta instância armazenará todos os logs, exceto o mais recente, no disco log_s3_plain, enquanto o log mais recente ficará no disco log_local.
A mesma lógica se aplica aos snapshots: todos os snapshots, exceto o mais recente, serão armazenados em snapshot_s3_plain, enquanto o snapshot mais recente ficará no disco snapshot_local.
Alterando a configuração de disco
Se uma configuração de disco em camadas estiver definida (usando discos separados para os arquivos mais recentes), o Keeper tentará mover automaticamente os arquivos para os discos corretos na inicialização. Aplica-se a mesma garantia de antes: até que o arquivo seja completamente movido para o novo disco, ele não é excluído do disco antigo, portanto, é seguro reiniciar várias vezes.
Se for necessário mover arquivos para um disco totalmente novo (ou passar de uma configuração com 2 discos para uma configuração com um único disco), é possível usar várias definições de keeper_server.old_snapshot_storage_disk e keeper_server.old_log_storage_disk.
A configuração a seguir mostra como passar da configuração anterior com 2 discos para uma nova configuração com um único disco:
<clickhouse>
<keeper_server>
<old_log_storage_disk>log_local</old_log_storage_disk>
<old_log_storage_disk>log_s3_plain</old_log_storage_disk>
<log_storage_disk>log_local2</log_storage_disk>
<old_snapshot_storage_disk>snapshot_s3_plain</old_snapshot_storage_disk>
<old_snapshot_storage_disk>snapshot_local</old_snapshot_storage_disk>
<snapshot_storage_disk>snapshot_local2</snapshot_storage_disk>
</keeper_server>
</clickhouse>Ao iniciar, todos os arquivos de log serão movidos de log_local e log_s3_plain para o disco log_local2.
Além disso, todos os arquivos de snapshot serão movidos de snapshot_local e snapshot_s3_plain para o disco snapshot_local2.
Configurando o cache de logs
Para minimizar a quantidade de dados lidos do disco, o Keeper armazena em cache na memória as entradas de log. Se as solicitações forem grandes, as entradas de log ocuparão muita memória; por isso, a quantidade de logs armazenados em cache é limitada. O limite do cache dos logs mais recentes é controlado por:
latest_logs_cache_size_threshold- tamanho total dos logs mais recentes armazenados no cache
Se o valor padrão for muito alto, reduza esta configuração para diminuir o uso de memória.
As entradas de log necessárias para o próximo commit são fornecidas por um leitor de leitura antecipada decodificada, dimensionado por
log_readahead_commit_window_bytes (0 desativa a leitura antecipada para commit). Essa configuração substitui as
configurações obsoletas commit_logs_cache_size_threshold e commit_logs_cache_entry_count_threshold,
mantidas apenas para compatibilidade de configuração (a primeira ainda é mapeada para log_readahead_commit_window_bytes se
este não estiver definido; a segunda não tem efeito). O mesmo mecanismo de leitura antecipada também atende às leituras de recuperação da
replicação do seguidor quando log_readahead_enabled é true; consulte
log_readahead_window_bytes, log_readahead_max_peer_readers, log_readahead_eviction_timeout_ms,
log_readahead_pool_threads, log_readahead_serve_wait_timeout_ms e log_readahead_chunk_size
nas configurações internas de coordenação para conhecer os parâmetros de ajuste
do lado do peer.
Prometheus
O Keeper pode expor dados de métricas para coleta pelo Prometheus.
Configurações:
endpoint– Endpoint HTTP para a coleta de métricas pelo servidor Prometheus. Deve começar com '/'.port– Porta doendpoint.metrics– Sinalizador que define se as métricas da tabela system.metrics serão expostas.events– Sinalizador que define se as métricas da tabela system.events serão expostas.asynchronous_metrics– Sinalizador que define se os valores atuais das métricas da tabela system.asynchronous_metrics serão expostos.
Exemplo
<clickhouse>
<listen_host>0.0.0.0</listen_host>
<http_port>8123</http_port>
<tcp_port>9000</tcp_port>
<prometheus>
<endpoint>/metrics</endpoint>
<port>9363</port>
<metrics>true</metrics>
<events>true</events>
<asynchronous_metrics>true</asynchronous_metrics>
</prometheus>
</clickhouse>Verifique (substitua 127.0.0.1 pelo endereço IP ou pelo hostname do seu servidor ClickHouse):
curl 127.0.0.1:9363/metricsConsulte também a integração com Prometheus do ClickHouse Cloud.
Guia do usuário do ClickHouse Keeper
Este guia apresenta configurações simples e mínimas para configurar o ClickHouse Keeper, com um exemplo de como testar operações distribuídas. Este exemplo é executado em 3 nós Linux.
Configure os nós com as configurações do Keeper
-
Instale 3 instâncias do ClickHouse em 3 hosts (
chnode1,chnode2,chnode3). (Consulte o Quick Start para mais detalhes sobre a instalação do ClickHouse.) -
Em cada nó, adicione a seguinte entrada para permitir a comunicação externa por meio da interface de rede.
<listen_host>0.0.0.0</listen_host> -
Adicione a seguinte configuração do ClickHouse Keeper aos três servidores, atualizando a configuração
<server_id>em cada servidor; parachnode1, seria1, parachnode2, seria2e assim por diante.<keeper_server> <tcp_port>9181</tcp_port> <server_id>1</server_id> <log_storage_path>/var/lib/clickhouse/coordination/log</log_storage_path> <snapshot_storage_path>/var/lib/clickhouse/coordination/snapshots</snapshot_storage_path> <coordination_settings> <operation_timeout_ms>10000</operation_timeout_ms> <session_timeout_ms>30000</session_timeout_ms> <raft_logs_level>warning</raft_logs_level> </coordination_settings> <raft_configuration> <server> <id>1</id> <hostname>chnode1.domain.com</hostname> <port>9234</port> </server> <server> <id>2</id> <hostname>chnode2.domain.com</hostname> <port>9234</port> </server> <server> <id>3</id> <hostname>chnode3.domain.com</hostname> <port>9234</port> </server> </raft_configuration> </keeper_server>Estas são as configurações básicas usadas acima:
Parâmetro Descrição Exemplo tcp_port porta a ser usada pelos clientes do Keeper 9181, equivalente padrão ao 2181, como no ZooKeeper server_id identificador de cada servidor do ClickHouse Keeper usado na configuração do Raft 1 coordination_settings seção de parâmetros como timeouts timeouts: 10000, nível de log: trace server definição do servidor participante lista com a definição de cada servidor raft_configuration configurações de cada servidor no cluster do Keeper servidor e configurações de cada um id ID numérico do servidor para os serviços do Keeper 1 hostname hostname, IP ou FQDN de cada servidor no cluster do Keeper chnode1.domain.comport porta usada para escutar conexões entre servidores do Keeper 9234 -
Habilite o componente Zookeeper. Ele usará o mecanismo ClickHouse Keeper:
<zookeeper> <node> <host>chnode1.domain.com</host> <port>9181</port> </node> <node> <host>chnode2.domain.com</host> <port>9181</port> </node> <node> <host>chnode3.domain.com</host> <port>9181</port> </node> </zookeeper>Estas são as configurações básicas usadas acima:
Parâmetro Descrição Exemplo node lista de nós para conexões com o ClickHouse Keeper entrada de configuração para cada servidor host hostname, IP ou FQDN de cada nó do ClickHouse Keeper chnode1.domain.comport porta do cliente do ClickHouse Keeper 9181 -
Reinicie o ClickHouse e verifique se cada instância do Keeper está em execução. Execute o comando a seguir em cada servidor. O comando
ruokretornaimokse o Keeper estiver em execução e funcionando corretamente:# echo ruok | nc localhost 9181; echo imok -
O banco de dados
systemtem uma tabela chamadazookeeperque contém os detalhes das suas instâncias do ClickHouse Keeper. Vamos ver essa tabela:SELECT * FROM system.zookeeper WHERE path IN ('/', '/clickhouse')A tabela tem esta aparência:
┌─name───────┬─value─┬─czxid─┬─mzxid─┬───────────────ctime─┬───────────────mtime─┬─version─┬─cversion─┬─aversion─┬─ephemeralOwner─┬─dataLength─┬─numChildren─┬─pzxid─┬─path────────┐ │ clickhouse │ │ 124 │ 124 │ 2022-03-07 00:49:34 │ 2022-03-07 00:49:34 │ 0 │ 2 │ 0 │ 0 │ 0 │ 2 │ 5693 │ / │ │ task_queue │ │ 125 │ 125 │ 2022-03-07 00:49:34 │ 2022-03-07 00:49:34 │ 0 │ 1 │ 0 │ 0 │ 0 │ 1 │ 126 │ /clickhouse │ │ tables │ │ 5693 │ 5693 │ 2022-03-07 00:49:34 │ 2022-03-07 00:49:34 │ 0 │ 3 │ 0 │ 0 │ 0 │ 3 │ 6461 │ /clickhouse │ └────────────┴───────┴───────┴───────┴─────────────────────┴─────────────────────┴─────────┴──────────┴──────────┴────────────────┴────────────┴─────────────┴───────┴─────────────┘
Configure um cluster no ClickHouse
-
Vamos configurar um cluster simples com 2 shards e apenas uma réplica em 2 dos nós. O terceiro nó será usado para atingir um quorum exigido pelo ClickHouse Keeper. Atualize a configuração em
chnode1echnode2. O cluster a seguir define 1 shard em cada nó, totalizando 2 shards sem replicação. Neste exemplo, parte dos dados ficará em um nó e parte ficará no outro:<remote_servers> <cluster_2S_1R> <shard> <replica> <host>chnode1.domain.com</host> <port>9000</port> <user>default</user> <password>ClickHouse123!</password> </replica> </shard> <shard> <replica> <host>chnode2.domain.com</host> <port>9000</port> <user>default</user> <password>ClickHouse123!</password> </replica> </shard> </cluster_2S_1R> </remote_servers>Parâmetro Descrição Exemplo shard lista de réplicas na definição do cluster lista de réplicas de cada shard replica lista de configurações de cada réplica entradas de configuração de cada réplica host hostname, IP ou FQDN do servidor que hospedará um shard de réplica chnode1.domain.comport porta usada para comunicação por meio do protocolo TCP nativo 9000 user nome de usuário que será usado para autenticação nas instâncias do cluster default password senha do usuário definido para permitir conexões com as instâncias do cluster ClickHouse123! -
Reinicie o ClickHouse e verifique se o cluster foi criado:
SHOW clusters;Você deverá ver seu cluster:
┌─cluster───────┐ │ cluster_2S_1R │ └───────────────┘
Criar e testar a tabela distribuída
-
Crie um novo banco de dados no novo cluster usando o clickhouse client em
chnode1. A cláusulaON CLUSTERcria automaticamente o banco de dados em ambos os nós.CREATE DATABASE db1 ON CLUSTER 'cluster_2S_1R'; -
Crie uma nova tabela no banco de dados
db1. Mais uma vez,ON CLUSTERcria a tabela em ambos os nós.CREATE TABLE db1.table1 on cluster 'cluster_2S_1R' ( `id` UInt64, `column1` String ) ENGINE = MergeTree ORDER BY column1 -
No nó
chnode1, adicione algumas linhas:INSERT INTO db1.table1 (id, column1) VALUES (1, 'abc'), (2, 'def') -
Adicione algumas linhas no nó
chnode2:INSERT INTO db1.table1 (id, column1) VALUES (3, 'ghi'), (4, 'jkl') -
Observe que executar uma instrução
SELECTem cada nó mostra apenas os dados daquele nó. Por exemplo, emchnode1:SELECT * FROM db1.table1Query id: 7ef1edbc-df25-462b-a9d4-3fe6f9cb0b6d ┌─id─┬─column1─┐ │ 1 │ abc │ │ 2 │ def │ └────┴─────────┘ 2 rows in set. Elapsed: 0.006 sec.Em
chnode2: -
SELECT * FROM db1.table1Query id: c43763cc-c69c-4bcc-afbe-50e764adfcbf ┌─id─┬─column1─┐ │ 3 │ ghi │ │ 4 │ jkl │ └────┴─────────┘ -
Você pode criar uma tabela
Distributedpara representar os dados nos dois shards. Tabelas com o engineDistributednão armazenam dados próprios, mas permitem o processamento distribuído de consultas em vários servidores. As leituras atingem todos os shards, e as gravações podem ser distribuídas entre os shards. Execute a seguinte consulta emchnode1:CREATE TABLE db1.dist_table ( id UInt64, column1 String ) ENGINE = Distributed(cluster_2S_1R,db1,table1) -
Observe que consultar
dist_tableretorna todas as quatro linhas de dados dos dois shards:SELECT * FROM db1.dist_tableQuery id: 495bffa0-f849-4a0c-aeea-d7115a54747a ┌─id─┬─column1─┐ │ 1 │ abc │ │ 2 │ def │ └────┴─────────┘ ┌─id─┬─column1─┐ │ 3 │ ghi │ │ 4 │ jkl │ └────┴─────────┘ 4 rows in set. Elapsed: 0.018 sec.
Resumo
Este guia mostrou como configurar um cluster usando o ClickHouse Keeper. Com o ClickHouse Keeper, você pode configurar clusters e definir tabelas distribuídas que podem ser replicadas entre os shards.
Configurando o ClickHouse Keeper com caminhos exclusivos
Descrição
Este artigo descreve como usar a configuração da macro interna {uuid}
para criar entradas exclusivas no ClickHouse Keeper ou ZooKeeper. Caminhos exclusivos
ajudam ao criar e remover tabelas com frequência, pois
isso evita ter de esperar vários minutos até que a coleta de lixo do Keeper
remova entradas de caminho, já que, sempre que um caminho é criado, um novo uuid é usado
nesse caminho; os caminhos nunca são reutilizados.
Ambiente de Example
Um cluster de três nós que será configurado para ter o ClickHouse Keeper em todos os três nós e o ClickHouse em dois deles. Isso fornece ao ClickHouse Keeper três nós (incluindo um nó de desempate) e um único shard do ClickHouse composto por duas réplicas.
| node | descrição |
|---|---|
chnode1.marsnet.local |
nó de dados - cluster cluster_1S_2R |
chnode2.marsnet.local |
nó de dados - cluster cluster_1S_2R |
chnode3.marsnet.local |
nó de desempate do ClickHouse Keeper |
Configuração de Example para o cluster:
<remote_servers>
<cluster_1S_2R>
<shard>
<replica>
<host>chnode1.marsnet.local</host>
<port>9440</port>
<user>default</user>
<password>ClickHouse123!</password>
<secure>1</secure>
</replica>
<replica>
<host>chnode2.marsnet.local</host>
<port>9440</port>
<user>default</user>
<password>ClickHouse123!</password>
<secure>1</secure>
</replica>
</shard>
</cluster_1S_2R>
</remote_servers>Procedimentos para configurar tabelas para usarem {uuid}
- Configure as macros em cada servidor exemplo para o servidor 1:
<macros>
<shard>1</shard>
<replica>replica_1</replica>
</macros>- Crie um banco de dados
CREATE DATABASE db_uuid
ON CLUSTER 'cluster_1S_2R'
ENGINE Atomic;CREATE DATABASE db_uuid ON CLUSTER cluster_1S_2R
ENGINE = Atomic
Query id: 07fb7e65-beb4-4c30-b3ef-bd303e5c42b5
┌─host──────────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ chnode2.marsnet.local │ 9440 │ 0 │ │ 1 │ 0 │
│ chnode1.marsnet.local │ 9440 │ 0 │ │ 0 │ 0 │
└───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘- Crie uma tabela no cluster usando as macros e
{uuid}
CREATE TABLE db_uuid.uuid_table1 ON CLUSTER 'cluster_1S_2R'
(
id UInt64,
column1 String
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/db_uuid/{uuid}', '{replica}' )
ORDER BY (id);CREATE TABLE db_uuid.uuid_table1 ON CLUSTER cluster_1S_2R
(
`id` UInt64,
`column1` String
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/db_uuid/{uuid}', '{replica}')
ORDER BY id
Query id: 8f542664-4548-4a02-bd2a-6f2c973d0dc4
┌─host──────────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ chnode1.marsnet.local │ 9440 │ 0 │ │ 1 │ 0 │
│ chnode2.marsnet.local │ 9440 │ 0 │ │ 0 │ 0 │
└───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘- Crie uma tabela distribuída
CREATE TABLE db_uuid.dist_uuid_table1 ON CLUSTER 'cluster_1S_2R'
(
id UInt64,
column1 String
)
ENGINE = Distributed('cluster_1S_2R', 'db_uuid', 'uuid_table1' );CREATE TABLE db_uuid.dist_uuid_table1 ON CLUSTER cluster_1S_2R
(
`id` UInt64,
`column1` String
)
ENGINE = Distributed('cluster_1S_2R', 'db_uuid', 'uuid_table1')
Query id: 3bc7f339-ab74-4c7d-a752-1ffe54219c0e
┌─host──────────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ chnode2.marsnet.local │ 9440 │ 0 │ │ 1 │ 0 │
│ chnode1.marsnet.local │ 9440 │ 0 │ │ 0 │ 0 │
└───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘Teste
- Insira dados no primeiro nó (por exemplo,
chnode1)
INSERT INTO db_uuid.uuid_table1
( id, column1)
VALUES
( 1, 'abc');INSERT INTO db_uuid.uuid_table1 (id, column1) FORMAT Values
Query id: 0f178db7-50a6-48e2-9a1b-52ed14e6e0f9
Ok.
1 row in set. Elapsed: 0.033 sec.- Insira dados no segundo nó (por exemplo,
chnode2)
INSERT INTO db_uuid.uuid_table1
( id, column1)
VALUES
( 2, 'def');INSERT INTO db_uuid.uuid_table1 (id, column1) FORMAT Values
Query id: edc6f999-3e7d-40a0-8a29-3137e97e3607
Ok.
1 row in set. Elapsed: 0.529 sec.- Visualize os registros usando a tabela distribuída
SELECT * FROM db_uuid.dist_uuid_table1;SELECT *
FROM db_uuid.dist_uuid_table1
Query id: 6cbab449-9e7f-40fe-b8c2-62d46ba9f5c8
┌─id─┬─column1─┐
│ 1 │ abc │
└────┴─────────┘
┌─id─┬─column1─┐
│ 2 │ def │
└────┴─────────┘
2 rows in set. Elapsed: 0.007 sec.Alternativas
O caminho de replicação padrão pode ser definido previamente por macros e também com {uuid}
- Defina o padrão das tabelas em cada nó
<default_replica_path>/clickhouse/tables/{shard}/db_uuid/{uuid}</default_replica_path>
<default_replica_name>{replica}</default_replica_name>- Crie a tabela sem parâmetros explícitos:
CREATE TABLE db_uuid.uuid_table1 ON CLUSTER 'cluster_1S_2R'
(
id UInt64,
column1 String
)
ENGINE = ReplicatedMergeTree
ORDER BY (id);CREATE TABLE db_uuid.uuid_table1 ON CLUSTER cluster_1S_2R
(
`id` UInt64,
`column1` String
)
ENGINE = ReplicatedMergeTree
ORDER BY id
Query id: ab68cda9-ae41-4d6d-8d3b-20d8255774ee
┌─host──────────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ chnode2.marsnet.local │ 9440 │ 0 │ │ 1 │ 0 │
│ chnode1.marsnet.local │ 9440 │ 0 │ │ 0 │ 0 │
└───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘
2 rows in set. Elapsed: 1.175 sec.- Verifique se ele usou as mesmas configurações da configuração padrão
SHOW CREATE TABLE db_uuid.uuid_table1;SHOW CREATE TABLE db_uuid.uuid_table1
CREATE TABLE db_uuid.uuid_table1
(
`id` UInt64,
`column1` String
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/db_uuid/{uuid}', '{replica}')
ORDER BY id
1 row in set. Elapsed: 0.003 sec.Solução de problemas
Exemplo de comando para obter informações da tabela e o UUID:
SELECT * FROM system.tables
WHERE database = 'db_uuid' AND name = 'uuid_table1';Comando de exemplo para obter informações sobre a tabela no ZooKeeper usando o UUID da tabela acima
SELECT * FROM system.zookeeper
WHERE path = '/clickhouse/tables/1/db_uuid/9e8a3cc2-0dec-4438-81a7-c3e63ce2a1cf/replicas';Para verificar:
Por exemplo,
SELECT name, engine FROM system.databases WHERE name = 'db_uuid';SELECT
name,
engine
FROM system.databases
WHERE name = 'db_uuid'
Query id: b047d459-a1d2-4016-bcf9-3e97e30e49c2
┌─name────┬─engine─┐
│ db_uuid │ Atomic │
└─────────┴────────┘
1 row in set. Elapsed: 0.004 sec.Reconfiguração dinâmica do ClickHouse Keeper
Descrição
O ClickHouse Keeper oferece suporte parcial ao comando reconfig
do ZooKeeper para reconfiguração dinâmica do cluster se keeper_server.enable_reconfiguration estiver ativado.
Um nó virtual /keeper/config contém a última configuração do cluster confirmada no seguinte formato:
server.id = server_host:server_port[;server_type][;server_priority]
server.id2 = ...
...- Cada entrada de servidor é separada por uma quebra de linha.
server_typeéparticipantoulearner(learner não participa das eleições de líder).server_priorityé um inteiro não negativo que indica quais nós devem ser priorizados nas eleições de líder. Prioridade 0 significa que o servidor nunca será líder.
Exemplo:
:) get /keeper/config
server.1=zoo1:9234;participant;1
server.2=zoo2:9234;participant;1
server.3=zoo3:9234;participant;1Você pode usar o comando reconfig para adicionar novos servidores, remover os existentes e alterar as
prioridades dos servidores atuais. Veja alguns exemplos (usando clickhouse-keeper-client):
# Adicionar dois novos servidores
reconfig add "server.5=localhost:123,server.6=localhost:234;learner"
# Remover outros dois servidores
reconfig remove "3,4"
# Alterar a prioridade do servidor existente para 8
reconfig add "server.5=localhost:5123;participant;8"E aqui estão exemplos de kazoo:
# Adicionar dois novos servidores, remover dois outros servidores
reconfig(joining="server.5=localhost:123,server.6=localhost:234;learner", leaving="3,4")
# Alterar a prioridade do servidor existente para 8
reconfig(joining="server.5=localhost:5123;participant;8", leaving=None)Os servidores em joining devem estar no formato de servidor descrito acima. As entradas de servidor devem ser separadas por vírgulas.
Ao adicionar novos servidores, você pode omitir server_priority (o valor padrão é 1) e server_type (o valor padrão
é participant).
Se quiser alterar a prioridade de um servidor existente, adicione-o a joining com a prioridade desejada.
O host, a porta e o tipo do servidor devem ser iguais aos da configuração existente do servidor.
Os servidores são adicionados e removidos na ordem em que aparecem em joining e leaving.
Todas as atualizações de joining são processadas antes das atualizações de leaving.
Há algumas ressalvas na implementação da reconfiguração do Keeper:
-
Apenas a reconfiguração incremental é suportada. Requisições com
new_membersnão vazio são recusadas.A implementação do ClickHouse Keeper depende da API do NuRaft para alterar a composição dinamicamente. O NuRaft oferece uma forma de adicionar um único servidor ou remover um único servidor, um de cada vez. Isso significa que cada alteração na configuração (cada parte de
joining, cada parte deleaving) deve ser decidida separadamente. Portanto, não há reconfiguração em lote, pois isso seria enganoso para os usuários finais.Alterar o tipo do servidor (participant/learner) também não é possível, já que isso não é suportado pelo NuRaft, e a única forma seria remover e adicionar o servidor, o que, novamente, seria enganoso.
-
Você não pode usar o valor
znodestatretornado. -
O campo
from_versionnão é usado. Todas as requisições comfrom_versiondefinido são recusadas. Isso ocorre porque/keeper/configé um nó virtual, o que significa que ele não é armazenado em armazenamento persistente, mas sim gerado em tempo real com a configuração de nó especificada para cada requisição. Essa decisão foi tomada para não duplicar dados, já que o NuRaft já armazena essa configuração. -
Diferentemente do ZooKeeper, não há como esperar a reconfiguração do cluster enviando um comando
sync. A nova configuração será aplicada eventualmente, mas sem garantias de tempo. -
O comando
reconfigpode falhar por vários motivos. Você pode verificar o estado do cluster e ver se a atualização foi aplicada.
Convertendo um keeper de nó único em um cluster
Às vezes, é necessário expandir um nó keeper experimental para formar um cluster. Veja a seguir como fazer isso passo a passo em um cluster de 3 nós:
- IMPORTANTE: novos nós devem ser adicionados em lotes menores que o quórum atual; caso contrário, eles elegerão um líder entre si. Neste exemplo, eles são adicionados um a um.
- O nó keeper existente deve ter o parâmetro de configuração
keeper_server.enable_reconfigurationhabilitado. - Inicie um segundo nó com a nova configuração completa do cluster keeper.
- Depois que ele iniciar, adicione-o ao nó 1 usando
reconfig. - Em seguida, inicie um terceiro nó e adicione-o usando
reconfig. - Atualize a configuração do
clickhouse-server, adicionando o novo nó keeper, e reinicie-o para aplicar as alterações. - Atualize a configuração do Raft no nó 1 e, opcionalmente, reinicie-o.
Para se familiarizar com o processo, aqui está um repositório sandbox.
Recursos não suportados
Embora o ClickHouse Keeper tenha como objetivo ser totalmente compatível com o ZooKeeper, alguns recursos ainda não foram implementados (embora o desenvolvimento continue em andamento):
createnão oferece suporte ao retorno do objetoStatcreatenão oferece suporte a TTLaddWatchnão funciona com watchesPERSISTENTremoveWatcheremoveAllWatchesnão têm suportesetWatchesnão tem suporte- A criação de znodes do tipo
CONTAINERnão tem suporte - A
autenticação SASLnão tem suporte