跳转到主要内容
在本示例中,你将学习如何搭建一个既支持复制、又可横向扩展的简单 ClickHouse 集群。 该集群由两个分片和两个副本组成,并配备一个 3 节点的 ClickHouse Keeper 集群, 用于负责协调管理并维持集群仲裁。
你将要搭建的集群架构如下所示:
尽管可以在同一台服务器上同时运行 ClickHouse Server 和 ClickHouse Keeper, 但我们强烈建议在生产环境中为 ClickHouse Keeper 使用专用主机, 这也是我们将在本示例中演示的方法。Keeper server 所需配置可以更小,通常每个 Keeper server 配置 4GB RAM 就足够了, 至少在你的 ClickHouse Server 规模扩大之前都是如此。

前置条件

1

设置目录结构和测试环境

示例文件以下步骤将引导你从零开始设置集群。如果你想跳过这些步骤,直接开始运行集群,也可以从 examples 仓库的 ‘docker-compose-recipes’ 目录 获取这些示例 文件。
在本教程中,您将使用 Docker compose 搭建 ClickHouse 集群。该配置同样可以修改后用于独立的本地机器、虚拟机或云实例。运行以下命令,为本示例创建目录结构:
将以下 docker-compose.yml 文件添加到 clickhouse-cluster 目录中:
docker-compose.yml
创建以下子目录和文件:
  • config.d 目录包含 ClickHouse server 配置文件 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 中的默认配置。这一行
可确保在 config.dusers.d 目录中定义的配置部分会覆盖默认 config.xmlusers.xml 文件中定义的默认配置部分。
2

配置 ClickHouse 节点

服务器配置

现在修改位于 fs/volumes/clickhouse-{}/etc/clickhouse-server/config.d 的每个空配置文件 config.xml。下方高亮显示的行需要根据各节点分别进行修改:
以下将对上述配置文件的各个部分进行详细说明。

网络与日志

通过启用 listen host 设置,即可允许通过网络接口进行外部通信。这可确保 ClickHouse server 主机可被其他 主机访问:
HTTP API 端口设为 8123
clickhouse-client 与其他原生 ClickHouse 工具之间,以及 clickhouse-server 与其他 clickhouse-servers 之间通过 ClickHouse 的原生协议进行交互所使用的 TCP 端口设置为 9000
日志配置在 <logger> 块中定义。以下示例配置将生成一个调试日志,文件大小达到 1000M 时自动滚动,最多保留三个滚动文件:
有关日志配置的更多信息,请参阅默认 ClickHouse 配置文件中的注释。

集群配置

集群的配置在 <remote_servers> 块中进行设置。 集群名称 cluster_2S_2R 在此处定义。<cluster_2S_2R></cluster_2S_2R> 块定义了集群的布局,使用 <shard></shard><replica></replica> 配置项,并作为 distributed DDL 查询的模板——这类查询通过 ON CLUSTER 子句在整个集群中执行。默认情况下,distributed DDL 查询是允许的,但也可以通过设置 allow_distributed_ddl_queries 将其关闭。internal_replication 设置为 true,这样数据只会写入其中一个副本。
<cluster_2S_2R></cluster_2S_2R> 部分定义了集群的结构,并作为分布式 DDL 查询的模板,这些查询通过 ON CLUSTER 子句在整个集群中执行。

Keeper 配置

<ZooKeeper> 部分用于告知 ClickHouse,ClickHouse Keeper (或 ZooKeeper) 的运行位置。 由于我们使用的是 ClickHouse Keeper 集群,需要指定集群中的每个 <node>, 并分别通过 <host><port> 标签指定其 hostname 和端口号。ClickHouse Keeper 的配置将在本教程的下一步中介绍。
虽然可以让 ClickHouse Keeper 与 ClickHouse Server 运行在同一台服务器上, 但在生产环境中,我们强烈建议将 ClickHouse Keeper 部署在专用主机上。

宏配置

此外,<macros> 部分用于为复制表定义参数替换。这些替换项列于 system.macros 中,可在查询中使用 {shard}{replica} 等替换占位符。

用户配置

现在,将以下内容写入位于 fs/volumes/clickhouse-{}/etc/clickhouse-server/users.d 的每个空配置文件 users.xml
/users.d/users.xml
在此示例中,为简便起见,默认用户未设置密码。 实际生产环境中,不建议采用此方式。
在此示例中,集群中所有节点上的 users.xml 文件都相同。
3

配置 ClickHouse Keeper

接下来,您将配置用于协调的 ClickHouse Keeper。

Keeper 配置

为了使复制正常工作,需要先搭建并配置 ClickHouse Keeper 集群。ClickHouse Keeper 为数据复制提供协调系统, 可作为 ZooKeeper 的替代方案,当然也可以直接使用 ZooKeeper。 不过,推荐使用 ClickHouse Keeper,因为它能提供更好的保障和 可靠性,并且比 ZooKeeper 占用更少的资源。为了实现高可用性并 保持 quorum,建议至少运行三个 ClickHouse Keeper 节点。
ClickHouse Keeper 可以与 ClickHouse 一起运行在集群的任何节点上,不过 更推荐将其部署在专用节点上,这样就可以独立于数据库集群对 ClickHouse Keeper 集群进行扩缩容和管理。
在示例文件夹的根目录下,使用以下命令为每个 ClickHouse Keeper 节点 创建 keeper_config.xml 文件:
修改在每个 节点目录 fs/volumes/clickhouse-keeper-{}/etc/clickhouse-keeper 中创建的空配置文件。下方高亮显示的内容需要改为各节点对应的具体值:
/clickhouse-keeper/keeper_config.xml
每个配置文件都应包含以下唯一配置 (如下所示) 。 所使用的 server_id 对于集群中的对应 ClickHouse Keeper 节点必须是唯一的, 并且要与 <raft_configuration> 部分中定义的服务器 <id> 一致。 tcp_port 是 ClickHouse Keeper 客户端 使用的端口。
以下部分用于配置参与 Raft 共识算法 仲裁的服务器:
ClickHouse Cloud 简化管理ClickHouse Cloud 免去了管理分片和副本带来的运维负担。该 平台会自动处理高可用性、复制和扩缩容。 计算资源与存储相互分离,并可根据需求弹性扩展,无需手动 配置或持续维护。了解更多
4

测试设置

请确保你的机器上已运行 Docker。 在 cluster_2S_2R 目录根目录下,使用 docker-compose up 命令启动集群:
你应该会看到 docker 开始拉取 ClickHouse 和 Keeper 镜像, 随后启动容器:
要验证集群是否正在运行,请连接到任意一个节点并运行 以下查询。下面以连接到第一个节点的命令为例:
如果成功,你将看到 ClickHouse 客户端的提示符:
运行以下查询,检查为哪些 主机定义了哪些集群拓扑:
Query
Response
运行以下查询以检查 ClickHouse Keeper 集群的状态:
Query
Response
mntr 命令也常用于验证 ClickHouse Keeper 是否正在运行,并获取三个 Keeper 节点之间关系的状态信息。 在此示例使用的配置中,有三个节点协同工作。 这些节点会选举出一个 leader,其余节点则为跟随者。mntr 命令会提供与性能相关的信息,以及特定节点是跟随者还是 leader。
你可能需要安装 netcat,才能将 mntr 命令发送给 Keeper。 请参阅 nmap.org 页面了解下载信息。
clickhouse-keeper-01clickhouse-keeper-02clickhouse-keeper-03 的 shell 中运行以下命令,以检查每个 Keeper 节点的状态。下面显示的是 clickhouse-keeper-01 的命令:
下面的响应展示了来自 follower 节点的示例响应:
Response
下面的响应显示了 leader 节点返回的示例响应:
Response
至此,你已成功搭建了一个包含两个分片和两个副本的 ClickHouse 集群。 下一步,你将在该集群中创建一个表。
5

创建数据库

现在你已经确认 cluster 已正确配置并正常运行,接下来你将重新创建与 英国房产价格 示例数据集教程中使用的同一张表。该表包含自 1995 年以来英格兰和威尔士房地产成交价格的约 3000 万行 数据。请在单独的终端标签页或窗口中分别运行以下各条命令,以连接到每个主机的客户端:
你可以在每台主机的 clickhouse-client 中运行以下查询,确认除默认数据库外, 尚未创建任何其他数据库:
Query
Response
clickhouse-01 客户端中,使用 ON CLUSTER 子句运行以下分布式 DDL 查询,创建名为 uk 的新数据库:
你可以再次从每台主机的客户端运行与之前相同的查询, 以确认尽管该查询仅从 clickhouse-01 发起, 该数据库仍已在整个集群中创建:
6

在集群上创建表

现在数据库已经创建完成,接下来需要创建一个启用复制的表。在任意主机客户端上运行以下查询:
请注意,它与原始 CREATE 语句 UK property prices 示例数据集教程中使用的查询完全相同, 唯一的区别是添加了 ON CLUSTER 子句,并使用了 ReplicatedMergeTree 引擎。ON CLUSTER 子句用于分布式执行 DDL (数据定义语言) 查询,例如 CREATEDROPALTERRENAME,以确保这些 schema 变更会应用到集群中的所有节点。ReplicatedMergeTree 引擎的工作方式与普通的 MergeTree 表引擎相同,但它还会复制数据。 它需要指定两个参数:
  • zoo_path:表元数据的 Keeper/ZooKeeper 路径。
  • replica_name:表的副本名称。

zoo_path 参数可以设置为你选择的任意值,不过建议遵循 使用前缀的约定
其中:
  • {database}{table} 会自动替换。
  • {shard}{replica} 是宏,此前已在每个 ClickHouse 节点的 config.xml 文件中定义
你可以在每台主机的客户端中运行以下查询,以确认该表已在整个集群中创建:
Query
Response
7

将数据插入分布式表

要向该表插入数据,不能使用 ON CLUSTER,因为它不适用于 INSERTUPDATEDELETE 这类 DML (数据操作语言) 查询。要插入数据,必须使用 Distributed 表引擎。 正如你在搭建包含 2 个分片和 1 个副本的集群指南中所了解的,分布式表是可访问位于不同 主机上分片的表,并使用 Distributed 表引擎定义。 分布式表充当集群中所有分片之间的接口。在任意主机的客户端上,运行以下查询,基于我们在上一步创建的现有副本表来创建一个分布式表:
现在,在每台主机上,你都会在 uk 数据库中看到以下表:
可以通过以下查询,从任意主机客户端向 uk_price_paid_distributed 表插入数据:
运行以下查询,确认已插入的数据是否已均匀分布在集群的各个节点上:

结论

这种由 2 个分片和 2 个副本组成的集群拓扑,优势在于同时具备可扩展性和容错能力。 数据分布在不同主机上,降低了每个节点的存储和 I/O 压力;同时,查询会在两个分片上并行执行,从而提升性能和内存使用效率。 更重要的是,该集群即使损失一个节点,也能不中断地继续提供查询服务,因为每个分片在另一个节点上都有可用的备份副本。 这种集群拓扑的主要缺点是存储开销更高——由于每个分片都有一份副本,与没有副本的部署相比,它需要两倍的存储容量。 此外,虽然该集群能够承受单个节点故障,但如果同时失去两个节点,集群可能无法继续运行,具体取决于故障节点的位置以及分片的分布方式。 这种拓扑在可用性和成本之间取得了平衡,因此适合用于生产环境:既需要一定程度的容错能力,又不希望承担更高复制因子带来的成本。 如需了解 ClickHouse Cloud 如何处理查询,以及如何同时实现可扩展性和容错能力,请参阅”并行副本”章节。
最后修改于 2026年6月12日