Dans ClickHouse Cloud, la réplication est gérée pour vous. Créez vos tables sans ajouter d’arguments. Par exemple, dans le texte ci-dessous, vous remplaceriez :par :
- ReplicatedSummingMergeTree
- ReplicatedCoalescingMergeTree
- ReplicatedVersionedCollapsingMergeTree
- ReplicatedCollapsingMergeTree
- ReplicatedGraphiteMergeTree
- ReplicatedMergeTree
- ReplicatedReplacingMergeTree
- ReplicatedAggregatingMergeTree
INSERT et ALTER sont répliquées (pour plus d’informations, voir la documentation de ALTER.
Les requêtes CREATE, DROP, ATTACH, DETACH et RENAME sont exécutées sur un seul serveur et ne sont pas répliquées :
- La requête
CREATE TABLEcrée une nouvelle table pouvant être répliquée sur le serveur où la requête est exécutée. Si cette table existe déjà sur d’autres serveurs, elle ajoute une nouvelle réplique. - La requête
DROP TABLEsupprime la réplique située sur le serveur où la requête est exécutée. - La requête
RENAMErenomme la table sur l’une des répliques. Autrement dit, les tables répliquées peuvent porter des noms différents selon les répliques.
Ne négligez pas la configuration de sécurité. ClickHouse prend en charge le schéma ACL
digest du sous-système de sécurité de ZooKeeper.SELECT, car la réplication n’affecte pas les performances de SELECT et les requêtes s’exécutent tout aussi rapidement que sur des tables non répliquées. Lors de l’interrogation de tables distribuées répliquées, le comportement de ClickHouse est contrôlé par les paramètres max_replica_delay_for_distributed_queries et fallback_to_stale_replicas_for_distributed_queries.
Pour chaque requête INSERT, environ dix entrées sont ajoutées à ZooKeeper au travers de plusieurs transactions. (Plus précisément, cela s’applique à chaque bloc de données inséré ; une requête INSERT contient un bloc, ou un bloc par max_insert_block_size = 1048576 lignes.) Cela entraîne des latences légèrement plus élevées pour INSERT par rapport aux tables non répliquées. Mais si vous suivez les recommandations consistant à insérer les données par lots, à raison de pas plus d’un INSERT par seconde, cela ne pose aucun problème. L’ensemble du cluster ClickHouse utilisant un cluster ZooKeeper pour la coordination prend en charge au total plusieurs centaines d’INSERTs par seconde. Le débit des insertions de données (le nombre de lignes par seconde) est tout aussi élevé que pour les données non répliquées.
Pour les très grands clusters, vous pouvez utiliser différents clusters ZooKeeper pour différents shards. Cependant, d’après notre expérience, cela ne s’est pas révélé nécessaire sur des clusters de production d’environ 300 serveurs.
La réplication est asynchrone et multi-maître. Les requêtes INSERT (ainsi que ALTER) peuvent être envoyées à n’importe quel serveur disponible. Les données sont insérées sur le serveur où la requête est exécutée, puis elles sont copiées vers les autres serveurs. Comme elle est asynchrone, les données récemment insérées apparaissent sur les autres répliques avec une certaine latence. Si une partie des répliques n’est pas disponible, les données sont écrites lorsqu’elles redeviennent disponibles. Si une réplique est disponible, la latence correspond au temps nécessaire pour transférer le bloc de données compressées sur le réseau. Le nombre de threads effectuant des tâches d’arrière-plan pour les tables répliquées peut être défini par le paramètre background_schedule_pool_size.
Le moteur ReplicatedMergeTree utilise un pool de threads distinct pour les fetches répliqués. La taille du pool est limitée par le paramètre background_fetches_pool_size, qui peut être ajusté après redémarrage du serveur.
Par défaut, une requête INSERT attend uniquement la confirmation de l’écriture des données par une seule réplique. Si les données n’ont été écrites avec succès que sur une seule réplique et que le serveur hébergeant cette réplique cesse d’exister, les données stockées seront perdues. Pour obtenir la confirmation des écritures de données depuis plusieurs répliques, utilisez l’option insert_quorum.
Chaque bloc de données est écrit de manière atomique. La requête INSERT est divisée en blocs allant jusqu’à max_insert_block_size = 1048576 lignes. En d’autres termes, si la requête INSERT contient moins de 1048576 lignes, elle est effectuée de manière atomique.
Les blocs de données sont dédupliqués. En cas d’écritures multiples du même bloc de données (des blocs de même taille contenant les mêmes lignes dans le même ordre), le bloc n’est écrit qu’une seule fois. L’objectif est de gérer les défaillances réseau, lorsque l’application cliente ne sait pas si les données ont été écrites dans la base de données, de sorte que la requête INSERT peut simplement être relancée. Peu importe à quelle réplique les INSERTs contenant des données identiques ont été envoyés. Les INSERTs sont idempotents. Les paramètres de déduplication sont contrôlés par les paramètres serveur merge_tree.
Pendant la réplication, seules les données source à insérer sont transférées sur le réseau. Les transformations ultérieures des données (merging) sont coordonnées et effectuées de la même manière sur toutes les répliques. Cela minimise l’utilisation du réseau, ce qui signifie que la réplication fonctionne bien lorsque les répliques se trouvent dans différents datacenters. (Notez que la duplication des données dans différents datacenters est l’objectif principal de la réplication.)
Vous pouvez avoir autant de répliques des mêmes données que vous le souhaitez. D’après notre expérience, une solution relativement fiable et pratique consiste à utiliser une double réplication en production, chaque serveur utilisant RAID-5 ou RAID-6 (et RAID-10 dans certains cas).
Le système surveille la synchronisation des données sur les répliques et est capable de récupérer après une défaillance. Le failover est automatique (pour de faibles écarts de données) ou semi-automatique (lorsque les données diffèrent trop, ce qui peut indiquer une erreur de configuration).
Création de tables répliquées
Dans ClickHouse Cloud, la réplication est gérée automatiquement.Créez des tables avec
MergeTree, sans arguments de réplication. Le système réécrit automatiquement MergeTree en SharedMergeTree pour assurer la réplication et la distribution des données.Évitez d’utiliser ReplicatedMergeTree ou de spécifier des paramètres de réplication, car celle-ci est gérée par la plateforme.Paramètres de Replicated*MergeTree
Exemple :
{}. Les valeurs de substitution proviennent de la section macros du fichier de configuration.
Exemple :
/clickhouse/tables/ est le préfixe commun. Nous recommandons d’utiliser exactement celui-ci.
{shard} sera remplacé par l’identifiant du shard.
table_name est le nom du nœud de la table dans ClickHouse Keeper. Il est recommandé de le faire correspondre au nom de la table. Il est défini explicitement, car contrairement au nom de la table, il ne change pas après une requête RENAME.
ASTUCE : vous pouvez également ajouter un nom de base de données devant table_name. Par ex. db_name.table_name
Les deux substitutions intégrées {database} et {table} peuvent être utilisées ; elles sont remplacées respectivement par le nom de la base de données et le nom de la table (sauf si ces macros sont définies dans la section macros). Le chemin ZooKeeper peut donc être spécifié comme '/clickhouse/tables/{shard}/{database}/{table}'.
Soyez prudent lors du renommage des tables si vous utilisez ces substitutions intégrées. Le chemin dans ClickHouse Keeper ne peut pas être modifié et, lorsque la table est renommée, les macros se résoudront en un chemin différent ; la table fera alors référence à un chemin qui n’existe pas dans ClickHouse Keeper et basculera en mode lecture seule.
Le nom de la réplique identifie les différentes répliques d’une même table. Vous pouvez utiliser pour cela le nom du serveur, comme dans l’exemple. Le nom doit simplement être unique au sein de chaque shard.
Vous pouvez définir les paramètres explicitement au lieu d’utiliser des substitutions. Cela peut être pratique pour les tests et pour configurer de petits clusters. Cependant, vous ne pouvez pas utiliser de requêtes DDL distribuées (ON CLUSTER) dans ce cas.
Lorsque vous travaillez avec de grands clusters, nous recommandons d’utiliser des substitutions, car elles réduisent le risque d’erreur.
Vous pouvez spécifier des arguments par défaut pour le moteur de table Replicated dans le fichier de configuration du serveur. Par exemple :
CREATE TABLE sur chaque réplique. Cette requête crée une nouvelle table répliquée ou ajoute une nouvelle réplique à une table existante.
Si vous ajoutez une nouvelle réplique alors que la table contient déjà des données sur d’autres répliques, les données seront copiées à partir des autres répliques vers la nouvelle après l’exécution de la requête. En d’autres termes, la nouvelle réplique se synchronise avec les autres.
Pour supprimer une réplique, exécutez DROP TABLE. Cependant, une seule réplique est supprimée : celle qui se trouve sur le serveur sur lequel vous exécutez la requête.
Récupération après des pannes
INSERT, ou si une erreur se produit lors d’une interaction avec ClickHouse Keeper, une exception est levée.
Après s’être connecté à ClickHouse Keeper, le système vérifie si l’ensemble des données présentes sur le système de fichiers local correspond à l’ensemble de données attendu (ClickHouse Keeper stocke ces informations). S’il existe de légères incohérences, le système les résout en synchronisant les données avec les répliques.
Si le système détecte des parties de données endommagées (avec une taille de fichier incorrecte) ou des parts non reconnues (parts écrites sur le système de fichiers mais non enregistrées dans ClickHouse Keeper), il les déplace vers le sous-répertoire detached (elles ne sont pas supprimées). Toutes les parts manquantes sont copiées depuis les répliques.
Notez que ClickHouse n’effectue aucune action destructive, comme supprimer automatiquement une grande quantité de données.
Lorsque le serveur démarre (ou établit une nouvelle session avec ClickHouse Keeper), il vérifie uniquement le nombre et la taille de tous les fichiers. Si la taille des fichiers correspond mais que des octets ont été modifiés quelque part au milieu, cela n’est pas détecté immédiatement, mais seulement lors d’une tentative de lecture des données pour une requête SELECT. La requête lève une exception signalant une somme de contrôle non concordante ou une taille incorrecte d’un bloc compressé. Dans ce cas, les parties de données sont ajoutées à la file de vérification et copiées depuis les répliques si nécessaire.
Si l’ensemble de données local diffère trop de l’ensemble attendu, un mécanisme de sécurité se déclenche. Le serveur l’indique dans le journal et refuse de démarrer. Cela s’explique par le fait que ce cas peut indiquer une erreur de configuration, par exemple si une réplique sur un shard a été configurée par erreur comme une réplique sur un autre shard. Cependant, les seuils de ce mécanisme sont définis assez bas, et cette situation peut se produire lors d’une récupération normale après une panne. Dans ce cas, les données sont restaurées de manière semi-automatique - en “appuyant sur un bouton”.
Pour lancer la récupération, créez le nœud /path_to_table/replica_name/flags/force_restore_data dans ClickHouse Keeper avec n’importe quel contenu, ou exécutez la commande pour restaurer toutes les tables répliquées :
Récupération après une perte complète de données
- Installez ClickHouse sur le serveur. Définissez correctement les substitutions dans le fichier de configuration qui contient l’identifiant du shard et les répliques, si vous les utilisez.
- Si vous aviez des tables non répliquées qu’il faut recopier manuellement sur les serveurs, copiez leurs données depuis une réplique (dans le répertoire
/var/lib/clickhouse/data/db_name/table_name/). - Copiez les définitions de tables situées dans
/var/lib/clickhouse/metadata/depuis une réplique. Si un identifiant de shard ou de réplique est défini explicitement dans les définitions de tables, corrigez-le pour qu’il corresponde à cette réplique. (Sinon, démarrez le serveur et exécutez toutes les requêtesATTACH TABLEqui auraient dû se trouver dans les fichiers .sql de/var/lib/clickhouse/metadata/.) - Pour lancer la récupération, créez le nœud ClickHouse Keeper
/path_to_table/replica_name/flags/force_restore_dataavec n’importe quel contenu, ou exécutez la commande suivante pour restaurer toutes les tables répliquées :sudo -u clickhouse touch /var/lib/clickhouse/flags/force_restore_data
/path_to_table/replica_name), puis à recréer la réplique comme décrit dans « Creating replicated tables ».
Aucune limitation de bande passante réseau n’est appliquée pendant la récupération. Gardez-le à l’esprit si vous restaurez plusieurs répliques en même temps.
Conversion de MergeTree vers ReplicatedMergeTree
MergeTree pour désigner tous les moteurs de table de la famille MergeTree, comme pour ReplicatedMergeTree.
Si vous avez une table MergeTree répliquée manuellement, vous pouvez la convertir en table répliquée. Vous pouvez avoir besoin de le faire si vous avez déjà accumulé une grande quantité de données dans une table MergeTree et souhaitez maintenant activer la réplication.
L’instruction ATTACH TABLE … AS REPLICATED permet d’attacher une table MergeTree détachée en tant que ReplicatedMergeTree.
Une table MergeTree peut être convertie automatiquement au redémarrage du serveur si l’option convert_to_replicated est définie dans le chemin de données de la table (/store/xxx/xxxyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy/ pour une base de données Atomic).
Créez un fichier vide convert_to_replicated et la table sera chargée en tant que table répliquée au prochain redémarrage du serveur.
Cette requête peut être utilisée pour obtenir le chemin de données de la table. Si la table possède plusieurs chemins de données, vous devez utiliser le premier.
default_replica_path et default_replica_name.
Pour créer une table convertie sur les autres répliques, vous devrez spécifier explicitement son chemin dans le premier argument du moteur ReplicatedMergeTree. La requête suivante peut être utilisée pour récupérer ce chemin.
ReplicatedMergeTree en lui redonnant l’ancien nom.
Déplacez les données de l’ancienne table vers le sous-répertoire detached du répertoire contenant les données de la nouvelle table (/var/lib/clickhouse/data/db_name/table_name/).
Exécutez ensuite ALTER TABLE ATTACH PARTITION sur l’une des répliques pour ajouter ces parties de données à l’ensemble actif.
Conversion de ReplicatedMergeTree vers MergeTree
ReplicatedMergeTree détachée en tant que MergeTree sur un seul serveur.
Une autre méthode nécessite de redémarrer le serveur. Créez une table MergeTree avec un nom différent. Déplacez toutes les données du répertoire contenant les données de la table ReplicatedMergeTree vers le répertoire de données de la nouvelle table. Supprimez ensuite la table ReplicatedMergeTree, puis redémarrez le serveur.
Si vous souhaitez supprimer une table ReplicatedMergeTree sans démarrer le serveur :
- Supprimez le fichier
.sqlcorrespondant dans le répertoire des métadonnées (/var/lib/clickhouse/metadata/). - Supprimez le chemin correspondant dans ClickHouse Keeper (
/path_to_table/replica_name).
MergeTree, déplacer les données vers son répertoire, puis redémarrer le serveur.