Перейти к основному содержанию
Перейти к основному содержанию

Репликация и масштабирование

В этом примере вы узнаете, как развернуть простой кластер ClickHouse, который одновременно обеспечивает репликацию и масштабирование. Он состоит из двух шардов и двух реплик, а также кластера ClickHouse Keeper из 3 узлов для координации работы и поддержания кворума в кластере.

Архитектура кластера, который вы будете настраивать, показана ниже:

Схема архитектуры для 2 шардов и 1 реплики
Примечание

Although it is possible to run ClickHouse Server and ClickHouse Keeper combined on the same server, we strongly recommend using dedicated hosts for ClickHouse keeper in production environments, which is the approach we will demonstrate in this example.

Keeper servers can be smaller, and 4GB RAM is generally enough for each Keeper server until your ClickHouse Servers grow large.

Предварительные требования

Настройка структуры каталогов и тестовой среды

Example files

The following steps will walk you through setting up the cluster from scratch. If you prefer to skip these steps and jump straight to running the cluster, you can obtain the example files from the examples repository 'docker-compose-recipes' directory.

В этом руководстве вы будете использовать Docker Compose для развёртывания кластера ClickHouse. Эту конфигурацию можно адаптировать для работы на отдельных локальных машинах, виртуальных машинах или облачных инстансах.

Выполните следующие команды для создания структуры каталогов для этого примера:

mkdir cluster_2S_2R
cd cluster_2S_2R

# Создать директории clickhouse-keeper
for i in {01..03}; do
  mkdir -p fs/volumes/clickhouse-keeper-${i}/etc/clickhouse-keeper
done

# Создать директории clickhouse-server
for i in {01..04}; do
  mkdir -p fs/volumes/clickhouse-${i}/etc/clickhouse-server
done

Добавьте следующий файл docker-compose.yml в каталог clickhouse-cluster:

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"

Создайте следующие подкаталоги и файлы:

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
  • The config.d directory contains ClickHouse server configuration file config.xml, in which custom configuration for each ClickHouse node is defined. This configuration gets combined with the default config.xml ClickHouse configuration file that comes with every ClickHouse installation.
  • The users.d directory contains user configuration file users.xml, in which custom configuration for users is defined. This configuration gets combined with the default ClickHouse users.xml configuration file that comes with every ClickHouse installation.
Custom configuration directories

It is a best practice to make use of the config.d and users.d directories when writing your own configuration, rather than directly modifying the default configuration in /etc/clickhouse-server/config.xml and etc/clickhouse-server/users.xml.

The line

<clickhouse replace="true">

Ensures that the configuration sections defined in the config.d and users.d directories override the default configuration sections defined in the default config.xml and users.xml files.

Настройка узлов ClickHouse

Настройка сервера

Теперь измените каждый пустой файл конфигурации config.xml, расположенный по пути fs/volumes/clickhouse-{}/etc/clickhouse-server/config.d. Строки, выделенные ниже, должны быть изменены для каждого узла отдельно:

<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>
    <!--highlight-next-line-->
    <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>
    <!--highlight-start-->
    <macros>
        <shard>01</shard>
        <replica>01</replica>
    </macros>
    <!--highlight-end-->
</clickhouse>
КаталогФайл
fs/volumes/clickhouse-01/etc/clickhouse-server/config.dconfig.xml
fs/volumes/clickhouse-02/etc/clickhouse-server/config.dconfig.xml
fs/volumes/clickhouse-03/etc/clickhouse-server/config.dconfig.xml
fs/volumes/clickhouse-04/etc/clickhouse-server/config.dconfig.xml

Каждый раздел указанного выше конфигурационного файла подробно описан ниже.

Сеть и логирование

External communication to the network interface is enabled by activating the listen host setting. This ensures that the ClickHouse server host is reachable by other hosts:

<listen_host>0.0.0.0</listen_host>

The port for the HTTP API is set to 8123:

<http_port>8123</http_port>

The TCP port for interaction by ClickHouse's native protocol between clickhouse-client and other native ClickHouse tools, and clickhouse-server and other clickhouse-servers is set to 9000:

<tcp_port>9000</tcp_port>

Конфигурация логирования определяется в блоке <logger>. Данный пример конфигурации создаёт отладочный лог с ротацией при достижении размера 1000M (три раза):

<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>

Дополнительную информацию о настройке логирования см. в комментариях стандартного файла конфигурации ClickHouse.

Конфигурация кластера

Конфигурация кластера задаётся в блоке <remote_servers>. Здесь задано имя кластера cluster_2S_2R.

Блок <cluster_2S_2R></cluster_2S_2R> определяет топологию кластера с помощью параметров <shard></shard> и <replica></replica> и служит шаблоном для распределённых DDL-запросов — запросов, выполняемых на всём кластере с использованием конструкции ON CLUSTER. По умолчанию распределённые DDL-запросы разрешены, но могут быть отключены с помощью параметра allow_distributed_ddl_queries.

internal_replication установлен в true, чтобы данные записывались только на одну из реплик.

<remote_servers>
   <!-- имя кластера (не должно содержать точки) -->
  <cluster_2S_2R>
      <!-- <allow_distributed_ddl_queries>false</allow_distributed_ddl_queries> -->
      <shard>
          <!-- Необязательный параметр. Определяет, следует ли записывать данные только в одну из реплик. Значение по умолчанию: false (данные записываются во все реплики). -->
          <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>

Секция <cluster_2S_2R></cluster_2S_2R> определяет топологию кластера и служит шаблоном для распределённых DDL-запросов — запросов, выполняемых на всех узлах кластера с помощью конструкции ON CLUSTER.

Конфигурация Keeper

Секция <ZooKeeper> указывает ClickHouse, где запущен ClickHouse Keeper (или ZooKeeper). Поскольку используется кластер ClickHouse Keeper, необходимо указать каждый узел <node> кластера вместе с его именем хоста и номером порта с помощью тегов <host> и <port> соответственно.

Настройка ClickHouse Keeper описана на следующем шаге руководства.

<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>
Примечание

Хотя ClickHouse Keeper можно запустить на том же сервере, что и ClickHouse Server, для production-окружений мы настоятельно рекомендуем использовать выделенные хосты для ClickHouse Keeper.

Конфигурация макросов

Кроме того, секция <macros> используется для определения подстановки параметров для реплицируемых таблиц. Они перечислены в system.macros и позволяют использовать подстановки типа {shard} и {replica} в запросах.

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

Настройка пользователя

Теперь измените каждый пустой конфигурационный файл users.xml, расположенный в fs/volumes/clickhouse-{}/etc/clickhouse-server/users.d, следующим образом:

<?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>

В данном примере пользователь по умолчанию настроен без пароля для упрощения. На практике это не рекомендуется.

Примечание

В данном примере файл users.xml одинаков для всех узлов кластера.

Настройка ClickHouse Keeper

Далее необходимо настроить ClickHouse Keeper, который используется для координации.

Настройка Keeper

In order for replication to work, a ClickHouse keeper cluster needs to be set up and configured. ClickHouse Keeper provides the coordination system for data replication, acting as a stand in replacement for Zookeeper, which could also be used. ClickHouse Keeper is, however, recommended, as it provides better guarantees and reliability and uses fewer resources than ZooKeeper. For high availability and to keep quorum, it is recommended to run at least three ClickHouse Keeper nodes.

Примечание

ClickHouse Keeper can run on any node of the cluster alongside ClickHouse, although it is recommended to have it run on a dedicated node which allows scaling and managing the ClickHouse Keeper cluster independently of the database cluster.

Create the keeper_config.xml files for each ClickHouse Keeper node using the following command from the root of the example folder:

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

Modify the empty configuration files which were created in each node directory fs/volumes/clickhouse-keeper-{}/etc/clickhouse-keeper. The highlighted lines below need to be changed to be specific to each node:

<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>
        <!--highlight-next-line-->
        <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>
КаталогФайл
fs/volumes/clickhouse-keeper-01/etc/clickhouse-keeperkeeper_config.xml
fs/volumes/clickhouse-keeper-02/etc/clickhouse-keeperkeeper_config.xml
fs/volumes/clickhouse-keeper-03/etc/clickhouse-keeperkeeper_config.xml

Each configuration file will contain the following unique configuration (shown below). The server_id used should be unique for that particular ClickHouse Keeper node in the cluster and match the server <id> defined in the <raft_configuration> section. tcp_port is the port used by clients of ClickHouse Keeper.

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

The following section is used to configure the servers that participate in the quorum for the raft consensus algorithm:

<raft_configuration>
    <server>
        <id>1</id>
        <hostname>clickhouse-keeper-01</hostname>
        <!-- TCP port used for communication between ClickHouse Keeper nodes -->
        <!--highlight-next-line-->
        <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>
ClickHouse Cloud simplifies management

ClickHouse Cloud removes the operational burden associated with managing shards and replicas. The platform automatically handles high availability, replication, and scaling decisions. Compute and storage are separate and scale based on demand without requiring manual configuration or ongoing maintenance.

Read more

Проверка настройки

Убедитесь, что Docker запущен на вашем компьютере. Запустите кластер командой docker-compose up из корневого каталога cluster_2S_2R:

docker-compose up -d

Вы увидите, как docker начнет загружать образы ClickHouse и Keeper, а затем запустит контейнеры:

[+] 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

Чтобы проверить, что кластер запущен, подключитесь к любому из узлов и выполните следующий запрос. Команда для подключения к первому узлу:

# Подключитесь к любому узлу
docker exec -it clickhouse-01 clickhouse-client

При успешном подключении вы увидите командную строку клиента ClickHouse:

cluster_2S_2R node 1 :)

Выполните следующий запрос, чтобы проверить, какие топологии кластера определены для каких хостов:

SELECT 
    cluster,
    shard_num,
    replica_num,
    host_name,
    port
FROM system.clusters;
┌─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 │
   └───────────────┴───────────┴─────────────┴───────────────┴──────┘

Выполните следующий запрос, чтобы проверить состояние кластера ClickHouse Keeper:

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

The mntr command is also commonly used to verify that ClickHouse Keeper is running and to get state information about the relationship of the three Keeper nodes. In the configuration used in this example, there are three nodes working together. The nodes will elect a leader, and the remaining nodes will be followers.

The mntr command gives information related to performance, and whether a particular node is a follower or a leader.

Совет

You may need to install netcat in order to send the mntr command to Keeper. Please see the nmap.org page for download information.

Run the command below from a shell on clickhouse-keeper-01, clickhouse-keeper-02, and clickhouse-keeper-03 to check the status of each Keeper node. The command for clickhouse-keeper-01 is shown below:

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

The response below shows an example response from a follower node:

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
# highlight-next-line
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

The response below shows an example response from a leader node:

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
# highlight-next-line
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
# highlight-start
zk_followers    2
zk_synced_followers     2
# highlight-end

Таким образом, вы успешно настроили кластер ClickHouse с двумя шардами и двумя репликами. На следующем шаге вы создадите таблицу в кластере.

Создание базы данных

Теперь, когда вы убедились, что кластер правильно настроен и запущен, вы создадите ту же таблицу, что и в руководстве по примеру набора данных UK property prices. Она содержит около 30 миллионов записей о ценах на недвижимость в Англии и Уэльсе с 1995 года.

Подключитесь к клиенту каждого хоста, выполнив следующие команды в отдельных вкладках или окнах терминала:

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

Вы можете выполнить приведённый ниже запрос из clickhouse-client на каждом хосте, чтобы убедиться, что помимо стандартных баз данных других пока не создано:

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

Из клиента clickhouse-01 выполните следующий распределённый DDL-запрос с использованием конструкции ON CLUSTER для создания новой базы данных uk:

CREATE DATABASE IF NOT EXISTS uk 
-- highlight-next-line
ON CLUSTER cluster_2S_2R;

Вы можете снова выполнить тот же запрос из клиента каждого хоста, чтобы убедиться, что база данных создана во всём кластере, несмотря на то, что запрос выполнялся только из clickhouse-01:

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

Создание таблицы в кластере

Теперь, когда база данных создана, создайте таблицу с репликацией.

Выполните следующий запрос из любого клиента на хосте:

CREATE TABLE IF NOT EXISTS uk.uk_price_paid_local
--highlight-next-line
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)
)
--highlight-next-line
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{database}/{table}/{shard}', '{replica}')
ORDER BY (postcode1, postcode2, addr1, addr2);

Обратите внимание, что этот запрос идентичен запросу из исходной инструкции CREATE в руководстве по примеру набора данных цен на недвижимость в Великобритании, за исключением конструкции ON CLUSTER и использования движка ReplicatedMergeTree.

Конструкция ON CLUSTER предназначена для распределённого выполнения DDL-запросов (Data Definition Language), таких как CREATE, DROP, ALTER и RENAME, что обеспечивает применение изменений схемы на всех узлах кластера.

Движок ReplicatedMergeTree работает так же, как обычный движок таблиц MergeTree, но дополнительно реплицирует данные. Необходимо указать два параметра:

  • zoo_path: Путь в Keeper/ZooKeeper, по которому хранятся метаданные таблицы.
  • replica_name: Имя реплики таблицы.

Параметр zoo_path можно задать произвольно, однако рекомендуется следовать соглашению об использовании префикса

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

где:

  • {database} и {table} будут автоматически подставлены.
  • {shard} и {replica} — макросы, которые были определены ранее в файле config.xml каждого узла ClickHouse.

Вы можете выполнить приведённый ниже запрос из клиента каждого хоста, чтобы убедиться, что таблица создана во всём кластере:

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

Вставка данных в распределённую таблицу

Для вставки данных в таблицу нельзя использовать ON CLUSTER, поскольку эта конструкция не применяется к DML-запросам (Data Manipulation Language — язык манипулирования данными), таким как INSERT, UPDATE и DELETE. Для вставки данных необходимо использовать табличный движок Distributed. Как описано в руководстве по настройке кластера с 2 шардами и 1 репликой, распределённые таблицы — это таблицы, имеющие доступ к шардам, расположенным на разных хостах, и определяемые с помощью табличного движка Distributed. Распределённая таблица служит интерфейсом для всех шардов в кластере.

С любого из клиентов хоста выполните следующий запрос для создания распределённой таблицы на основе существующей реплицируемой таблицы, созданной на предыдущем шаге:

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());

На каждом хосте теперь будут доступны следующие таблицы в базе данных uk:

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

Данные можно вставить в таблицу uk_price_paid_distributed с любого из клиентских хостов с помощью следующего запроса:

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;

Выполните следующий запрос, чтобы убедиться, что вставленные данные равномерно распределены по узлам кластера:

SELECT count(*)
FROM uk.uk_price_paid_distributed;

SELECT count(*) FROM uk.uk_price_paid_local;
┌──count()─┐
1. │ 30212555 │ -- 30,21 миллиона
   └──────────┘

   ┌──count()─┐
1. │ 15105983 │ -- 15,11 миллиона
   └──────────┘

Заключение

Преимущество такой топологии кластера с 2 шардами и 2 репликами в том, что она обеспечивает и масштабируемость, и отказоустойчивость. Данные распределяются по отдельным хостам, снижая требования к хранению и операциям ввода-вывода (I/O) на каждый узел, а запросы обрабатываются параллельно на обоих шардах, что повышает производительность и эффективность использования памяти. Важно, что кластер может выдержать потерю одного узла и продолжить обслуживать запросы без перебоев, поскольку у каждого шарда есть резервная реплика на другом узле.

Основной недостаток такой топологии кластера — увеличенные затраты на хранение: требуется в два раза больше дискового пространства по сравнению с конфигурацией без реплик, поскольку каждый шард дублируется. Кроме того, хотя кластер выдерживает отказ одного узла, одновременная потеря двух узлов может сделать кластер неработоспособным в зависимости от того, какие именно узлы выйдут из строя и как распределены шарды. Эта топология представляет собой компромисс между доступностью и стоимостью, что делает её подходящей для продакшн-сред, где требуется определённый уровень отказоустойчивости без расходов на более высокий коэффициент репликации.

Чтобы узнать, как ClickHouse Cloud обрабатывает запросы, обеспечивая и масштабируемость, и отказоустойчивость, см. раздел "Parallel Replicas".