跳转到主要内容
本页不适用于 ClickHouse Cloud。本文所述流程在 ClickHouse Cloud 服务中已实现自动化。
ClickHouse Keeper 为数据复制分布式 DDL查询的执行提供协调系统。ClickHouse Keeper 与 ZooKeeper 兼容。

实现细节

ZooKeeper 是最早广为人知的开源协调系统之一。它使用 Java 实现,并拥有简单而强大的数据模型。ZooKeeper 的协调算法 ZooKeeper Atomic Broadcast (ZAB) 无法为读操作提供线性一致性保证,因为每个 ZooKeeper 节点都在本地处理读请求。与 ZooKeeper 不同,ClickHouse Keeper 使用 C++ 编写,并采用了 RAFT 算法实现。该算法可为读写同时提供线性一致性,并且在多种语言中都有开源实现。 默认情况下,ClickHouse Keeper 提供与 ZooKeeper 相同的保证:写入具备线性一致性,而读取不具备线性一致性。它具有兼容的客户端/服务器协议,因此任何标准的 ZooKeeper 客户端都可以与 ClickHouse Keeper 交互。快照和日志的格式与 ZooKeeper 不兼容,但 clickhouse-keeper-converter 工具可以将 ZooKeeper 数据转换为 ClickHouse Keeper 快照。ClickHouse Keeper 的服务器间协议也与 ZooKeeper 不兼容,因此无法构建混合的 ZooKeeper / ClickHouse Keeper 集群。 ClickHouse Keeper 对访问控制列表 (ACL) 的支持方式与 ZooKeeper 相同。ClickHouse Keeper 支持同样的一组权限,并提供完全相同的内置方案:worldauthdigestdigest 身份验证方案使用 username:password 这一组凭据,其中密码采用 Base64 编码。
不支持外部集成。

配置

ClickHouse Keeper 既可作为 ZooKeeper 的独立替代方案使用,也可作为 ClickHouse server 的内部组件。在这两种情况下,配置使用的 .xml 文件几乎相同。

Keeper 配置设置

主要的 ClickHouse Keeper 配置标签为 <keeper_server>,包含以下参数: 其他常用参数继承自 ClickHouse server 配置 (listen_hostlogger 等) 。

内部协调设置

内部协调设置位于 <keeper_server>.<coordination_settings> 部分,包含以下参数: Quorum 配置位于 <keeper_server>.<raft_configuration> 部分,包含各服务器的描述。 整个 quorum 只有一个参数 secure,用于为 quorum 参与者之间的通信启用加密连接。如果节点之间的内部通信需要 SSL 连接,可将该参数设为 true;否则可不指定。 每个 <server> 的主要参数有:
  • id — quorum 中的服务器标识符。
  • hostname — 该服务器所在主机的主机名。
  • port — 该服务器监听连接的端口。
  • can_become_leader — 设为 false 可将服务器配置为 learner。如果省略,则默认为 true
如果你的 ClickHouse Keeper 集群拓扑发生变化 (例如替换某台服务器) ,请务必保持 server_idhostname 的映射一致,并避免打乱现有 server_id 的对应关系,或将已有 server_id 复用于其他服务器 (例如,在依赖自动化脚本部署 ClickHouse Keeper 时就可能发生这种情况) 。如果某个 Keeper 实例所在的主机可能发生变化,我们建议定义并使用主机名,而不是直接使用 IP 地址。更改主机名等同于移除并重新添加该服务器,而在某些情况下这可能无法做到 (例如,没有足够的 Keeper 实例来形成 quorum) 。
默认禁用 async_replication,以避免破坏向后兼容性。如果你的集群中所有 Keeper 实例运行的版本都支持 async_replication (v23.9+) ,我们建议启用它,因为它可以提升性能且没有任何缺点。
带有 test_keeper_ 前缀的集成测试中提供了三节点 quorum 的配置示例。下面是服务器 #1 的示例配置:

如何运行

ClickHouse Keeper 已集成在 ClickHouse server 软件包中,只需将 <keeper_server> 配置添加到 /etc/your_path_to_config/clickhouse-server/config.xml,然后像平常一样启动 ClickHouse server 即可。如果你想运行独立运行的 ClickHouse Keeper,也可以用类似的方式启动:
如果没有该符号链接 (clickhouse-keeper) ,您可以创建一个,或将 keeper 指定为 clickhouse 的参数:

四字母命令

ClickHouse Keeper 也提供 4lw 命令,其用法与 ZooKeeper 基本相同。每个命令都由四个字母组成,例如 mntrstat 等。还有一些比较常用的命令:stat 提供有关 server 和已连接客户端的常规信息,srvr 提供 server 的扩展信息,cons 提供 connections 的扩展信息。 4lw 命令有一个白名单配置项 four_letter_word_white_list,其默认值为 conf,cons,crst,envi,ruok,srst,srvr,stat,wchs,dirs,mntr,isro,rcvr,apiv,csnp,lgif,rqld,ydld 你可以通过 telnet 或 nc 在客户端端口向 ClickHouse Keeper 发送这些命令。
以下是 4lw 命令的详细说明:
  • ruok:测试 server 是否正在运行且未处于 error 状态。如果 server 正在运行,会返回 imok;否则将完全没有响应。返回 imok 并不一定表示 server 已加入 quorum,它只说明 server 进程处于活动状态,并已绑定到指定的客户端端口。要查看与 quorum 相关的状态以及客户端 connection 信息,请使用 stat
  • mntr:输出一组可用于监控集群健康状态的变量。
  • srvr:列出 server 的完整信息。
  • stat:列出 server 和已连接客户端的简要信息。
  • srst:重置服务器统计信息。该命令会影响 srvrmntrstat 的结果。
  • conf: 打印当前服务配置的详细信息。
  • cons:列出连接到此服务器的所有客户端的完整连接/会话信息。包括收发数据包数量、会话 ID、操作延迟、最近执行的操作等信息……
  • crst:重置所有连接的连接/会话统计信息。
  • envi: 输出服务环境的详细信息
  • dirs:显示快照和日志文件的总大小 (单位为字节)
  • isro:用于检查 server 是否以只读模式运行。处于只读模式时,server 会返回 ro;否则返回 rw
  • wchs:列出服务器上 watches 的简要信息。
  • wchc:按会话列出服务器上的 watch 详细信息。该命令会输出会话 (连接) 及其关联的 watch (路径) 列表。请注意,具体开销取决于 watch 的数量,此操作可能代价较高 (会影响服务器性能) ,请谨慎使用。
  • wchp:按路径列出服务器上的 watches 详细信息。它会输出路径 (znodes) 及其关联会话的列表。请注意,watches 数量较多时,此操作的开销可能很大 (即会影响服务器性能) ,请谨慎使用。
  • dump:列出未完成的会话和临时节点。此命令仅在 leader 上有效。
  • csnp:调度一个快照创建任务。成功时返回已调度快照的最后一个已提交日志索引,失败时返回 Failed to schedule snapshot creation task.lgif 命令可帮助你判断快照是否已完成。
  • lgif:Keeper 日志信息。first_log_idx:当前节点在日志存储中的第一个日志索引;first_log_term:当前节点的第一个日志任期;last_log_idx:当前节点在日志存储中的最后一个日志索引;last_log_term:当前节点的最后一个日志任期;last_committed_log_idx:当前节点在状态机中的最后一个已提交日志索引;leader_committed_log_idx:当前节点视角下 leader 的已提交日志索引;target_committed_log_idx:应提交到的目标日志索引;last_snapshot_idx:最近一次快照中最大的已提交日志索引。
  • rqld:请求成为新的 leader。若请求发送成功,则返回 Sent leadership request to leader.;若未发送,则返回 Failed to send leadership request to leader.。如果该节点已是 leader,则结果与请求发送成功时相同。
  • ftfl:列出所有功能开关,以及它们是否已在 Keeper 实例上启用。
  • ydld:请求让出 leader 角色并切换为跟随者。如果接收该请求的 server 是 leader,它会先暂停写入操作,等待继任者 (当前 leader 不可能成为继任者) 完成对最新日志的追平,然后辞去 leader 身份。继任者将自动选出。如果请求发送成功,则返回 Sent yield leadership request to leader.;如果请求未发送,则返回 Failed to send yield leadership request to leader.。如果该节点本身已经是跟随者,结果与请求已发送时相同。
  • pfev:返回所有已收集事件的值。对于每个事件,会返回事件名称、事件值及其描述。

HTTP 控制

ClickHouse Keeper 提供了 HTTP 接口,用于检查副本是否已准备好接收流量。在 Kubernetes 等云环境中可使用该接口。 启用 /ready 端点的配置示例:

功能开关

Keeper 与 ZooKeeper 及其客户端完全兼容,但也引入了一些 ClickHouse 客户端可用的特有功能和请求类型。 由于这些功能可能带来不兼容的变更,因此其中大多数默认处于禁用状态,可通过 keeper_server.feature_flags 配置启用。 也可以显式禁用所有功能。 如果您想为 Keeper 集群启用某个新功能,建议先将集群中的所有 Keeper 实例升级到支持该功能的版本,再启用该功能本身。 下面是一个功能开关配置示例,其中禁用了 multi_read,并启用了 check_not_exists
以下功能可用:
从 25.7 版本开始,部分功能开关默认启用。 建议将 Keeper 升级到 25.7+ 的方式是先升级到 24.9+ 版本。

从 ZooKeeper 迁移

无法从 ZooKeeper 无缝迁移到 ClickHouse Keeper。您必须先停止 ZooKeeper 集群,转换数据,然后再启动 ClickHouse Keeper。clickhouse-keeper-converter 工具可将 ZooKeeper 的日志和快照转换为 ClickHouse Keeper 快照。该工具要求 ZooKeeper 版本为 3.4 或更高。

迁移前准备

迁移需要停止数据摄取。请在开始前安排好维护窗口。 在停止 ZooKeeper 之前,先停止会修改协调元数据的 ClickHouse 后台任务。例如:
在迁移前记录用于比对的指标,以便在迁移后验证一致性。

迁移步骤

  1. 停止向所有 ClickHouse 节点摄取数据。
  2. 停止所有 ClickHouse 节点上的后台任务 (参见上文) 。
  3. 停止所有 ZooKeeper 节点。
  4. 可选但建议执行:找到 ZooKeeper 的 leader 节点,将其重新启动后再停止。这样会强制 ZooKeeper 在转换前先将一致性快照写入磁盘。
  5. 在 leader 节点上运行 clickhouse-keeper-converter。如果你安装了完整的 ClickHouse 可执行文件,请改用 keeper-converter 子命令 (clickhouse keeper-converter) 。如果两者都不可用,请下载该可执行文件
  1. 将快照复制到所有 ClickHouse Keeper 节点。在任何节点启动之前,每个节点上都必须已有该快照——如果某个节点在没有快照的情况下启动,可能会以空状态将自己选举为 leader。
  2. 更新 ClickHouse 配置,使其指向新的 Keeper 集群。
  3. 在所有节点上启动 ClickHouse Keeper,然后重启 ClickHouse。
  4. 将各项指标与迁移前的基线进行比较,以验证一致性。
  5. 恢复后台任务并重启数据摄取。

整合多个 ZooKeeper 集群

如果您运行了多个 ZooKeeper 集群 (例如每个分片组一个) ,可以将它们整合到一个 ClickHouse Keeper 集群中。官方 clickhouse-keeper-converter 工具仅支持一对一转换 (一个 ZooKeeper 集群对应一个 Keeper 快照) ,因此若要进行整合,需要修改转换器的源代码以合并多个快照:
  1. 在每个 ZooKeeper 集群上分别运行 clickhouse-keeper-converter,并将各自的输出写入不同的目录。
  2. 按顺序对快照文件进行反序列化。合并时,重新计算 numChildren 值,以避免不同源集群的命名空间之间发生节点 ID 冲突。
  3. 将合并后的输出写入目标 ClickHouse Keeper 快照目录。

处理加密和 ACL

ClickHouse Keeper 支持与 ZooKeeper 相同的 ACL 方案 (worldauthdigest) 。在转换过程中如何处理 ACL,取决于你的 ZooKeeper 配置:
  • 完全加密或完全未加密:可直接转换。转换器会保留现有的 ACL 信息。
  • 部分加密:转换前,先为超级管理员账户授予权限,并使用 setAcl -R 清除受影响 path 上的 ACL。转换完成后,如有需要,再在 ClickHouse Keeper 中重新启用加密。

验证迁移

启动 ClickHouse Keeper 并重启 ClickHouse 后,请将关键指标与迁移前的基线进行对比,以确认迁移已成功。 在整合多个 ZooKeeper 集群时,需要区分以下两类:
  • 公共路径:多个源集群中都存在且数据相同的路径——这些路径应在合并后的输出中去重。
  • 差异化路径:仅存在于特定集群下的路径 (例如每个分片组在 /clickhouse/tables 下的路径) ——这些路径必须从正确的源中保留下来。
避免直接遍历大型 ZooKeeper 树进行比较。应在转换过程中将所有已转换的路径输出到文件中。

迁移后调优

迁移后,若集群规模更大或吞吐量更高,可考虑调整以下设置: 这些设置需在 Keeper 配置coordination_settings 下进行配置。

丢失 quorum 后的恢复

由于 ClickHouse Keeper 使用 Raft,因此它可根据集群规模容忍一定数量的节点崩溃。 例如,对于一个 3 节点集群,如果只有 1 个节点崩溃,它仍能继续正常工作。 集群配置可以动态调整,但也有一些限制。重新配置同样依赖于 Raft, 因此,要向集群中添加或移除节点,就必须具备 quorum。如果集群同时丢失了过多节点,且无法 再次将其启动,Raft 就会停止工作,并且不再允许你通过常规方式重新配置集群。 不过,ClickHouse Keeper 提供了一种恢复模式,允许你仅用 1 个节点强制重新配置集群。 只有在你无法再次启动这些节点,或者无法在相同端点上启动新的实例时,才应将其作为最后手段。 继续之前,请务必注意以下事项:
  • 确保故障节点无法再次连接到集群。
  • 在步骤明确说明之前,不要启动任何新节点。
确认以上事项无误后,你需要执行以下操作:
  1. 选择一个 Keeper 节点作为新的 leader。请注意,该节点的数据将用于整个集群,因此建议选择状态最新的节点。
  2. 在执行任何其他操作之前,先备份所选节点的 log_storage_pathsnapshot_storage_path 文件夹。
  3. 在你打算使用的所有节点上重新配置集群。
  4. 向你选定的节点发送四字命令 rcvr,这会将该节点切换到恢复模式;或者停止所选节点上的 Keeper 实例,然后使用 --force-recovery 参数重新启动它。
  5. 逐个启动新节点上的 Keeper 实例,并确保在启动下一个节点之前,mntrzk_server_state 返回 follower
  6. 在恢复模式下,leader 节点会对 mntr 命令返回错误消息,直到它与新节点达成 quorum;同时会拒绝来自客户端和跟随者的任何请求。
  7. 达成 quorum 后,leader 节点将恢复正常运行模式,并开始接受所有请求。可使用 mntr 通过 zk_server_state 返回 leader 来验证 Raft 已恢复正常。

在 Keeper 中使用磁盘

Keeper 支持使用部分外部磁盘来存储快照、日志文件和状态文件。 支持的磁盘类型包括:
  • s3_plain
  • s3
  • local
下面是配置中包含的磁盘定义示例。
要将某个磁盘用于存储日志,应将 keeper_server.log_storage_disk 配置设为该磁盘的名称。 要将某个磁盘用于存储快照,应将 keeper_server.snapshot_storage_disk 配置设为该磁盘的名称。 此外,keeper_server.latest_log_storage_disk 可用于存储最新日志,keeper_server.latest_snapshot_storage_disk 可用于存储最新快照。 在这种情况下,创建新的日志或快照时,Keeper 会自动将文件移动到正确的磁盘。 要将某个磁盘用于存储状态文件,应将 keeper_server.state_storage_disk 配置设为该磁盘的名称。 在不同磁盘之间移动文件是安全的,即使 Keeper 在传输过程中停止,也不会有数据丢失的风险。 在文件完全移动到新磁盘之前,它不会从旧磁盘中删除。 当 Keeper 的 keeper_server.coordination_settings.force_sync 设置为 true (默认值即为 true) 时,对于所有类型的磁盘,都无法满足某些保证。 目前,只有 local 类型的磁盘支持持久化同步。 如果使用 force_sync,且未使用 latest_log_storage_disk,则 log_storage_disk 应为 local 磁盘。 如果使用了 latest_log_storage_disk,则它必须始终是 local 磁盘。 如果禁用 force_sync,则在任何配置下都可以使用所有类型的磁盘。 Keeper 实例的一种可能存储配置如下所示:
此实例会将除最新日志外的所有日志存储在 log_s3_plain 磁盘上,而最新日志则存储在 log_local 磁盘上。 快照同理:除最新快照外的所有快照都将存储在 snapshot_s3_plain 上,而最新快照则存储在 snapshot_local 磁盘上。

更改磁盘配置

在应用新的磁盘配置之前,请手动备份所有 Keeper 日志和快照。
如果定义了分层磁盘配置 (为最新文件使用单独的磁盘) ,Keeper 会在启动时尝试自动将文件移动到对应的磁盘。 仍然提供与之前相同的保障:在文件完全迁移到新磁盘之前,不会从旧磁盘中删除,因此可以安全地 多次重启。 如果需要将文件迁移到全新的磁盘 (或者从双磁盘配置迁移到单磁盘配置) ,可以为 keeper_server.old_snapshot_storage_diskkeeper_server.old_log_storage_disk 定义多个值。 以下配置展示了如何从之前的双磁盘配置迁移到全新的单磁盘配置:
启动时,所有日志文件都会从 log_locallog_s3_plain 移至 log_local2 磁盘。 此外,所有快照文件都会从 snapshot_localsnapshot_s3_plain 移至 snapshot_local2 磁盘。

配置日志缓存

为尽量减少从磁盘读取的数据量,Keeper 会在内存中缓存日志条目。 如果请求较大,日志条目会占用过多内存,因此缓存日志的数量设有上限。 该上限由以下两个配置控制:
  • latest_logs_cache_size_threshold - 缓存中保存的最新日志总大小
  • commit_logs_cache_size_threshold - 接下来需要提交的后续日志总大小
如果默认值过大,可以通过调低这两个配置来减少内存占用。
你可以使用 pfev 命令查看从各个缓存和文件中读取的日志量。 你也可以使用 Prometheus 端点提供的指标来跟踪这两个缓存的当前大小。

Prometheus

Keeper 可以暴露供 Prometheus 抓取的指标数据。 设置:
  • endpoint – Prometheus 服务器抓取指标的 HTTP 端点。以 ’/’ 开头。
  • portendpoint 的端口。
  • metrics – 用于控制是否暴露 system.metrics 表中的指标的标志。
  • events – 用于控制是否暴露 system.events 表中的指标的标志。
  • asynchronous_metrics – 用于控制是否暴露 system.asynchronous_metrics 表中当前指标值的标志。
示例
检查 (将 127.0.0.1 替换为你的 ClickHouse 服务器的 IP 地址或主机名) :
另请参阅 ClickHouse Cloud Prometheus 集成

ClickHouse Keeper 用户指南

本指南提供了配置 ClickHouse Keeper 所需的简单最小设置,并附带一个测试分布式操作的示例。该示例在 Linux 上使用 3 个节点进行。

1. 使用 Keeper 设置来配置节点

  1. 在 3 台主机 (chnode1chnode2chnode3) 上安装 3 个 ClickHouse 实例。 (有关 ClickHouse 的安装详情,请参阅快速入门。)
  2. 在每个节点上,添加以下配置项,以允许通过网络接口进行对外通信。
  3. 将以下 ClickHouse Keeper 配置添加到三台服务器中的每一台,并为各服务器更新 <server_id> 设置;例如,chnode1 应设为 1chnode2 应设为 2,依此类推。
    以下是上文中使用的基本设置:
  4. 启用 ZooKeeper 组件。它将使用 ClickHouse Keeper 引擎:
    以上是前面用到的基本设置:
  5. 重启 ClickHouse,并验证每个 Keeper 实例都在运行。在每台服务器上执行以下命令。如果 Keeper 正在运行且状态正常,ruok 命令将返回 imok
  6. system 数据库中有一张名为 zookeeper 的表,包含你的 ClickHouse Keeper 实例的详细信息。我们来查看这张表:
    表如下所示:

2. 在 ClickHouse 中配置集群

  1. 我们来配置一个简单集群:在其中 2 个节点上设置 2 个分片,且每个分片只有 1 个副本。第三个节点将用于满足 ClickHouse Keeper 的法定人数要求。更新 chnode1chnode2 上的配置。以下集群在每个节点上定义了 1 个分片,总共 2 个分片,且不使用复制。在此示例中,部分数据会位于一个节点上,另一部分数据会位于另一个节点上:
  2. 重启 ClickHouse 并验证集群已创建:
    你应该会看到你的集群:

3. 创建并测试分布式表

  1. chnode1 上使用 ClickHouse client,在新集群中创建一个新数据库。ON CLUSTER 子句会自动在两个节点上创建该数据库。
  2. db1 数据库中创建一个新表。同样,ON CLUSTER 会在两个节点上创建该表。
  3. chnode1 节点上插入两行数据:
  4. chnode2 节点上再插入两行数据:
  5. 请注意,在每个节点上执行 SELECT 语句时,只会看到该节点上的数据。例如,在 chnode1 上:
    chnode2 上:
  6. 你可以创建一个 Distributed 表,用来表示这两个分片上的数据。使用 Distributed 表引擎的表本身不存储任何数据,但支持在多个服务器上进行分布式查询处理。读取会访问所有分片,写入也可以分发到各个分片。请在 chnode1 上运行以下查询:
  7. 可以看到,查询 dist_table 会返回来自这两个分片的全部四行数据:

摘要

本指南介绍了如何使用 ClickHouse Keeper 搭建集群。借助 ClickHouse Keeper,您可以配置集群,并定义可在各个分片之间复制的分布式表。

使用唯一路径配置 ClickHouse Keeper

本页不适用于 ClickHouse Cloud。本文所述流程在 ClickHouse Cloud 服务中已实现自动化。

说明

本文介绍如何使用内置的 {uuid} 宏设置, 在 ClickHouse Keeper 或 ZooKeeper 中创建唯一的条目。唯一的 路径 在频繁创建和 drop 表时很有帮助,因为 这样可以避免每次都要等待几分钟,让 Keeper 的垃圾回收 删除 路径 条目;这是因为每次创建 路径 时,都会在该 路径 中使用新的 uuid;路径 永远不会被重复使用。

示例环境

一个三节点集群,配置为在全部三个节点上运行 ClickHouse Keeper, 并在其中两个节点上运行 ClickHouse。这样一来, ClickHouse Keeper 将拥有三个节点 (包括一个仲裁节点) ,并且 ClickHouse 只有一个分片,由两个副本组成。 集群配置示例:

将表配置为使用 {uuid} 的步骤

  1. 在每台服务器上配置宏 服务器 1 的示例:
请注意,我们为 shardreplica 定义了宏,但 {uuid} 并未在此定义——它是内置的,无需单独定义。
  1. 创建数据库
  1. 使用宏和 {uuid} 在集群中创建表
  1. 创建分布式表

测试

  1. 向第一个节点插入数据 (例如 chnode1)
  1. 向第二个节点插入数据 (例如,chnode2)
  1. 通过分布式表查看记录

备选方案

默认的复制路径可以预先通过宏定义,也可以使用 {uuid}
  1. 在每个节点上为表设置默认值
如果某些数据库使用了节点,你也可以在每个节点上定义宏 {database}
  1. 创建表时不显式指定参数:
  1. 验证其是否使用了默认配置中的设置

故障排查

获取表信息和 UUID 的示例命令:
获取 ZooKeeper 中上述表 (含 UUID) 信息的示例命令
数据库必须使用 Atomic;如果是从早期版本升级, default 数据库很可能是 Ordinary 类型。
检查方法如下: 例如,

ClickHouse Keeper 动态重新配置

本页不适用于 ClickHouse Cloud。本文所述流程在 ClickHouse Cloud 服务中已实现自动化。

说明

如果启用了 keeper_server.enable_reconfiguration,ClickHouse Keeper 会部分支持 ZooKeeper 的 reconfig 命令,以实现集群的动态重新配置。
如果此设置已关闭,你可以通过手动修改副本的 raft_configuration 部分来重新配置集群。请确保编辑所有副本上的文件,因为只有 leader 会应用更改。 或者,你也可以通过任何兼容 ZooKeeper 的客户端发送 reconfig 查询。
虚拟节点 /keeper/config 包含最近一次已提交的集群配置,格式如下:
  • 每个 server 条目以换行符分隔。
  • server_type 的值可以是 participantlearner (learner 不参与 leader 选举) 。
  • server_priority 是一个非负整数,用于指定在 leader 选举中应优先选择哪些节点。 优先级为 0 表示该 server 永远不会成为 leader。
示例:
你可以使用 reconfig 命令来添加新服务器、移除现有服务器,以及调整现有服务器的优先级。以下是一些示例 (使用 clickhouse-keeper-client) :
以下是 kazoo 的示例:
joining 中的服务器应采用上文所述的 server 格式。各服务器条目之间应以逗号分隔。 添加新服务器时,可以省略 server_priority (默认值为 1) 和 server_type (默认值 为 participant) 。 如果要更改现有服务器的优先级,请将该服务器及目标优先级一起添加到 joining 中。 服务器主机、端口和类型必须与现有服务器配置相同。 服务器会按照它们在 joiningleaving 中出现的顺序添加和移除。 joining 中的所有更新都会先于 leaving 中的更新处理。 Keeper 重新配置的实现有一些注意事项:
  • 仅支持增量重新配置。带有非空 new_members 的请求会被拒绝。 ClickHouse Keeper 的实现依赖 NuRaft API 动态更改成员关系。NuRaft 只能一次 添加一台服务器或移除一台服务器,每次只能处理一个。这意味着对配置的每次更改 (joining 中的每一项、leaving 中的每一项) 都必须单独决定。因此不提供批量 重新配置,因为这会对最终用户造成误导。 同样也无法更改服务器类型 (participant/learner) ,因为 NuRaft 不支持这一点,而 唯一的办法是先移除再添加服务器,这同样会造成误导。
  • 不能使用返回的 znodestat 值。
  • from_version 字段不会被使用。所有设置了 from_version 的请求都会被拒绝。 这是因为 /keeper/config 是一个虚拟节点,也就是说它不会存储在 持久化存储中,而是会针对每个请求根据指定的节点配置动态生成。 作出这一决定是为了避免数据重复,因为 NuRaft 已经存储了该配置。
  • 与 ZooKeeper 不同,无法通过提交 sync 命令来等待集群重新配置完成。 新配置最终会生效,但不保证具体时间。
  • reconfig 命令可能会因各种原因失败。你可以检查集群的状态,查看更新 是否已应用。

将单节点 keeper 转换为集群

有时需要将实验性的 keeper 节点扩展为集群。下面是将其逐步扩展为 3 节点集群的方案:
  • 重要:新增节点必须分批添加,且每批数量必须小于当前 法定人数,否则它们会自行选举出一个 leader。本例中按每次一个节点添加。
  • 现有 keeper 节点必须开启 keeper_server.enable_reconfiguration 配置参数。
  • 使用 keeper 集群的完整新配置启动第二个节点。
  • 节点启动后,使用 reconfig 将其添加到节点 1。
  • 然后启动第三个节点,并使用 reconfig 将其添加进来。
  • 更新 clickhouse-server 配置,将新的 keeper 节点添加进去,然后重启以应用更改。
  • 更新节点 1 的 raft 配置,并可选择重启它。
为了更好地熟悉这一过程,这里有一个 sandbox 仓库

不支持的功能

虽然 ClickHouse Keeper 的目标是与 ZooKeeper 完全兼容,但仍有一些功能尚未实现 (不过相关开发仍在持续进行) :
最后修改于 2026年6月25日