ClickHouse Keeper fournit le système de coordination pour la réplication des données et l’exécution des requêtes distributed DDL. ClickHouse Keeper est compatible avec ZooKeeper.
Détails d’implémentation
ZooKeeper est l’un des premiers systèmes de coordination open source largement connus. Il est implémenté en Java et s’appuie sur un modèle de données simple et puissant. L’algorithme de coordination de ZooKeeper, ZooKeeper Atomic Broadcast (ZAB), n’offre pas de garanties de linéarisabilité pour les lectures, car chaque nœud ZooKeeper traite les lectures localement. Contrairement à ZooKeeper, ClickHouse Keeper est écrit en C++ et utilise l’algorithme RAFT et son implémentation. Cet algorithme permet la linéarisabilité des lectures et des écritures, et possède plusieurs implémentations open source dans différents langages.
Par défaut, ClickHouse Keeper offre les mêmes garanties que ZooKeeper : des écritures linéarisables et des lectures non linéarisables. Il dispose d’un protocole client-serveur compatible, de sorte que n’importe quel client ZooKeeper standard peut être utilisé pour interagir avec ClickHouse Keeper. Les snapshots et les logs ont un format incompatible avec ZooKeeper, mais l’outil clickhouse-keeper-converter permet de convertir les données ZooKeeper en snapshots ClickHouse Keeper. Le protocole interserver de ClickHouse Keeper est lui aussi incompatible avec ZooKeeper ; un cluster mixte ZooKeeper / ClickHouse Keeper est donc impossible.
ClickHouse Keeper prend en charge les listes de contrôle d’accès (ACL) de la même manière que ZooKeeper. ClickHouse Keeper prend en charge le même ensemble de permissions et dispose des mêmes schémas intégrés : world, auth et digest. Le schéma d’authentification digest utilise la paire username:password ; le mot de passe est encodé en Base64.
Configuration
ClickHouse Keeper peut être utilisé comme alternative autonome à ZooKeeper ou comme composant interne de serveur ClickHouse. Dans les deux cas, le fichier de configuration .xml est quasiment le même.
Paramètres de configuration de Keeper
La balise principale de configuration de ClickHouse Keeper est <keeper_server> et comporte les paramètres suivants :
| Parameter | Description | Default |
|---|---|---|
tcp_port |
Port auquel un client peut se connecter. | 2181 |
tcp_port_secure |
Port sécurisé pour une connexion SSL entre le client et le serveur Keeper. | - |
server_id |
ID de serveur unique : chaque participant du cluster ClickHouse Keeper doit avoir un numéro unique (1, 2, 3…). | - |
log_storage_path |
Chemin d’accès aux logs de coordination. Comme avec ZooKeeper, il est préférable de stocker les logs sur des nœuds peu chargés. | - |
snapshot_storage_path |
Chemin d’accès aux snapshots de coordination. | - |
enable_reconfiguration |
Active la reconfiguration dynamique du cluster via reconfig. |
False |
max_memory_usage_soft_limit |
Limite souple, en octets, de l’utilisation maximale de la mémoire par Keeper. | max_memory_usage_soft_limit_ratio * physical_memory_amount |
max_memory_usage_soft_limit_ratio |
Si max_memory_usage_soft_limit n’est pas défini ou est défini sur zéro, cette valeur est utilisée pour définir la limite souple par défaut. |
0.9 |
cgroups_memory_observer_wait_time |
Si max_memory_usage_soft_limit n’est pas défini ou est défini à 0, cet intervalle est utilisé pour observer la quantité de mémoire physique. Lorsque cette quantité change, la limite souple de mémoire de Keeper est recalculée à l’aide de max_memory_usage_soft_limit_ratio. |
15 |
http_control |
Configuration de l’interface HTTP control. | - |
digest_enabled |
Active la vérification de cohérence des données en temps réel | True |
create_snapshot_on_exit |
Crée un snapshot lors de l’arrêt | - |
hostname_checks_enabled |
Active les vérifications de cohérence des noms d’hôte pour la configuration du cluster (par exemple, si localhost est utilisé avec des endpoints distants) | True |
four_letter_word_white_list |
Liste blanche des commandes 4lw. | conf, cons, crst, envi, ruok, srst, srvr, stat, wchs, dirs, mntr, isro, rcvr, apiv, csnp, lgif, rqld, ydld |
enable_ipv6 |
Active IPv6 | True |
Les autres paramètres courants sont hérités de la config du serveur ClickHouse (listen_host, logger, etc.).
Paramètres de coordination interne
Les paramètres de coordination interne se trouvent dans la section <keeper_server>.<coordination_settings> et comprennent les paramètres suivants :
| Paramètre | Description | Par défaut |
|---|---|---|
operation_timeout_ms |
Délai d’expiration pour une opération client unique (ms) | 10000 |
min_session_timeout_ms |
Délai d’expiration minimal pour la session client (ms) | 10000 |
session_timeout_ms |
Délai d’expiration maximal pour la session client (ms) | 100000 |
dead_session_check_period_ms |
Fréquence à laquelle ClickHouse Keeper vérifie les sessions expirées et les supprime (ms) | 500 |
heart_beat_interval_ms |
Fréquence à laquelle un leader ClickHouse Keeper envoie des heartbeats aux followers (ms) | 500 |
election_timeout_lower_bound_ms |
Si le follower ne reçoit pas de heartbeat du leader dans cet intervalle, il peut lancer une leader election. Doit être inférieur ou égal à election_timeout_upper_bound_ms. Idéalement, ils ne devraient pas être égaux. |
1000 |
election_timeout_upper_bound_ms |
Si le follower ne reçoit pas de heartbeat du leader dans cet intervalle, il doit lancer une leader election. | 2000 |
rotate_log_storage_interval |
Nombre d’enregistrements de log à stocker dans un seul fichier. | 100000 |
reserved_log_items |
Nombre d’enregistrements du log de coordination à conserver avant la compaction. | 100000 |
snapshot_distance |
Fréquence à laquelle ClickHouse Keeper crée de nouveaux snapshots (en nombre d’enregistrements dans les logs). | 100000 |
snapshots_to_keep |
Nombre de snapshots à conserver. | 3 |
stale_log_gap |
Seuil à partir duquel le leader considère le follower comme stale et lui envoie le snapshot au lieu des logs. | 10000 |
fresh_log_gap |
Moment à partir duquel le nœud est considéré comme fresh. | 200 |
max_requests_batch_size |
Taille maximale du batch, en nombre de requests, avant son envoi à RAFT. | 100 |
force_sync |
Appeler fsync à chaque écriture dans le log de coordination. |
true |
quorum_reads |
Exécuter les read requests comme des écritures via l’ensemble du consensus RAFT, avec une vitesse similaire. | false |
raft_logs_level |
Niveau de logging textuel lié à la coordination (trace, debug, etc.). | par défaut du système |
auto_forwarding |
Autoriser le transfert des write requests des followers vers le leader. | true |
shutdown_timeout |
Attendre la fin des connections internes et l’arrêt (ms). | 5000 |
startup_timeout |
Si le server ne se connecte pas aux autres participants du quorum dans le délai spécifié, il s’arrête (ms). | 30000 |
async_replication |
Activer la réplication asynchrone. Toutes les garanties d’écriture et de lecture sont préservées tout en améliorant les performances. Ce paramètre est désactivé par défaut afin de ne pas rompre la compatibilité descendante | false |
latest_logs_cache_size_threshold |
Taille totale maximale de l’in-memory cache des dernières log entries | 1GiB |
commit_logs_cache_size_threshold |
Obsolète. Utilisé pour log_readahead_commit_window_bytes si ce paramètre n’est pas lui-même défini. |
- |
commit_logs_cache_entry_count_threshold |
Obsolète, sans effet. Utilisez plutôt log_readahead_commit_window_bytes. |
- |
log_readahead_enabled |
Activer la lecture anticipée décodée par peer pour les lectures de rattrapage du changelog (réplication des followers). | false |
log_readahead_window_bytes |
Nombre maximal d’octets d’entries décodées mis en buffer par lecteur peer. Doit être au moins aussi grand qu’un batch append-entries classique. | 64MiB |
log_readahead_max_peer_readers |
Nombre maximal de lecteurs de lecture anticipée par peer exécutés de manière concurrente. | 8 |
log_readahead_eviction_timeout_ms |
Délai d’inactivité après lequel un lecteur de lecture anticipée par peer inactif, ou le lecteur de commit, est évincé (un échec ultérieur le recrée). | 30000 |
log_readahead_pool_threads |
Nombre de threads dans le thread pool dédié à la lecture anticipée. 0 dérive la valeur de log_readahead_max_peer_readers. |
0 |
log_readahead_serve_wait_timeout_ms |
Durée maximale d’attente du remplissage de lecture anticipée en arrière-plan avant de revenir à une lecture directe. | 200 |
log_readahead_chunk_size |
Nombre d’entrées de log décodées par фрагмент dans la tâche de remplissage de lecture anticipée. | 16 |
log_readahead_commit_window_bytes |
Taille totale maximale des entrées de log décodées mises en mémoire tampon avant le thread de commit. 0 désactive la lecture anticipée du commit (le commit lit les entrées du disque une par une). |
500MiB |
log_startup_read_max_streams |
Nombre maximal de fichiers de changelog lus simultanément au démarrage de Keeper. 0 = utiliser automatiquement le nombre de cœurs CPU. 1 = utiliser la lecture de démarrage sérielle (pré-parallèle). Le parallélisme effectif est limité par le nombre de fichiers de changelog à lire ; envisagez de le réduire sur les stockages limités par les seek (HDD, volumes limités en IOPS). |
0 |
log_startup_read_buffer_size |
Taille du read buffer par stream (octets) utilisée lors de la lecture des changelogs au démarrage de Keeper. Doit être supérieure à 0. Le buffer est également limité à la taille du fichier. |
8MiB |
disk_move_retries_wait_ms |
Durée d’attente entre les retries après un échec survenu lors du déplacement d’un fichier entre des disks | 1000 |
disk_move_retries_during_init |
Nombre de retries après un échec survenu lors du déplacement d’un fichier entre des disks pendant l’initialisation | 100 |
experimental_use_rocksdb |
Utiliser rocksdb comme stockage backend | 0 |
La configuration du quorum se trouve dans la section <keeper_server>.<raft_configuration> et contient la description des serveurs.
Le seul paramètre pour l’ensemble du quorum est secure, qui active une connexion chiffrée pour la communication entre les participants au quorum. Le paramètre peut être défini sur true si une connexion SSL est requise pour la communication interne entre les nœuds, ou laissé non spécifié dans le cas contraire.
Les principaux paramètres de chaque <server> sont :
id— Identifiant du serveur dans un quorum.hostname— Nom d’hôte où ce serveur est hébergé.port— Port sur lequel ce serveur écoute les connexions.can_become_leader— Définissezfalsepour configurer le serveur commelearner. Si ce paramètre est omis, la valeur esttrue.
Des exemples de configuration pour un quorum à trois nœuds sont disponibles dans les tests d’intégration avec le préfixe test_keeper_. Exemple de configuration pour le serveur #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>Comment l’exécuter
ClickHouse Keeper est inclus dans le paquet du serveur ClickHouse ; il vous suffit d’ajouter la configuration de <keeper_server> à votre fichier /etc/your_path_to_config/clickhouse-server/config.xml et de démarrer le serveur ClickHouse comme d’habitude. Si vous souhaitez exécuter ClickHouse Keeper en mode standalone, vous pouvez le démarrer de manière similaire avec :
clickhouse-keeper --config /etc/your_path_to_config/config.xmlSi vous ne disposez pas du lien symbolique (clickhouse-keeper), vous pouvez le créer ou passer keeper en argument à clickhouse :
clickhouse keeper --config /etc/your_path_to_config/config.xmlCommandes à quatre lettres
ClickHouse Keeper fournit également des commandes 4lw, presque identiques à celles de ZooKeeper. Chaque commande se compose de quatre lettres, comme mntr, stat, etc. Parmi les commandes les plus utiles : stat fournit des informations générales sur le serveur et les clients connectés, srvr fournit des détails supplémentaires sur le serveur, et cons fournit des détails supplémentaires sur les connexions.
Les commandes 4lw utilisent une configuration de liste blanche, four_letter_word_white_list, dont la valeur par défaut est conf,cons,crst,envi,ruok,srst,srvr,stat,wchs,dirs,mntr,isro,rcvr,apiv,csnp,lgif,rqld,ydld.
Vous pouvez envoyer ces commandes à ClickHouse Keeper via telnet ou nc, sur le port client.
echo mntr | nc localhost 9181Vous trouverez ci-dessous les commandes 4lw détaillées :
ruok: teste si le serveur est en cours de fonctionnement et ne se trouve pas dans un état d'erreur. Le serveur répond parimoks'il est en cours d'exécution. Sinon, il ne répond pas du tout. Une réponseimokn'indique pas nécessairement que le serveur a rejoint le quorum, mais seulement que le processus serveur est actif et lié au port client spécifié. Utilisez "stat" pour obtenir des détails sur l'état vis-à-vis du quorum et les informations de connexion du client.
imokmntr: affiche une liste de variables pouvant être utilisées pour surveiller l’état du 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 et zk_cnt_election_time sont des métriques cumulatives réservées au leader. Elles constituent des observations par serveur, et non des mesures de disponibilité à l’échelle du cluster : le suivi commence lorsque ce serveur cesse d’observer un leader actif. Lors d’une partition réseau, cela peut inclure le temps pendant lequel un ancien leader reste actif dans une autre partition. Les métriques d’élection n’enregistrent qu’une élection réussie qui suit une fenêtre locale observée sans leader ; un transfert de leadership qui n’expose pas d’état sans leader échantillonné n’est intentionnellement pas comptabilisé.
Keeper échantillonne son état local de leader NuRaft une fois par heart_beat_interval_ms, mais jamais à une fréquence supérieure à une fois toutes les 100 millisecondes. Chaque limite de fenêtre peut différer de cette transition d’état locale d’un maximum égal à l’intervalle effectif, et les fenêtres plus courtes que cet intervalle peuvent ne pas être détectées. Keeper enregistre la fin d’une élection locale lors de BecomeLeader de NuRaft. srst réinitialise les quatre valeurs.
La durée de la fenêtre la plus récente de chaque type observée localement est également exportée vers system.asynchronous_metrics sous les noms KeeperLastLeaderElectionTime et KeeperLastLeaderUnavailableTime, en millisecondes. KeeperLastLeaderElectionTime suit la même définition de fenêtre sans leader que zk_sum_election_time. Les deux sont également réservées au leader : un nœud qui n’est pas le leader actif, ou qui n’a pas encore terminé de fenêtre, indique 0. srst les réinitialise avec les compteurs cumulatifs.
srvr: affiche les informations détaillées du serveur.
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: Affiche des informations succinctes sur le serveur et les clients connectés.
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: Réinitialise les statistiques du serveur. La commande affecte le résultat desrvr,mntretstat.
Server stats reset.conf: Affiche les détails de la configuration de service.
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: Répertorie les informations détaillées sur la connexion/session de tous les clients connectés à ce serveur. Inclut des informations sur le nombre de paquets reçus/envoyés, l’identifiant de session, les latences des opérations, la dernière opération effectuée, 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: Réinitialise les statistiques de connexion et de session pour toutes les connexions.
Connection stats reset.envi: Afficher les détails de l’environnement d’exécution
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: Affiche la taille totale des snapshots et des fichiers de log, en octets
snapshot_dir_size: 0
log_dir_size: 3875isro: vérifie si le serveur est en mode lecture seule. Le serveur renvoieros’il est en mode lecture seule, ourwdans le cas contraire.
rwwchs: Affiche de brèves informations sur les watches du serveur.
1 connections watching 1 paths
Total watches:1wchc: Liste les informations détaillées sur les watches du serveur, par session. Cette commande affiche une liste de sessions (connexions) avec les watches associées (chemins). Notez que, selon le nombre de watches, cette opération peut être coûteuse (et affecter les performances du serveur) ; utilisez-la avec précaution.
0x0000000000000001
/clickhouse/task_queue/ddlwchp: répertorie des informations détaillées sur les watches du serveur, par chemin. La commande renvoie une liste de chemins (znodes) avec les sessions associées. Notez que, selon le nombre de watches, cette opération peut être coûteuse (c.-à-d. affecter les performances du serveur) ; utilisez-la avec précaution.
/clickhouse/task_queue/ddl
0x0000000000000001dump: répertorie les sessions ouvertes et les nœuds éphémères. Cette commande fonctionne uniquement sur le leader.
Sessions dump (2):
0x0000000000000001
0x0000000000000002
Sessions with Ephemerals (1):
0x0000000000000001
/clickhouse/task_queue/ddlcsnp: planifie une tâche de création de snapshot. Renvoie le dernier index de log validé du snapshot planifié en cas de succès, ouFailed to schedule snapshot creation task.en cas d’échec. La commandelgifpeut vous aider à déterminer si le snapshot est terminé.
100lgif: Informations sur le log de Keeper.first_log_idx: mon premier index de log dans le stockage de logs ;first_log_term: mon premier terme de log ;last_log_idx: mon dernier index de log dans le stockage de logs ;last_log_term: mon dernier terme de log ;last_committed_log_idx: mon dernier index de log validé dans la machine à états ;leader_committed_log_idx: l’index de log validé du leader, de mon point de vue ;target_committed_log_idx: l’index de log cible qui doit être validé ;last_snapshot_idx: le plus grand index de log validé dans le dernier 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: Demande à devenir le nouveau leader. RenvoieSent leadership request to leader.si la demande est envoyée, ouFailed to send leadership request to leader.dans le cas contraire. Si le nœud est déjà leader, le résultat est le même que si la demande avait été envoyée.
Sent leadership request to leader.ftfl: Répertorie tous les feature flags et indique s’ils sont enabled pour l’instance Keeper.
filtered_list 1
multi_read 1
check_not_exists 0ydld: Demande de céder le leadership et de devenir follower. Si le serveur qui reçoit la requête est leader, il suspend d’abord les opérations d’écriture, attend que le successeur (le leader actuel ne peut jamais être le successeur) ait terminé le rattrapage du dernier log, puis renonce à son rôle. Le successeur est choisi automatiquement. RenvoieSent yield leadership request to leader.si la requête est envoyée ouFailed to send yield leadership request to leader.dans le cas contraire. Si le nœud est déjà un follower, le résultat est le même que si la requête avait été envoyée.
Sent yield leadership request to leader.pfev: Renvoie les valeurs de tous les événements collectés. Pour chaque événement, renvoie son nom, sa valeur et sa description.
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
...Contrôle HTTP
ClickHouse Keeper fournit une interface HTTP permettant de vérifier si une réplique est prête à recevoir du trafic. Elle peut être utilisée dans des environnements cloud, comme Kubernetes.
Exemple de configuration activant le point de terminaison /ready :
<clickhouse>
<keeper_server>
<http_control>
<port>9182</port>
<readiness>
<endpoint>/ready</endpoint>
</readiness>
</http_control>
</keeper_server>
</clickhouse>Feature flags
Keeper est entièrement compatible avec ZooKeeper et ses clients, mais il introduit également certaines fonctionnalités et certains types de requêtes spécifiques qui peuvent être utilisés par le client ClickHouse.
Comme ces fonctionnalités peuvent entraîner des changements incompatibles avec les versions précédentes, la plupart sont désactivées par défaut et peuvent être activées à l’aide de la config keeper_server.feature_flags.
Toutes les fonctionnalités peuvent aussi être désactivées explicitement.
Si vous souhaitez activer une nouvelle fonctionnalité pour votre cluster Keeper, nous vous recommandons de commencer par mettre à jour toutes les instances Keeper du cluster vers une version qui prend en charge cette fonctionnalité, puis d’activer la fonctionnalité elle-même.
Exemple de config de feature flag qui désactive multi_read et active 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>Les fonctionnalités suivantes sont disponibles :
| Fonctionnalité | Description | Par défaut |
|---|---|---|
multi_read |
Prise en charge des requêtes de lecture multiples | 1 |
filtered_list |
Prise en charge des requêtes de liste qui filtrent les résultats selon le type de nœud (éphémère ou persistant) | 1 |
check_not_exists |
Prise en charge de la requête CheckNotExists, qui vérifie que le nœud n'existe pas |
1 |
create_if_not_exists |
Prise en charge de la requête CreateIfNotExists, qui tente de créer un nœud s'il n'existe pas. S'il existe déjà, aucune modification n'est appliquée et ZOK est renvoyé |
1 |
remove_recursive |
Prise en charge de la requête RemoveRecursive, qui supprime le nœud ainsi que son sous-arbre |
1 |
Migration depuis ZooKeeper
Une migration fluide de ZooKeeper vers ClickHouse Keeper n'est pas possible. Vous devez arrêter votre cluster ZooKeeper, convertir les données, puis démarrer ClickHouse Keeper. L'outil clickhouse-keeper-converter convertit les logs et snapshots ZooKeeper en un snapshot ClickHouse Keeper. Il nécessite ZooKeeper 3.4 ou une version ultérieure.
Préparation avant la migration
La migration nécessite d’interrompre l’ingestion des données. Prévoyez une fenêtre de maintenance avant de commencer.
Avant d’arrêter ZooKeeper, stoppez les tâches d’arrière-plan de ClickHouse qui modifient les métadonnées de coordination. Par exemple :
SYSTEM STOP MERGES;Consignez des métriques de comparaison avant la migration afin de pouvoir vérifier la cohérence ensuite.
Étapes de la migration
-
Arrêtez l’ingestion de données sur tous les nœuds ClickHouse.
-
Arrêtez toutes les tâches en arrière-plan sur tous les nœuds ClickHouse (voir ci-dessus).
-
Arrêtez tous les nœuds ZooKeeper.
-
Facultatif, mais recommandé : identifiez le nœud leader de ZooKeeper, démarrez-le, puis arrêtez-le à nouveau. Cela force ZooKeeper à écrire un snapshot cohérent sur le disque avant la conversion.
-
Exécutez
clickhouse-keeper-convertersur le nœud leader. Si vous avez installé le binaire complet de ClickHouse, utilisez plutôt la sous-commandekeeper-converter(clickhouse keeper-converter). Si aucun des deux n’est disponible, téléchargez le binaire.
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-
Copiez le snapshot sur tous les nœuds ClickHouse Keeper. Le snapshot doit être présent sur chaque nœud avant qu’aucun nœud ne démarre — si un nœud démarre sans snapshot, il peut s’élire leader avec un état vide.
-
Mettez à jour votre configuration ClickHouse afin qu’elle pointe vers le nouveau cluster Keeper.
-
Démarrez ClickHouse Keeper sur tous les nœuds, puis redémarrez ClickHouse.
-
Comparez les métriques à votre référence pré-migration pour vérifier leur cohérence.
-
Reprenez les tâches en arrière-plan et redémarrez l’ingestion des données.
Consolidation de plusieurs clusters ZooKeeper
Si vous exécutez plusieurs clusters ZooKeeper — par exemple, un par groupe de shards — vous pouvez les consolider en un seul cluster ClickHouse Keeper. L’outil officiel clickhouse-keeper-converter ne prend en charge que les conversions un à un (un cluster ZooKeeper vers un snapshot Keeper) ; la consolidation exige donc de modifier le code source du convertisseur pour fusionner plusieurs snapshots :
- Exécutez
clickhouse-keeper-converterséparément sur chaque cluster ZooKeeper, en enregistrant chaque sortie dans un répertoire distinct. - Désérialisez les fichiers de snapshot successivement. Lors de la fusion, recalculez les valeurs
numChildrenpour éviter les conflits d’ID de nœud entre les espaces de noms provenant de différents clusters source. - Écrivez la sortie fusionnée dans le répertoire cible des snapshots ClickHouse Keeper.
Gestion du chiffrement et des ACL
ClickHouse Keeper prend en charge les mêmes schémas d’ACL que ZooKeeper (world, auth, digest). La façon de gérer les ACL pendant la conversion dépend de votre configuration ZooKeeper :
- Entièrement chiffré ou entièrement non chiffré : convertissez directement. Le convertisseur conserve les informations d’ACL existantes.
- Partiellement chiffré : avant la conversion, accordez des privilèges de super-administrateur à un compte, puis supprimez les ACL avec
setAcl -Rsur les chemins concernés. Convertissez, puis réactivez le chiffrement dans ClickHouse Keeper si nécessaire.
Vérification de la migration
Après avoir démarré ClickHouse Keeper et redémarré ClickHouse, comparez vos métriques clés au niveau de référence d’avant la migration pour confirmer que celle-ci a réussi.
Lors de la consolidation de plusieurs clusters ZooKeeper, faites la distinction entre :
- Chemins communs : chemins présents dans plusieurs clusters sources avec des données identiques — ils doivent être dédupliqués dans la sortie fusionnée.
- Chemins distincts : chemins qui n’existent que dans des clusters spécifiques (par exemple, sous
/clickhouse/tablespour chaque groupe de shards) — ils doivent être conservés depuis la source appropriée.
Évitez de parcourir directement de grands arbres ZooKeeper pour les comparer. À la place, écrivez tous les chemins convertis dans un fichier pendant la conversion.
Ajustements après migration
Après la migration, pensez à ajuster ces paramètres pour les clusters de plus grande taille ou un débit plus élevé :
| Paramètre | Par défaut | Recommandé | Notes |
|---|---|---|---|
max_requests_batch_size |
100 |
10000 |
Augmentez cette valeur pour les clusters avec un nombre élevé de parts ou de nombreux shards |
force_sync |
true |
false |
Les écritures de logs asynchrones améliorent le débit |
compress_logs |
false |
true |
Compresse les fichiers de log Raft afin de réduire les E/S disque |
compress_snapshots_with_zstd_format |
true |
— | Déjà activé par défaut ; compresse les instantanés avec zstd |
Ces paramètres se configurent sous coordination_settings dans votre configuration de Keeper.
Récupération après la perte du quorum
Comme ClickHouse Keeper utilise Raft, il peut tolérer un certain nombre de pannes de nœuds en fonction de la taille du cluster. Par exemple, pour un cluster de 3 nœuds, il continuera à fonctionner correctement si un seul nœud tombe en panne.
La configuration du cluster peut être modifiée dynamiquement, mais il existe certaines limitations. La reconfiguration repose elle aussi sur Raft. Ainsi, pour ajouter ou supprimer un nœud du cluster, vous devez disposer d’un quorum. Si vous perdez trop de nœuds de votre cluster en même temps, sans possibilité de les redémarrer, Raft cessera de fonctionner et ne vous permettra plus de reconfigurer votre cluster de manière classique.
Néanmoins, ClickHouse Keeper dispose d’un mode de récupération qui vous permet de reconfigurer de force votre cluster avec un seul nœud. Vous ne devez y recourir qu’en dernier recours si vous ne pouvez pas redémarrer vos nœuds ni lancer une nouvelle instance sur le même point de terminaison.
Points importants à noter avant de continuer :
- Assurez-vous que les nœuds défaillants ne puissent plus se reconnecter au cluster.
- Ne démarrez aucun des nouveaux nœuds tant que cela n’est pas indiqué dans les étapes.
Une fois ces points vérifiés, vous devez procéder comme suit :
- Choisissez un seul nœud Keeper pour en faire votre nouveau leader. Gardez à l’esprit que les données de ce nœud seront utilisées pour l’ensemble du cluster. Nous vous recommandons donc d’utiliser un nœud dont l’état est le plus à jour possible.
- Avant toute autre action, effectuez une sauvegarde des répertoires
log_storage_pathetsnapshot_storage_pathdu nœud sélectionné. - Reconfigurez le cluster sur tous les nœuds que vous souhaitez utiliser.
- Envoyez la commande à quatre lettres
rcvrau nœud choisi, ce qui fera passer le nœud en mode de récupération, OU arrêtez l’instance Keeper sur le nœud choisi et redémarrez-la avec l’argument--force-recovery. - Démarrez ensuite, un par un, les instances Keeper sur les nouveaux nœuds, en vous assurant que
mntrrenvoiefollowerpourzk_server_stateavant de démarrer le suivant. - En mode de récupération, le nœud leader renverra un message d’erreur pour la commande
mntrjusqu’à ce qu’il atteigne le quorum avec les nouveaux nœuds, et il refusera toutes les requêtes du client et des followers. - Une fois le quorum atteint, le nœud leader reviendra à un fonctionnement normal et acceptera toutes les requêtes via Raft ; vérifiez-le avec
mntr, qui doit renvoyerleaderpourzk_server_state.
Utiliser des disques avec Keeper
Keeper prend en charge un sous-ensemble des disques externes pour stocker les snapshot, les fichier de log et le fichier d'état.
Les types de disques pris en charge sont :
- s3_plain
- s3
- local
Voici un exemple de définitions de disques contenues dans une configuration.
<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>Pour utiliser un disque pour les logs, le paramètre keeper_server.log_storage_disk doit être défini sur le nom du disque.
Pour utiliser un disque pour les snapshot, le paramètre keeper_server.snapshot_storage_disk doit être défini sur le nom du disque.
De plus, keeper_server.latest_log_storage_disk peut être utilisé pour les logs les plus récents et keeper_server.latest_snapshot_storage_disk pour les snapshot les plus récents.
Dans ce cas, Keeper déplacera automatiquement les fichiers vers les disques appropriés lors de la création de nouveaux logs ou snapshot.
Pour utiliser un disque pour le fichier d'état, le paramètre keeper_server.state_storage_disk doit être défini sur le nom du disque.
Le déplacement de fichiers entre disques est sûr et il n'y a aucun risque de perte de données si Keeper s'arrête au milieu du transfert. Tant que le fichier n'a pas été entièrement déplacé vers le nouveau disque, il n'est pas supprimé de l'ancien.
Lorsque keeper_server.coordination_settings.force_sync est défini sur true (true par défaut), Keeper ne peut pas garantir certaines propriétés pour tous les types de disques.
À l'heure actuelle, seuls les disques de type local prennent en charge la synchronisation persistante.
Si force_sync est utilisé, log_storage_disk doit être un disque local si latest_log_storage_disk n'est pas utilisé.
Si latest_log_storage_disk est utilisé, il doit toujours être un disque local.
Si force_sync est désactivé, des disques de tout type peuvent être utilisés dans n'importe quelle configuration.
Voici à quoi pourrait ressembler une configuration de stockage possible pour une instance Keeper :
<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>Cette instance stockera tous les logs, sauf les plus récents, sur le disque log_s3_plain, tandis que le log le plus récent sera stocké sur le disque log_local.
La même logique s'applique aux snapshot : tous les snapshot, sauf les plus récents, seront stockés sur le disque snapshot_s3_plain, tandis que le snapshot le plus récent sera stocké sur le disque snapshot_local.
Modifier la configuration des disques
Si une configuration de disques hiérarchisée est définie (avec des disques distincts pour les fichiers les plus récents), Keeper essaiera de déplacer automatiquement les fichiers vers les disques appropriés au démarrage. La même garantie s’applique que précédemment : tant que le fichier n’a pas été entièrement déplacé vers le nouveau disque, il n’est pas supprimé de l’ancien. Il est donc possible d’effectuer plusieurs redémarrages en toute sécurité.
S’il est nécessaire de déplacer des fichiers vers un disque entièrement nouveau (ou de passer d’une configuration à 2 disques à une configuration à disque unique), il est possible d’utiliser plusieurs définitions de keeper_server.old_snapshot_storage_disk et keeper_server.old_log_storage_disk.
La configuration suivante montre comment passer de la précédente configuration à 2 disques à une toute nouvelle configuration à disque unique :
<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>Au démarrage, tous les fichiers de log seront déplacés depuis log_local et log_s3_plain vers le disque log_local2.
De même, tous les fichiers d’instantané seront déplacés depuis snapshot_local et snapshot_s3_plain vers le disque snapshot_local2.
Configuration du cache des logs
Afin de minimiser la quantité de données lues sur le disque, Keeper met les entrées de journal en cache en mémoire. Si les requêtes sont volumineuses, les entrées de journal consomment trop de mémoire ; le volume de logs mis en cache est donc plafonné. La limite du cache des derniers logs est définie par :
latest_logs_cache_size_threshold- taille totale des derniers logs stockés dans le cache
Si la valeur par défaut est trop élevée, vous pouvez réduire l'utilisation de la mémoire en diminuant cette valeur de configuration.
Les entrées de journal nécessaires à la validation suivante sont fournies par un lecteur de prélecture décodé, dont la taille est définie par
log_readahead_commit_window_bytes (0 désactive la prélecture lors de la validation). Ce paramètre remplace les paramètres
obsolètes commit_logs_cache_size_threshold et commit_logs_cache_entry_count_threshold,
conservés uniquement pour assurer la compatibilité de configuration (le premier est toujours associé à log_readahead_commit_window_bytes si
celui-ci n'est pas défini ; le second n'a aucun effet). Le même mécanisme de prélecture prend également en charge les lectures de rattrapage de
réplication des nœuds followers lorsque log_readahead_enabled est défini sur true ; consultez
log_readahead_window_bytes, log_readahead_max_peer_readers, log_readahead_eviction_timeout_ms,
log_readahead_pool_threads, log_readahead_serve_wait_timeout_ms et log_readahead_chunk_size
dans les paramètres de coordination interne pour les options de réglage
côté pair.
Prometheus
Keeper peut exposer des métriques pour leur collecte par Prometheus.
Paramètres :
endpoint– Endpoint HTTP de collecte des métriques par le serveur Prometheus. Doit commencer par '/'.port– Port deendpoint.metrics– Indicateur qui active l’exposition des métriques de la table system.metrics.events– Indicateur qui active l’exposition des métriques de la table system.events.asynchronous_metrics– Indicateur qui active l’exposition des valeurs actuelles des métriques de la table system.asynchronous_metrics.
Exemple
<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>Vérifiez (remplacez 127.0.0.1 par l’adresse IP ou le nom d’hôte de votre serveur ClickHouse) :
curl 127.0.0.1:9363/metricsVoir aussi l’intégration Prometheus de ClickHouse Cloud.
Guide d’utilisation de ClickHouse Keeper
Ce guide présente une configuration simple et minimale de ClickHouse Keeper, ainsi qu’un exemple montrant comment tester des opérations distribuées. Cet exemple s’appuie sur 3 nœuds sous Linux.
Configurer les nœuds avec les paramètres de Keeper
-
Installez 3 instances de ClickHouse sur 3 hôtes (
chnode1,chnode2,chnode3). (Consultez le Quick Start pour plus de détails sur l’installation de ClickHouse.) -
Sur chaque nœud, ajoutez l’entrée suivante pour permettre les communications externes via l’interface réseau.
<listen_host>0.0.0.0</listen_host> -
Ajoutez la configuration ClickHouse Keeper suivante sur les trois serveurs en mettant à jour le paramètre
<server_id>pour chacun d’eux ; pourchnode1, la valeur serait1, pourchnode2, ce serait2, etc.<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>Voici les paramètres de base utilisés ci-dessus :
Paramètre Description Exemple tcp_port port à utiliser par les clients de Keeper 9181, équivalent par défaut de 2181 comme dans ZooKeeper server_id identifiant de chaque serveur ClickHouse Keeper utilisé dans la configuration Raft 1 coordination_settings section des paramètres tels que les timeouts timeouts: 10000, log level: trace server définition du serveur participant liste de la définition de chaque serveur raft_configuration paramètres de chaque serveur dans le cluster Keeper serveur et paramètres pour chacun id identifiant numérique du serveur pour les services Keeper 1 hostname nom d’hôte, IP ou FQDN de chaque serveur du cluster Keeper chnode1.domain.comport port d’écoute pour les connexions inter-serveurs de Keeper 9234 -
Activez le composant Zookeeper. Il utilisera le moteur 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>Voici les paramètres de base utilisés ci-dessus :
Paramètre Description Exemple node liste des nœuds pour les connexions à ClickHouse Keeper entrée de configuration pour chaque serveur host nom d’hôte, IP ou FQDN de chaque nœud ClickHouse Keeper chnode1.domain.comport port client de ClickHouse Keeper 9181 -
Redémarrez ClickHouse et vérifiez que chaque instance de Keeper est en fonctionnement. Exécutez la commande suivante sur chaque serveur. La commande
ruokrenvoieimoksi Keeper est en fonctionnement et sain :# echo ruok | nc localhost 9181; echo imok -
La base de données
systemcomporte une table nomméezookeeper, qui contient les détails de vos instances ClickHouse Keeper. Affichons la table :SELECT * FROM system.zookeeper WHERE path IN ('/', '/clickhouse')Le tableau ressemble à ceci :
┌─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 │ └────────────┴───────┴───────┴───────┴─────────────────────┴─────────────────────┴─────────┴──────────┴──────────┴────────────────┴────────────┴─────────────┴───────┴─────────────┘
Configurer un cluster dans ClickHouse
-
Configurons un cluster simple avec 2 shards et une seule réplique sur 2 des nœuds. Le troisième nœud sera utilisé pour atteindre le quorum requis par ClickHouse Keeper. Mettez à jour la configuration sur
chnode1etchnode2. Le cluster suivant définit 1 shard sur chaque nœud, pour un total de 2 shards sans réplication. Dans cet exemple, une partie des données sera sur un nœud et une autre sur l’autre nœud :<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>Paramètre Description Exemple shard liste des répliques dans la définition du cluster liste des répliques pour chaque shard replica liste des paramètres de chaque réplique entrée de configuration pour chaque réplique host nom d’hôte, IP ou FQDN du serveur qui hébergera un shard de réplique chnode1.domain.comport port utilisé pour communiquer via le protocole TCP natif 9000 user nom d’utilisateur qui sera utilisé pour s’authentifier auprès des instances du cluster default password mot de passe de l’utilisateur défini pour autoriser les connexions aux instances du cluster ClickHouse123! -
Redémarrez ClickHouse et vérifiez que le cluster a bien été créé :
SHOW clusters;Vous devriez voir votre cluster :
┌─cluster───────┐ │ cluster_2S_1R │ └───────────────┘
Créer et tester une table distribuée
-
Créez une nouvelle base de données sur le nouveau cluster à l’aide du client ClickHouse sur
chnode1. La clauseON CLUSTERcrée automatiquement la base de données sur les deux nœuds.CREATE DATABASE db1 ON CLUSTER 'cluster_2S_1R'; -
Créez une nouvelle table dans la base de données
db1. Là encore,ON CLUSTERcrée la table sur les deux nœuds.CREATE TABLE db1.table1 on cluster 'cluster_2S_1R' ( `id` UInt64, `column1` String ) ENGINE = MergeTree ORDER BY column1 -
Sur le nœud
chnode1, ajoutez quelques lignes :INSERT INTO db1.table1 (id, column1) VALUES (1, 'abc'), (2, 'def') -
Ajoutez quelques lignes sur le nœud
chnode2:INSERT INTO db1.table1 (id, column1) VALUES (3, 'ghi'), (4, 'jkl') -
Notez que l’exécution d’une instruction
SELECTsur chaque nœud n’affiche que les données présentes sur ce nœud. Par exemple, surchnode1:SELECT * FROM db1.table1Query id: 7ef1edbc-df25-462b-a9d4-3fe6f9cb0b6d ┌─id─┬─column1─┐ │ 1 │ abc │ │ 2 │ def │ └────┴─────────┘ 2 rows in set. Elapsed: 0.006 sec.Sur
chnode2: -
SELECT * FROM db1.table1Query id: c43763cc-c69c-4bcc-afbe-50e764adfcbf ┌─id─┬─column1─┐ │ 3 │ ghi │ │ 4 │ jkl │ └────┴─────────┘ -
Vous pouvez créer une table
Distributedpour représenter les données réparties sur les deux shards. Les tables utilisant le moteur de tableDistributedne stockent pas leurs propres données, mais permettent le traitement distribué des requêtes sur plusieurs serveurs. Les lectures accèdent à tous les shards, et les écritures peuvent être réparties entre eux. Exécutez la requête suivante surchnode1:CREATE TABLE db1.dist_table ( id UInt64, column1 String ) ENGINE = Distributed(cluster_2S_1R,db1,table1) -
Notez qu’une requête sur
dist_tablerenvoie les quatre lignes de données provenant des deux 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.
Résumé
Ce guide a montré comment configurer un cluster à l’aide de ClickHouse Keeper. Avec ClickHouse Keeper, vous pouvez configurer des clusters et définir des tables distribuées qui peuvent être répliquées sur plusieurs shards.
Configuration de ClickHouse Keeper avec des chemins uniques
Description
Cet article explique comment utiliser la macro intégrée {uuid}
pour créer des entrées uniques dans ClickHouse Keeper ou ZooKeeper. Des
chemins uniques sont utiles lorsque vous créez et supprimez des tables
fréquemment, car cela évite d'avoir à attendre plusieurs minutes que le nettoyage automatique de Keeper
supprime les entrées de chemin, puisque chaque fois qu'un chemin est créé, un nouveau uuid est utilisé
dans ce chemin ; les chemins ne sont jamais réutilisés.
Environnement d’exemple
Un cluster à trois nœuds, configuré avec ClickHouse Keeper sur les trois nœuds et ClickHouse sur deux d’entre eux. Cela donne à ClickHouse Keeper trois nœuds (y compris un nœud d’arbitrage), ainsi qu’un seul shard ClickHouse composé de deux répliques.
| node | description |
|---|---|
chnode1.marsnet.local |
nœud de données - cluster cluster_1S_2R |
chnode2.marsnet.local |
nœud de données - cluster cluster_1S_2R |
chnode3.marsnet.local |
nœud d’arbitrage ClickHouse Keeper |
Exemple de configuration du 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>Procédures pour configurer les tables afin d’utiliser {uuid}
- Configurez les macros sur chaque serveur exemple pour le serveur 1 :
<macros>
<shard>1</shard>
<replica>replica_1</replica>
</macros>- Créer une base de données
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 │
└───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘- Créez une table sur le cluster à l’aide des macros et de
{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 │
└───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘- Créez une table distribuée
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 │
└───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘Test
- Insérez des données dans le premier nœud (par exemple
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.- Insérez des données sur le deuxième nœud (par ex.,
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.- Consulter les enregistrements à l’aide d’une table distribuée
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.Alternatives
Le chemin de réplication par défaut peut être défini à l’avance à l’aide de macros, en utilisant également {uuid}
- Définir le chemin par défaut pour les tables sur chaque nœud
<default_replica_path>/clickhouse/tables/{shard}/db_uuid/{uuid}</default_replica_path>
<default_replica_name>{replica}</default_replica_name>- Créez la table sans paramètres explicites :
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.- Vérifiez qu’il a bien repris les paramètres de la configuration par défaut
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.Dépannage
Exemple de commande pour obtenir des informations sur la table et son UUID :
SELECT * FROM system.tables
WHERE database = 'db_uuid' AND name = 'uuid_table1';Exemple de commande pour obtenir des informations sur la table dans ZooKeeper à l’aide de l’UUID de la table ci-dessus
SELECT * FROM system.zookeeper
WHERE path = '/clickhouse/tables/1/db_uuid/9e8a3cc2-0dec-4438-81a7-c3e63ce2a1cf/replicas';Pour vérifier :
Par exemple,
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.Reconfiguration dynamique de ClickHouse Keeper
Description
ClickHouse Keeper prend en charge partiellement la commande ZooKeeper reconfig
pour la reconfiguration dynamique du cluster si keeper_server.enable_reconfiguration est activé.
Un nœud virtuel /keeper/config contient la dernière configuration du cluster validée au format suivant :
server.id = server_host:server_port[;server_type][;server_priority]
server.id2 = ...
...- Chaque entrée de serveur est séparée par un saut de ligne.
server_typevaut soitparticipant, soitlearner(learner ne participe pas à l’élection du leader).server_priorityest un entier positif ou nul indiquant quels nœuds doivent être prioritaires lors de l’élection du leader. Une priorité de 0 signifie qu’un serveur ne sera jamais leader.
Exemple :
:) get /keeper/config
server.1=zoo1:9234;participant;1
server.2=zoo2:9234;participant;1
server.3=zoo3:9234;participant;1Vous pouvez utiliser la commande reconfig pour ajouter de nouveaux serveurs, supprimer des serveurs existants et modifier la priorité de serveurs existants. Voici quelques exemples (avec clickhouse-keeper-client) :
# Add two new servers
reconfig add "server.5=localhost:123,server.6=localhost:234;learner"
# Remove two other servers
reconfig remove "3,4"
# Change existing server priority to 8
reconfig add "server.5=localhost:5123;participant;8"Et voici des exemples pour kazoo :
# Add two new servers, remove two other servers
reconfig(joining="server.5=localhost:123,server.6=localhost:234;learner", leaving="3,4")
# Change existing server priority to 8
reconfig(joining="server.5=localhost:5123;participant;8", leaving=None)Les serveurs dans joining doivent être au format de serveur décrit ci-dessus. Les entrées de serveur doivent être séparées par des virgules.
Lors de l'ajout de nouveaux serveurs, vous pouvez omettre server_priority (la valeur par défaut est 1) et server_type (la valeur par défaut
est participant).
Si vous souhaitez modifier la priorité d'un serveur existant, ajoutez-le à joining avec la priorité cible.
L'hôte, le port et le type du serveur doivent correspondre à ceux de la configuration du serveur existante.
Les serveurs sont ajoutés et supprimés dans l'ordre d'apparition dans joining et leaving.
Toutes les mises à jour de joining sont traitées avant celles de leaving.
Il existe quelques points à connaître concernant l'implémentation de la reconfiguration de Keeper :
-
Seule la reconfiguration incrémentielle est prise en charge. Les requêtes avec un
new_membersnon vide sont refusées.L'implémentation de ClickHouse Keeper s'appuie sur l'API NuRaft pour modifier dynamiquement les membres. NuRaft permet d'ajouter un seul serveur ou de supprimer un seul serveur, un à la fois. Cela signifie que chaque modification de la configuration (chaque partie de
joining, chaque partie deleaving) doit être décidée séparément. Il n'existe donc pas de reconfiguration en bloc, car cela serait trompeur pour les utilisateurs finaux.Il n'est pas non plus possible de modifier le type de serveur (participant/learner), car NuRaft ne le prend pas en charge, et le seul moyen serait de supprimer puis de rajouter le serveur, ce qui serait là encore trompeur.
-
Vous ne pouvez pas utiliser la valeur
znodestatrenvoyée. -
Le champ
from_versionn'est pas utilisé. Toutes les requêtes avecfrom_versiondéfini sont refusées. Cela est dû au fait que/keeper/configest un nœud virtuel, ce qui signifie qu'il n'est pas stocké dans le stockage persistant, mais généré à la volée à partir de la configuration de nœud spécifiée pour chaque requête. Cette décision a été prise afin de ne pas dupliquer les données, puisque NuRaft stocke déjà cette configuration. -
Contrairement à ZooKeeper, il n'existe aucun moyen d'attendre la reconfiguration du cluster en soumettant une commande
sync. La nouvelle configuration sera à terme appliquée, mais sans aucune garantie de délai. -
La commande
reconfigpeut échouer pour diverses raisons. Vous pouvez vérifier l'état du cluster et voir si la mise à jour a été appliquée.
Conversion d’un Keeper mono-nœud en cluster
Il est parfois nécessaire d’étendre un nœud Keeper expérimental pour en faire un cluster. Voici la procédure à suivre, étape par étape, pour un cluster de 3 nœuds :
- IMPORTANT : les nouveaux nœuds doivent être ajoutés par lots inférieurs au quorum actuel, sinon ils éliront un leader entre eux. Dans cet exemple, ils sont ajoutés un par un.
- Le nœud Keeper existant doit avoir le paramètre de configuration
keeper_server.enable_reconfigurationactivé. - Démarrez un deuxième nœud avec la nouvelle configuration complète du cluster Keeper.
- Une fois démarré, ajoutez-le au nœud 1 à l’aide de
reconfig. - Démarrez ensuite un troisième nœud et ajoutez-le de la même manière à l’aide de
reconfig. - Mettez à jour la configuration de
clickhouse-serveren y ajoutant le nouveau nœud Keeper, puis redémarrez-le pour appliquer les modifications. - Mettez à jour la configuration Raft du nœud 1 et, si nécessaire, redémarrez-le.
Pour vous familiariser avec le processus, consultez ce dépôt sandbox.
Fonctionnalités non prises en charge
Bien que ClickHouse Keeper vise une compatibilité totale avec ZooKeeper, certaines fonctionnalités ne sont pas encore implémentées (même si leur développement est en cours) :
createne prend pas en charge le retour de l'objetStatcreatene prend pas en charge TTLaddWatchne fonctionne pas avec les watchesPERSISTENTremoveWatchetremoveAllWatchesne sont pas pris en chargesetWatchesn'est pas pris en charge- La création de znodes de type
CONTAINERn'est pas prise en charge - L'authentification SASL n'est pas prise en charge