跳至主要内容
跳至主要内容

复制数据

在本示例中,你将学习如何设置一个简单的 ClickHouse 集群来复制数据。配置了五台服务器。其中两台用于托管数据的副本。另外三台服务器用于协调数据的复制。

你将要设置的集群架构如下所示

注意

虽然可以将 ClickHouse Server 和 ClickHouse Keeper 组合在同一服务器上运行,但我们强烈建议在生产环境中为 ClickHouse Keeper 使用专用主机,我们将在此示例中演示这种方法。

Keeper 服务器可以更小,通常每个 Keeper 服务器 4GB 内存就足够了,直到你的 ClickHouse 服务器变得很大。

先决条件

设置目录结构和测试环境

示例文件

以下步骤将引导你从头开始设置集群。如果你想跳过这些步骤并直接运行集群,可以从 examples 仓库获取示例文件 'docker-compose-recipes' 目录

在本教程中,你将使用 Docker compose 来设置 ClickHouse 集群。此设置也可以修改为适用于单独的本地机器、虚拟机或云实例。

运行以下命令来设置此示例的目录结构

mkdir cluster_1S_2R
cd cluster_1S_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..02}; do
  mkdir -p fs/volumes/clickhouse-${i}/etc/clickhouse-server
done

将以下 docker-compose.yml 文件添加到 cluster_1S_2R 目录

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-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..02}; 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
  • config.d 目录包含 ClickHouse 服务器配置文件 config.xml,其中定义了每个 ClickHouse 节点的自定义配置。此配置与每个 ClickHouse 安装程序附带的默认 config.xml ClickHouse 配置文件合并。
  • users.d 目录包含用户配置文件 users.xml,其中定义了用户的自定义配置。此配置与每个 ClickHouse 安装程序附带的默认 ClickHouse users.xml 配置文件合并。
自定义配置目录

在编写自己的配置时,使用 config.dusers.d 目录是一种最佳实践,而不是直接修改 /etc/clickhouse-server/config.xmletc/clickhouse-server/users.xml 中的默认配置。

该行

<clickhouse replace="true">

确保 config.dusers.d 目录中定义的配置节覆盖默认 config.xmlusers.xml 文件中定义的默认配置节。

配置 ClickHouse 节点

服务器设置

现在修改位于 fs/volumes/clickhouse-{}/etc/clickhouse-server/config.d 的每个空配置文件 config.xml。下面突出显示的行需要更改为特定于每个节点

<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_1S_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_1S_2R>
            <shard>
                <internal_replication>true</internal_replication>
                <replica>
                    <host>clickhouse-01</host>
                    <port>9000</port>
                </replica>
                <replica>
                    <host>clickhouse-02</host>
                    <port>9000</port>
                </replica>
            </shard>
        </cluster_1S_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>
        <cluster>cluster_1S_2R</cluster>
    </macros>
    <!--highlight-end-->
</clickhouse>
目录文件
fs/volumes/clickhouse-01/etc/clickhouse-server/config.dconfig.xml
fs/volumes/clickhouse-02/etc/clickhouse-server/config.dconfig.xml

上述配置文件的每个部分将在下面更详细地解释。

网络和日志记录

通过激活 listen host 设置,可以启用到网络接口的外部通信。这确保了 ClickHouse 服务器主机可以被其他主机访问

<listen_host>0.0.0.0</listen_host>

HTTP API 的端口设置为 8123

<http_port>8123</http_port>

TCP 端口设置为 9000,用于 clickhouse-client 和其他 native ClickHouse 工具以及 clickhouse-server 和其他 clickhouse-server 之间的交互

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

<cluster_1S_2R></cluster_1S_2R> 块使用 <shard></shard><replica></replica> 设置定义了集群的布局,并作为使用 ON CLUSTER 子句在集群上执行查询的分布式 DDL 查询的模板。默认情况下,允许分布式 DDL 查询,但也可以通过设置 allow_distributed_ddl_queries 来关闭。

internal_replication 设置为 true,以便数据只写入一个副本。

<remote_servers>
    <!-- cluster name (should not contain dots) -->
    <cluster_1S_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-02</host>
                <port>9000</port>
            </replica>
        </shard>
    </cluster_1S_2R>
</remote_servers>

对于每台服务器,指定以下参数

参数描述默认值
host远程服务器的地址。你可以使用域名或 IPv4 或 IPv6 地址。如果指定域名,服务器在启动时会进行 DNS 请求,并且结果会存储在服务器运行期间。如果 DNS 请求失败,服务器将不会启动。如果更改了 DNS 记录,你需要重新启动服务器。-
port用于 messenger 活动的 TCP 端口(配置中的 tcp_port,通常设置为 9000)。不要与 http_port 混淆。-

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 相同的服务器上,但在生产环境中,我们强烈建议 ClickHouse Keeper 在专用主机上运行。

宏配置

此外,<macros> 部分用于定义复制表的参数替换。这些列在 system.macros 中列出,并允许在查询中使用诸如 {shard}{replica} 之类的替换。

<macros>
    <shard>01</shard>
    <replica>01</replica>
    <cluster>cluster_1S_2R</cluster>
</macros>
注意

这些将根据集群的布局进行唯一定义。

用户配置

现在修改位于 fs/volumes/clickhouse-{}/etc/clickhouse-server/users.d 的每个空配置文件 users.xml,内容如下

<?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>
目录文件
fs/volumes/clickhouse-01/etc/clickhouse-server/users.dusers.xml
fs/volumes/clickhouse-02/etc/clickhouse-server/users.dusers.xml

在本示例中,默认用户配置为没有密码,以简化操作。在实践中,不建议这样做。

注意

在本示例中,每个 users.xml 文件对于集群中的所有节点都是相同的。

配置 ClickHouse Keeper

Keeper 设置

为了使复制工作,需要设置并配置 ClickHouse keeper 集群。ClickHouse Keeper 提供数据复制的协调系统,作为 ZooKeeper 的替代方案,ZooKeeper 也可以使用。但是,建议使用 ClickHouse Keeper,因为它提供更好的保证和可靠性,并且比 ZooKeeper 使用更少的资源。为了实现高可用性和保持法定人数,建议运行至少三个 ClickHouse Keeper 节点。

注意

ClickHouse Keeper 可以在集群的任何节点上与 ClickHouse 一起运行,但建议将其运行在专用节点上,这允许扩展和独立管理 ClickHouse Keeper 集群与数据库集群。

使用以下命令从示例文件夹的根目录创建每个 ClickHouse Keeper 节点的 keeper_config.xml 文件

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

修改在每个节点目录 fs/volumes/clickhouse-keeper-{}/etc/clickhouse-keeper 中创建的空配置文件。下面突出显示的行需要更改为特定于每个节点

<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

每个配置文件将包含以下唯一配置(如下所示)。用于该 ClickHouse Keeper 节点的 server_id 应该是唯一的,并且与 <raft_configuration> 部分中定义的服务器 <id> 相匹配。tcp_port 是 ClickHouse Keeper 客户端使用的端口。

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

以下部分用于配置参与 raft 共识算法法定人数的服务器

<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 简化管理

ClickHouse Cloud 移除了与管理分片和副本相关的操作负担。该平台自动处理高可用性、复制和扩展决策。计算和存储是分开的,并根据需求进行扩展,而无需手动配置或持续维护。

阅读更多

测试设置

确保你的机器上正在运行 docker。使用 docker-compose up 命令从 cluster_1S_2R 目录的根目录启动集群

docker-compose up -d

你应该看到 docker 开始拉取 ClickHouse 和 Keeper 镜像,然后启动容器

[+] Running 6/6
 ✔ Network cluster_1s_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

要验证集群是否正在运行,请连接到 clickhouse-01clickhouse-02 中的任何一个,并运行以下查询。连接到第一个节点的命令如下所示

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

如果成功,你将看到 ClickHouse 客户端提示符

cluster_1S_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_1S_2R │         1 │           1 │ clickhouse-01 │ 9000 │
2. │ cluster_1S_2R │         1 │           2 │ clickhouse-02 │ 9000 │
3. │ default       │         1 │           1 │ localhost     │ 9000 │
   └───────────────┴───────────┴─────────────┴───────────────┴──────┘

运行以下查询以检查 ClickHouse Keeper 集群的状态

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

mntr 命令也常用于验证 ClickHouse Keeper 是否正在运行,并获取有关三个 Keeper 节点之间关系的各种状态信息。在本示例中使用的配置中,有三个节点协同工作。这些节点将选举出一个领导者,其余节点将作为追随者。

mntr 命令提供与性能相关的信息,以及特定节点是追随者还是领导者。

提示

你可能需要安装 netcat 才能将 mntr 命令发送到 Keeper。请参阅 nmap.org 页面以获取下载信息。

clickhouse-keeper-01clickhouse-keeper-02clickhouse-keeper-03 上的 shell 中运行以下命令,以检查每个 Keeper 节点的状态。clickhouse-keeper-01 的命令如下所示

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

以下响应显示了来自追随者节点的示例响应

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

以下响应显示了来自领导者节点的示例响应

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 集群。在下一步中,你将在集群中创建一个表。

创建一个数据库

现在你已经验证了集群已正确设置并正在运行,你将重新创建与 英国房价 示例数据集教程中使用的相同表。它包含自 1995 年以来英格兰和威尔士房地产价格的大约 3000 万行数据。

通过运行以下每个命令从单独的终端选项卡或窗口连接到每个主机的客户端

docker exec -it clickhouse-01 clickhouse-client
docker exec -it clickhouse-02 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_1S_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_1S_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
ORDER BY (postcode1, postcode2, addr1, addr2);

请注意,它与原始 英国房价 示例数据集教程中使用的 CREATE 语句相同,只是添加了 ON CLUSTER 子句并使用了 ReplicatedMergeTree 引擎。

ON CLUSTER 子句专为 DDL(数据定义语言)查询(如 CREATEDROPALTERRENAME)的分布式执行而设计,确保这些模式更改应用于集群中的所有节点。

ReplicatedMergeTree 引擎的工作方式与普通的 MergeTree 表引擎相同,但它也会复制数据。

你可以从 clickhouse-01clickhouse-02 客户端运行以下查询,以确认表已在整个集群中创建

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

插入数据

由于数据集很大,并且完全导入需要几分钟,因此我们首先只插入一个较小的子集。

clickhouse-01 使用以下查询插入较小的子集数据

INSERT INTO uk.uk_price_paid_local
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'
) LIMIT 10000
SETTINGS max_http_get_redirects=10;

请注意,数据已完全复制到每个主机

-- clickhouse-01
SELECT count(*)
FROM uk.uk_price_paid_local

--   ┌─count()─┐
-- 1.│   10000 │
--   └─────────┘

-- clickhouse-02
SELECT count(*)
FROM uk.uk_price_paid_local

--   ┌─count()─┐
-- 1.│   10000 │
--   └─────────┘

为了演示其中一台主机发生故障时会发生什么,请从任何主机创建一个简单的测试数据库和测试表

CREATE DATABASE IF NOT EXISTS test ON CLUSTER cluster_1S_2R;
CREATE TABLE test.test_table ON CLUSTER cluster_1S_2R
(
    `id` UInt64,
    `name` String
)
ENGINE = ReplicatedMergeTree
ORDER BY id;

uk_price_paid 表一样,我们可以从任何主机插入数据

INSERT INTO test.test_table (id, name) VALUES (1, 'Clicky McClickface');

但是,如果其中一台主机停止运行会发生什么?要模拟此情况,请通过运行以下命令停止 clickhouse-01

docker stop clickhouse-01

通过运行以下命令检查主机是否已停止

docker-compose ps
NAME                   IMAGE                                        COMMAND            SERVICE                CREATED          STATUS          PORTS
clickhouse-02          clickhouse/clickhouse-server:latest          "/entrypoint.sh"   clickhouse-02          X minutes ago    Up X minutes    127.0.0.1:8124->8123/tcp, 127.0.0.1:9001->9000/tcp
clickhouse-keeper-01   clickhouse/clickhouse-keeper:latest-alpine   "/entrypoint.sh"   clickhouse-keeper-01   X minutes ago    Up X minutes    127.0.0.1:9181->9181/tcp
clickhouse-keeper-02   clickhouse/clickhouse-keeper:latest-alpine   "/entrypoint.sh"   clickhouse-keeper-02   X minutes ago    Up X minutes    127.0.0.1:9182->9181/tcp
clickhouse-keeper-03   clickhouse/clickhouse-keeper:latest-alpine   "/entrypoint.sh"   clickhouse-keeper-03   X minutes ago    Up X minutes    127.0.0.1:9183->9181/tcp

clickhouse-01 停止运行时,将另一行数据插入测试表并查询该表

INSERT INTO test.test_table (id, name) VALUES (2, 'Alexey Milovidov');
SELECT * FROM test.test_table;
   ┌─id─┬─name───────────────┐
1. │  1 │ Clicky McClickface │
2. │  2 │ Alexey Milovidov   │
   └────┴────────────────────┘

现在使用以下命令重新启动 clickhouse-01(你可以再次运行 docker-compose ps 以确认)

docker start clickhouse-01

在运行 docker exec -it clickhouse-01 clickhouse-client 后,从 clickhouse-01 再次查询测试表

SELECT * FROM test.test_table
   ┌─id─┬─name───────────────┐
1. │  1 │ Clicky McClickface │
2. │  2 │ Alexey Milovidov   │
   └────┴────────────────────┘

如果此时你想导入完整的英国房价数据集进行试验,可以运行以下查询来执行此操作

TRUNCATE TABLE uk.uk_price_paid_local ON CLUSTER cluster_1S_2R;
INSERT INTO uk.uk_price_paid_local
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;

clickhouse-02clickhouse-01 查询该表

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

结论

此集群拓扑的优点是,使用两个副本,你的数据存在于两个单独的主机上。如果一台主机发生故障,另一个副本将继续提供数据,而不会丢失任何数据。这消除了存储级别的单点故障。

当一台主机停止运行时,剩余的副本仍然能够

  • 处理读取查询而不会中断
  • 接受新的写入(取决于你的一致性设置)
  • 保持应用程序的服务可用性

当故障主机恢复在线时,它能够

  • 自动同步缺失的数据,从健康的副本
  • 恢复正常运行,无需手动干预
  • 快速恢复完全冗余

在下一个示例中,我们将研究如何设置一个具有两个分片但只有一个副本的集群。

    © . This site is unofficial and not affiliated with ClickHouse, Inc.