Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

Réplication + mise à l’échelle

Dans cet exemple, vous allez apprendre à configurer un cluster ClickHouse simple qui assure à la fois la réplication et la montée en charge. Il se compose de deux shards et de deux répliques avec un cluster ClickHouse Keeper à 3 nœuds pour assurer la coordination et maintenir le quorum dans le cluster.

L’architecture du cluster que vous allez configurer est illustrée ci-dessous :

Schéma d’architecture pour 2 shards et 1 réplique

Prérequis

Configurer la structure de répertoires et l'environnement de test

Dans ce tutoriel, vous utiliserez Docker compose pour configurer le cluster ClickHouse. Cette configuration peut être adaptée pour fonctionner sur des machines locales séparées, des machines virtuelles ou des instances Cloud.

Exécutez les commandes suivantes pour configurer la structure de répertoires de cet exemple :

mkdir cluster_2S_2R
cd cluster_2S_2R

# Create clickhouse-keeper directories
for i in {01..03}; do
  mkdir -p fs/volumes/clickhouse-keeper-${i}/etc/clickhouse-keeper
done

# Create clickhouse-server directories
for i in {01..04}; do
  mkdir -p fs/volumes/clickhouse-${i}/etc/clickhouse-server
done

Ajoutez le fichier docker-compose.yml suivant dans le répertoire clickhouse-cluster :

docker-compose.ymlyaml
version: '3.8'
services:
  clickhouse-01:
    image: "clickhouse/clickhouse-server:latest"
    user: "101:101"
    container_name: clickhouse-01
    hostname: clickhouse-01
    volumes:
      - ${PWD}/fs/volumes/clickhouse-01/etc/clickhouse-server/config.d/config.xml:/etc/clickhouse-server/config.d/config.xml
      - ${PWD}/fs/volumes/clickhouse-01/etc/clickhouse-server/users.d/users.xml:/etc/clickhouse-server/users.d/users.xml
    ports:
      - "127.0.0.1:8123:8123"
      - "127.0.0.1:9000:9000"
    depends_on:
      - clickhouse-keeper-01
      - clickhouse-keeper-02
      - clickhouse-keeper-03
  clickhouse-02:
    image: "clickhouse/clickhouse-server:latest"
    user: "101:101"
    container_name: clickhouse-02
    hostname: clickhouse-02
    volumes:
      - ${PWD}/fs/volumes/clickhouse-02/etc/clickhouse-server/config.d/config.xml:/etc/clickhouse-server/config.d/config.xml
      - ${PWD}/fs/volumes/clickhouse-02/etc/clickhouse-server/users.d/users.xml:/etc/clickhouse-server/users.d/users.xml
    ports:
      - "127.0.0.1:8124:8123"
      - "127.0.0.1:9001:9000"
    depends_on:
      - clickhouse-keeper-01
      - clickhouse-keeper-02
      - clickhouse-keeper-03
  clickhouse-03:
    image: "clickhouse/clickhouse-server:latest"
    user: "101:101"
    container_name: clickhouse-03
    hostname: clickhouse-03
    volumes:
      - ${PWD}/fs/volumes/clickhouse-03/etc/clickhouse-server/config.d/config.xml:/etc/clickhouse-server/config.d/config.xml
      - ${PWD}/fs/volumes/clickhouse-03/etc/clickhouse-server/users.d/users.xml:/etc/clickhouse-server/users.d/users.xml
    ports:
      - "127.0.0.1:8125:8123"
      - "127.0.0.1:9002:9000"
    depends_on:
      - clickhouse-keeper-01
      - clickhouse-keeper-02
      - clickhouse-keeper-03
  clickhouse-04:
    image: "clickhouse/clickhouse-server:latest"
    user: "101:101"
    container_name: clickhouse-04
    hostname: clickhouse-04
    volumes:
      - ${PWD}/fs/volumes/clickhouse-04/etc/clickhouse-server/config.d/config.xml:/etc/clickhouse-server/config.d/config.xml
      - ${PWD}/fs/volumes/clickhouse-04/etc/clickhouse-server/users.d/users.xml:/etc/clickhouse-server/users.d/users.xml
    ports:
      - "127.0.0.1:8126:8123"
      - "127.0.0.1:9003:9000"
    depends_on:
      - clickhouse-keeper-01
      - clickhouse-keeper-02
      - clickhouse-keeper-03
  clickhouse-keeper-01:
    image: "clickhouse/clickhouse-keeper:latest-alpine"
    user: "101:101"
    container_name: clickhouse-keeper-01
    hostname: clickhouse-keeper-01
    volumes:
      - ${PWD}/fs/volumes/clickhouse-keeper-01/etc/clickhouse-keeper/keeper_config.xml:/etc/clickhouse-keeper/keeper_config.xml
    ports:
      - "127.0.0.1:9181:9181"
  clickhouse-keeper-02:
    image: "clickhouse/clickhouse-keeper:latest-alpine"
    user: "101:101"
    container_name: clickhouse-keeper-02
    hostname: clickhouse-keeper-02
    volumes:
      - ${PWD}/fs/volumes/clickhouse-keeper-02/etc/clickhouse-keeper/keeper_config.xml:/etc/clickhouse-keeper/keeper_config.xml
    ports:
      - "127.0.0.1:9182:9181"
  clickhouse-keeper-03:
    image: "clickhouse/clickhouse-keeper:latest-alpine"
    user: "101:101"
    container_name: clickhouse-keeper-03
    hostname: clickhouse-keeper-03
    volumes:
      - ${PWD}/fs/volumes/clickhouse-keeper-03/etc/clickhouse-keeper/keeper_config.xml:/etc/clickhouse-keeper/keeper_config.xml
    ports:
      - "127.0.0.1:9183:9181"

Créez les sous-répertoires et fichiers suivants :

for i in {01..04}; do
  mkdir -p fs/volumes/clickhouse-${i}/etc/clickhouse-server/config.d
  mkdir -p fs/volumes/clickhouse-${i}/etc/clickhouse-server/users.d
  touch fs/volumes/clickhouse-${i}/etc/clickhouse-server/config.d/config.xml
  touch fs/volumes/clickhouse-${i}/etc/clickhouse-server/users.d/users.xml
done
  • Le répertoire config.d contient le fichier de configuration du serveur ClickHouse config.xml, dans lequel est définie la configuration personnalisée de chaque nœud ClickHouse. Cette configuration est fusionnée avec le fichier de configuration ClickHouse config.xml par défaut fourni avec chaque installation de ClickHouse.
  • Le répertoire users.d contient le fichier de configuration utilisateur users.xml, dans lequel est définie la configuration personnalisée des utilisateurs. Cette configuration est fusionnée avec le fichier de configuration ClickHouse users.xml par défaut fourni avec chaque installation de ClickHouse.

Configurer les nœuds ClickHouse

Configuration du serveur

Modifiez maintenant chaque fichier de configuration vide config.xml situé dans fs/volumes/clickhouse-{}/etc/clickhouse-server/config.d. Les lignes surlignées ci-dessous doivent être adaptées à chaque nœud :

<clickhouse replace="true">
    <logger>
        <level>debug</level>
        <log>/var/log/clickhouse-server/clickhouse-server.log</log>
        <errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
        <size>1000M</size>
        <count>3</count>
    </logger>
    <display_name>cluster_2S_2R node 1</display_name>
    <listen_host>0.0.0.0</listen_host>
    <http_port>8123</http_port>
    <tcp_port>9000</tcp_port>
    <user_directories>
        <users_xml>
            <path>users.xml</path>
        </users_xml>
        <local_directory>
            <path>/var/lib/clickhouse/access/</path>
        </local_directory>
    </user_directories>
    <distributed_ddl>
        <path>/clickhouse/task_queue/ddl</path>
    </distributed_ddl>
    <remote_servers>
        <cluster_2S_2R>
            <shard>
                <internal_replication>true</internal_replication>
                <replica>
                    <host>clickhouse-01</host>
                    <port>9000</port>
                </replica>
                <replica>
                    <host>clickhouse-03</host>
                    <port>9000</port>
                </replica>
            </shard>
            <shard>
                <internal_replication>true</internal_replication>
                <replica>
                    <host>clickhouse-02</host>
                    <port>9000</port>
                </replica>
                <replica>
                    <host>clickhouse-04</host>
                    <port>9000</port>
                </replica>
            </shard>
        </cluster_2S_2R>
    </remote_servers>
    <zookeeper>
        <node>
            <host>clickhouse-keeper-01</host>
            <port>9181</port>
        </node>
        <node>
            <host>clickhouse-keeper-02</host>
            <port>9181</port>
        </node>
        <node>
            <host>clickhouse-keeper-03</host>
            <port>9181</port>
        </node>
    </zookeeper>
    <macros>
        <shard>01</shard>
        <replica>01</replica>
    </macros>
</clickhouse>
Répertoire File
fs/volumes/clickhouse-01/etc/clickhouse-server/config.d config.xml
fs/volumes/clickhouse-02/etc/clickhouse-server/config.d config.xml
fs/volumes/clickhouse-03/etc/clickhouse-server/config.d config.xml
fs/volumes/clickhouse-04/etc/clickhouse-server/config.d config.xml

Chaque section du fichier de configuration ci-dessus est expliquée plus en détail ci-dessous.

Réseau et journalisation

La communication externe via l’interface réseau est activée en configurant le paramètre listen host. Cela garantit que l’hôte du serveur ClickHouse est accessible depuis d’autres hôtes :

<listen_host>0.0.0.0</listen_host>

Le port de l’API HTTP est configuré sur 8123 :

<http_port>8123</http_port>

Le port TCP utilisé pour la communication via le protocole natif de ClickHouse entre clickhouse-client et d'autres outils natifs de ClickHouse, ainsi qu'entre clickhouse-server et d'autres clickhouse-servers, est défini sur 9000:

<tcp_port>9000</tcp_port>

La configuration de la journalisation est définie dans le bloc <logger>. Cet exemple de configuration vous fournit un journal de débogage avec rotation à 1000 Mo, trois fois :

<logger>
   <level>debug</level>
   <log>/var/log/clickhouse-server/clickhouse-server.log</log>
   <errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
   <size>1000M</size>
   <count>3</count>
</logger>

Pour plus d'informations sur la configuration de la journalisation, consultez les commentaires inclus dans le fichier de configuration ClickHouse par défaut.

Configuration du cluster

La configuration du cluster est définie dans le bloc <remote_servers>. Le nom du cluster cluster_2S_2R y est défini.

Le bloc <cluster_2S_2R></cluster_2S_2R> définit la disposition du cluster, à l'aide des paramètres <shard></shard> et <replica></replica>, et sert de modèle pour les requêtes DDL distribuées, c'est-à-dire les requêtes qui s'exécutent sur l'ensemble du cluster via la clause ON CLUSTER. Par défaut, les requêtes DDL distribuées sont autorisées, mais peuvent également être désactivées avec le paramètre allow_distributed_ddl_queries.

internal_replication est défini sur true afin que les données ne soient écrites que sur l'une des répliques.

<remote_servers>
   <!-- cluster name (should not contain dots) -->
  <cluster_2S_2R>
      <!-- <allow_distributed_ddl_queries>false</allow_distributed_ddl_queries> -->
      <shard>
          <!-- Optional. Whether to write data to just one of the replicas. Default: false (write data to all replicas). -->
          <internal_replication>true</internal_replication>
          <replica>
              <host>clickhouse-01</host>
              <port>9000</port>
          </replica>
          <replica>
              <host>clickhouse-03</host>
              <port>9000</port>
          </replica>
      </shard>
      <shard>
          <internal_replication>true</internal_replication>
          <replica>
              <host>clickhouse-02</host>
              <port>9000</port>
          </replica>
          <replica>
              <host>clickhouse-04</host>
              <port>9000</port>
          </replica>
      </shard>
  </cluster_2S_2R>
</remote_servers>

La section <cluster_2S_2R></cluster_2S_2R> définit le layout du cluster et sert de template pour les requêtes DDL distribuées, c'est-à-dire les requêtes qui s'exécutent sur l'ensemble du cluster à l'aide de la clause ON CLUSTER.

Configuration de Keeper

La section <ZooKeeper> indique à ClickHouse où ClickHouse Keeper (ou ZooKeeper) est en cours d'exécution. Comme nous utilisons un cluster ClickHouse Keeper, chaque <node> du cluster doit être spécifié, avec son hostname et son numéro de port via les tags <host> et <port> respectivement.

La configuration de ClickHouse Keeper est présentée à l'étape suivante du tutoriel.

<zookeeper>
    <node>
        <host>clickhouse-keeper-01</host>
        <port>9181</port>
    </node>
    <node>
        <host>clickhouse-keeper-02</host>
        <port>9181</port>
    </node>
    <node>
        <host>clickhouse-keeper-03</host>
        <port>9181</port>
    </node>
</zookeeper>

Configuration des macros

Par ailleurs, la section <macros> permet de définir des substitutions de paramètres pour les tables répliquées. Celles-ci sont répertoriées dans system.macros et permettent d'utiliser des substitutions telles que {shard} et {replica} dans les requêtes.

<macros>
   <shard>01</shard>
   <replica>01</replica>
</macros>

Configuration utilisateur

Modifiez maintenant chaque fichier de configuration vide users.xml situé dans fs/volumes/clickhouse-{}/etc/clickhouse-server/users.d avec le contenu suivant :

/users.d/users.xmlxml
<?xml version="1.0"?>
<clickhouse replace="true">
    <profiles>
        <default>
            <max_memory_usage>10000000000</max_memory_usage>
            <use_uncompressed_cache>0</use_uncompressed_cache>
            <load_balancing>in_order</load_balancing>
            <log_queries>1</log_queries>
        </default>
    </profiles>
    <users>
        <default>
            <access_management>1</access_management>
            <profile>default</profile>
            <networks>
                <ip>::/0</ip>
            </networks>
            <quota>default</quota>
            <access_management>1</access_management>
            <named_collection_control>1</named_collection_control>
            <show_named_collections>1</show_named_collections>
            <show_named_collections_secrets>1</show_named_collections_secrets>
        </default>
    </users>
    <quotas>
        <default>
            <interval>
                <duration>3600</duration>
                <queries>0</queries>
                <errors>0</errors>
                <result_rows>0</result_rows>
                <read_rows>0</read_rows>
                <execution_time>0</execution_time>
            </interval>
        </default>
    </quotas>
</clickhouse>

Dans cet exemple, l'utilisateur par défaut est configuré sans mot de passe par souci de simplicité. En pratique, cette pratique est déconseillée.

Configurer ClickHouse Keeper

Ensuite, configurez ClickHouse Keeper, utilisé pour la coordination.

Configuration de Keeper

Pour que la réplication fonctionne, un cluster ClickHouse Keeper doit être mis en place et configuré. ClickHouse Keeper fournit le système de coordination pour la réplication des données, et remplace ZooKeeper, qui peut également être utilisé. ClickHouse Keeper est toutefois recommandé, car il offre de meilleures garanties, une meilleure fiabilité et utilise moins de ressources que ZooKeeper. Pour assurer une haute disponibilité et maintenir le quorum, il est recommandé d’exécuter au moins trois nœuds ClickHouse Keeper.

Créez les fichiers keeper_config.xml pour chaque nœud ClickHouse Keeper à l’aide de la commande suivante depuis la racine du dossier d’exemple :

for i in {01..03}; do
  touch fs/volumes/clickhouse-keeper-${i}/etc/clickhouse-keeper/keeper_config.xml
done

Modifiez les fichiers de configuration vides créés dans chaque répertoire de nœud fs/volumes/clickhouse-keeper-{}/etc/clickhouse-keeper. Les lignes mises en évidence ci-dessous doivent être adaptées à chaque nœud :

/clickhouse-keeper/keeper_config.xmlxml
<clickhouse replace="true">
    <logger>
        <level>information</level>
        <log>/var/log/clickhouse-keeper/clickhouse-keeper.log</log>
        <errorlog>/var/log/clickhouse-keeper/clickhouse-keeper.err.log</errorlog>
        <size>1000M</size>
        <count>3</count>
    </logger>
    <listen_host>0.0.0.0</listen_host>
    <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>information</raft_logs_level>
        </coordination_settings>
        <raft_configuration>
            <server>
                <id>1</id>
                <hostname>clickhouse-keeper-01</hostname>
                <port>9234</port>
            </server>
            <server>
                <id>2</id>
                <hostname>clickhouse-keeper-02</hostname>
                <port>9234</port>
            </server>
            <server>
                <id>3</id>
                <hostname>clickhouse-keeper-03</hostname>
                <port>9234</port>
            </server>
        </raft_configuration>
    </keeper_server>
</clickhouse>
Répertoire Fichier
fs/volumes/clickhouse-keeper-01/etc/clickhouse-keeper keeper_config.xml
fs/volumes/clickhouse-keeper-02/etc/clickhouse-keeper keeper_config.xml
fs/volumes/clickhouse-keeper-03/etc/clickhouse-keeper keeper_config.xml

Chaque fichier de configuration contient la configuration unique suivante (illustrée ci-dessous). Le server_id utilisé doit être unique pour ce nœud ClickHouse Keeper dans le cluster et correspondre à l’<id> du serveur défini dans la section <raft_configuration>. tcp_port est le port utilisé par les clients de ClickHouse Keeper.

<tcp_port>9181</tcp_port>
<server_id>{id}</server_id>

La section suivante permet de configurer les serveurs qui participent au quorum de l’algorithme de consensus Raft :

<raft_configuration>
    <server>
        <id>1</id>
        <hostname>clickhouse-keeper-01</hostname>
        <!-- TCP port used for communication between ClickHouse Keeper nodes -->
        <port>9234</port>
    </server>
    <server>
        <id>2</id>
        <hostname>clickhouse-keeper-02</hostname>
        <port>9234</port>
    </server>
    <server>
        <id>3</id>
        <hostname>clickhouse-keeper-03</hostname>
        <port>9234</port>
    </server>
</raft_configuration>

Tester la configuration

Assurez-vous que Docker est en cours d’exécution sur votre machine. Démarrez le cluster à l’aide de la commande docker-compose up depuis la racine du répertoire cluster_2S_2R :

docker-compose up -d

Vous devriez voir Docker commencer à récupérer les images ClickHouse et Keeper, puis démarrer les conteneurs :

[+] Running 8/8
 Network   cluster_2s_2r_default     Created
 Container clickhouse-keeper-03      Started
 Container clickhouse-keeper-02      Started
 Container clickhouse-keeper-01      Started
 Container clickhouse-01             Started
 Container clickhouse-02             Started
 Container clickhouse-04             Started
 Container clickhouse-03             Started

Pour vérifier que le cluster est bien en fonctionnement, connectez-vous à l’un des nœuds et exécutez la requête suivante. La commande pour se connecter au premier nœud est indiquée :

# Connect to any node
docker exec -it clickhouse-01 clickhouse-client

Si tout s’est bien passé, l’invite du client ClickHouse s’affiche :

cluster_2S_2R node 1 :)

Exécutez la requête suivante afin de voir quelles topologies de cluster sont définies pour quels hôtes :

Querysql
SELECT 
    cluster,
    shard_num,
    replica_num,
    host_name,
    port
FROM system.clusters;
Responseresponse
   ┌─cluster───────┬─shard_num─┬─replica_num─┬─host_name─────┬─port─┐
1. │ cluster_2S_2R │         1 │           1 │ clickhouse-01 │ 9000 │
2. │ cluster_2S_2R │         1 │           2 │ clickhouse-03 │ 9000 │
3. │ cluster_2S_2R │         2 │           1 │ clickhouse-02 │ 9000 │
4. │ cluster_2S_2R │         2 │           2 │ clickhouse-04 │ 9000 │
5. │ default       │         1 │           1 │ localhost     │ 9000 │
   └───────────────┴───────────┴─────────────┴───────────────┴──────┘

Exécutez la requête suivante pour vérifier l’état du cluster ClickHouse Keeper :

Querysql
SELECT *
FROM system.zookeeper
WHERE path IN ('/', '/clickhouse')
Responseresponse
   ┌─name───────┬─value─┬─path────────┐
1. │ task_queue │       │ /clickhouse │
2. │ sessions   │       │ /clickhouse │
3. │ keeper     │       │ /           │
4. │ clickhouse │       │ /           │
   └────────────┴───────┴─────────────┘

La commande mntr est également couramment utilisée pour vérifier que ClickHouse Keeper est en cours d’exécution et pour obtenir des informations sur l’état des relations entre les trois nœuds Keeper. Dans la configuration utilisée dans cet exemple, trois nœuds fonctionnent ensemble. Les nœuds éliront un leader, et les nœuds restants seront des followers.

La commande mntr fournit des informations relatives aux performances et indique si un nœud donné est un follower ou un leader.

Exécutez la commande ci-dessous depuis un shell sur clickhouse-keeper-01, clickhouse-keeper-02 et clickhouse-keeper-03 pour vérifier l’état de chaque nœud Keeper. La commande pour clickhouse-keeper-01 est indiquée ci-dessous :

docker exec -it clickhouse-keeper-01  /bin/sh -c 'echo mntr | nc 127.0.0.1 9181'

La réponse ci-dessous présente un exemple de réponse d’un nœud follower :

Responseresponse
zk_version      v23.3.1.2823-testing-46e85357ce2da2a99f56ee83a079e892d7ec3726
zk_avg_latency  0
zk_max_latency  0
zk_min_latency  0
zk_packets_received     0
zk_packets_sent 0
zk_num_alive_connections        0
zk_outstanding_requests 0
zk_server_state follower
zk_znode_count  6
zk_watch_count  0
zk_ephemerals_count     0
zk_approximate_data_size        1271
zk_key_arena_size       4096
zk_latest_snapshot_size 0
zk_open_file_descriptor_count   46
zk_max_file_descriptor_count    18446744073709551615

La réponse ci-dessous montre un exemple de réponse renvoyée par un nœud leader :

Responseresponse
zk_version      v23.3.1.2823-testing-46e85357ce2da2a99f56ee83a079e892d7ec3726
zk_avg_latency  0
zk_max_latency  0
zk_min_latency  0
zk_packets_received     0
zk_packets_sent 0
zk_num_alive_connections        0
zk_outstanding_requests 0
zk_server_state leader
zk_znode_count  6
zk_watch_count  0
zk_ephemerals_count     0
zk_approximate_data_size        1271
zk_key_arena_size       4096
zk_latest_snapshot_size 0
zk_open_file_descriptor_count   48
zk_max_file_descriptor_count    18446744073709551615
zk_followers    2
zk_synced_followers     2

Vous avez ainsi configuré avec succès un cluster ClickHouse avec deux shards et deux répliques. À l’étape suivante, vous créerez une table dans le cluster.

Créer une base de données

Maintenant que vous avez vérifié que le cluster est correctement configuré et en fonctionnement, vous allez recréer la même table que celle utilisée dans le tutoriel du jeu de données d’exemple UK property prices. Cette table contient environ 30 millions de lignes correspondant aux prix payés pour des biens immobiliers en Angleterre et au pays de Galles depuis 1995.

Connectez-vous au client de chaque hôte en exécutant chacune des commandes suivantes dans des onglets ou des fenêtres de terminal distincts :

docker exec -it clickhouse-01 clickhouse-client
docker exec -it clickhouse-02 clickhouse-client
docker exec -it clickhouse-03 clickhouse-client
docker exec -it clickhouse-04 clickhouse-client

Vous pouvez exécuter la requête ci-dessous depuis clickhouse-client sur chaque hôte afin de vérifier qu’aucune base de données n’a encore été créée, à l’exception de celles créées par défaut :

Querysql
SHOW DATABASES;
Responseresponse
   ┌─name───────────────┐
1. │ INFORMATION_SCHEMA │
2. │ default            │
3. │ information_schema │
4. │ system             │
   └────────────────────┘

Depuis le client clickhouse-01, exécutez la requête DDL distribuée suivante avec la clause ON CLUSTER afin de créer une nouvelle base de données appelée uk :

CREATE DATABASE IF NOT EXISTS uk 
ON CLUSTER cluster_2S_2R;

Vous pouvez de nouveau exécuter la même requête qu’auparavant depuis le client de chaque hôte pour vérifier que la base de données a bien été créée sur l’ensemble du cluster, même si la requête n’a été exécutée que depuis clickhouse-01 :

SHOW DATABASES;
   ┌─name───────────────┐
1. │ INFORMATION_SCHEMA │
2. │ default            │
3. │ information_schema │
4. │ system             │
5. │ uk                 │
   └────────────────────┘

Créez une table dans le cluster

Maintenant que la base de données a été créée, vous allez créer une table avec réplication.

Exécutez la requête suivante depuis l’un des clients hôtes :

CREATE TABLE IF NOT EXISTS uk.uk_price_paid_local
ON CLUSTER cluster_2S_2R
(
    price UInt32,
    date Date,
    postcode1 LowCardinality(String),
    postcode2 LowCardinality(String),
    type Enum8('terraced' = 1, 'semi-detached' = 2, 'detached' = 3, 'flat' = 4, 'other' = 0),
    is_new UInt8,
    duration Enum8('freehold' = 1, 'leasehold' = 2, 'unknown' = 0),
    addr1 String,
    addr2 String,
    street LowCardinality(String),
    locality LowCardinality(String),
    town LowCardinality(String),
    district LowCardinality(String),
    county LowCardinality(String)
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{database}/{table}/{shard}', '{replica}')
ORDER BY (postcode1, postcode2, addr1, addr2);

Notez qu’elle est identique à la requête utilisée dans l’instruction CREATE d’origine du tutoriel du jeu de données d’exemple UK property prices, à l’exception de la clause ON CLUSTER et de l’utilisation du moteur ReplicatedMergeTree.

La clause ON CLUSTER est conçue pour l’exécution distribuée de requêtes DDL (Data Definition Language) telles que CREATE, DROP, ALTER et RENAME, afin de garantir que ces modifications de schéma sont appliquées à tous les nœuds d’un cluster.

Le moteur ReplicatedMergeTree fonctionne exactement comme le moteur de table MergeTree ordinaire, mais il réplique également les données. Deux paramètres doivent être spécifiés :

  • zoo_path : le chemin Keeper/ZooKeeper des métadonnées de la table.
  • replica_name : le nom de la réplique de la table.

Le paramètre zoo_path peut être défini comme vous le souhaitez, bien qu’il soit recommandé de suivre la convention consistant à utiliser le préfixe

/clickhouse/tables/{shard}/{database}/{table}

où :

  • {database} et {table} seront remplacés automatiquement.
  • {shard} et {replica} sont des macros qui ont été définies précédemment dans le fichier config.xml de chaque nœud ClickHouse.

Vous pouvez exécuter la requête ci-dessous à partir du client de chaque hôte pour confirmer que la table a bien été créée sur l’ensemble du cluster :

Querysql
SHOW TABLES IN uk;
Responseresponse
   ┌─name────────────────┐
1. │ uk_price_paid_local │
   └─────────────────────┘

Insérer des données dans une table distribuée

Pour insérer des données dans la table, ON CLUSTER ne peut pas être utilisé, car il ne s'applique pas aux requêtes DML (Data Manipulation Language) telles que INSERT, UPDATE et DELETE. Pour insérer des données, il faut utiliser le moteur de table Distributed. Comme vous l'avez vu dans le guide de configuration d'un cluster avec 2 shards et 1 replica, les tables distribuées sont des tables qui accèdent à des shards situés sur différents hôtes et sont définies à l'aide du moteur de table Distributed. La table distribuée sert d'interface entre tous les shards du cluster.

Depuis le client de n'importe lequel des hôtes, exécutez la requête suivante pour créer une table distribuée à l'aide de la table répliquée existante que nous avons créée à l'étape précédente :

CREATE TABLE IF NOT EXISTS uk.uk_price_paid_distributed
ON CLUSTER cluster_2S_2R
ENGINE = Distributed('cluster_2S_2R', 'uk', 'uk_price_paid_local', rand());

Sur chacun des hôtes, vous verrez désormais les tables suivantes dans la base de données uk :

   ┌─name──────────────────────┐
1. │ uk_price_paid_distributed │
2. │ uk_price_paid_local       │
   └───────────────────────────┘

Les données peuvent être insérées dans la table uk_price_paid_distributed depuis n’importe quel client hôte à l’aide de la requête suivante :

INSERT INTO uk.uk_price_paid_distributed
SELECT
    toUInt32(price_string) AS price,
    parseDateTimeBestEffortUS(time) AS date,
    splitByChar(' ', postcode)[1] AS postcode1,
    splitByChar(' ', postcode)[2] AS postcode2,
    transform(a, ['T', 'S', 'D', 'F', 'O'], ['terraced', 'semi-detached', 'detached', 'flat', 'other']) AS type,
    b = 'Y' AS is_new,
    transform(c, ['F', 'L', 'U'], ['freehold', 'leasehold', 'unknown']) AS duration,
    addr1,
    addr2,
    street,
    locality,
    town,
    district,
    county
FROM url(
    'http://prod1.publicdata.landregistry.gov.uk.s3-website-eu-west-1.amazonaws.com/pp-complete.csv',
    'CSV',
    'uuid_string String,
    price_string String,
    time String,
    postcode String,
    a String,
    b String,
    c String,
    addr1 String,
    addr2 String,
    street String,
    locality String,
    town String,
    district String,
    county String,
    d String,
    e String'
) SETTINGS max_http_get_redirects=10;

Exécutez la requête suivante pour confirmer que les données insérées ont été réparties uniformément entre les nœuds de notre cluster :

SELECT count(*)
FROM uk.uk_price_paid_distributed;

SELECT count(*) FROM uk.uk_price_paid_local;
   ┌──count()─┐
1. │ 30212555 │ -- 30.21 million
   └──────────┘

   ┌──count()─┐
1. │ 15105983 │ -- 15.11 million
   └──────────┘

Conclusion

L’avantage de cette topologie de cluster avec 2 shards et 2 répliques est qu’elle offre à la fois passage à l’échelle et tolérance aux pannes. Les données sont réparties sur des hôtes distincts, ce qui réduit les besoins en stockage et en E/S par nœud, tandis que les requêtes sont traitées en parallèle sur les deux shards afin d’améliorer les performances et l’efficience mémoire. Point essentiel : le cluster peut tolérer la perte d’un nœud et continuer à traiter les requêtes sans interruption, car chaque shard dispose d’une réplique de secours sur un autre nœud.

Le principal inconvénient de cette topologie de cluster est le surcoût de stockage : elle nécessite deux fois plus de capacité de stockage qu’une configuration sans répliques, puisque chaque shard est dupliqué. De plus, même si le cluster peut survivre à la défaillance d’un seul nœud, la perte simultanée de deux nœuds peut le rendre inutilisable, selon les nœuds concernés et la manière dont les shards sont répartis. Cette topologie offre un compromis entre disponibilité et coût, ce qui la rend adaptée aux environnements de production où un certain niveau de tolérance aux pannes est nécessaire sans le coût de facteurs de réplication plus élevés.

Pour découvrir comment ClickHouse Cloud traite les requêtes, en offrant à la fois passage à l’échelle et tolérance aux pannes, consultez la section "Répliques parallèles".

Navigation