CodeWalk

ClickHouse ZooKeeper依赖与分布式DDL执行机制

作者:我是大山 · 2026-05-30 12:55

ClickHouse中的ReplicatedMergeTree为什么依赖ZooKeeper?请解释ZooKeeper在ClickHouse集群中的角色(元数据协调/副本同步/DDL分发),以及分布式DDL(ON CLUSTER语法)的执行流程。ZK负载过高如何优化?给出减少ZK压力的最佳实践。

回答

我是大山

ClickHouse与ZooKeeper的关系:

1. ZooKeeper的角色

CREATE TABLE orders ON CLUSTER my_cluster (
  id UInt64,
  amount Float64
) ENGINE = ReplicatedMergeTree(
  '/clickhouse/tables/{shard}/orders',  -- ZK路径
  '{replica}'                            -- 副本名
)
ORDER BY id;
  • 元数据协调:存储表结构、Part信息、副本列表
  • 副本同步:记录各副本拥有的Data Part列表,协调Merge
  • 分布式DDLON CLUSTER语法通过ZK分发DDL到所有节点
  • Leader选举:每个分片选一个副本做Merge的Leader

2. 分布式DDL(ON CLUSTER)执行流程

  1. 客户端向任意节点发送ALTER TABLE ... ON CLUSTER cluster_name
  2. 该节点创建DDL任务写入ZK路径/clickhouse/task_queue/ddl/
  3. 集群所有节点监听该ZK路径,拉取DDL任务
  4. 各节点独立执行DDL操作
  5. 执行结果写入ZK,协调节点汇总

3. ZK负载过高的问题

  • 小Part过多导致ZK更新频繁
  • 物化视图过多增加ZK通信
  • 大量INSERT产生海量Part元数据

4. 优化最佳实践

# ZK优化配置
background_pool_size: 64
# 减少Part数量
merge_tree.max_bytes_to_merge_at_max_space_in_pool: 20000000000  # 20GB
merge_tree.max_parts_in_total: 10000
# 减少ZK操作
replicated_deduplication_window: 100  # 减少去重记录
replicated_can_become_leader: false   # 非Leader减少ZK通信

# 配置层面
- 增大写入批次(每次≥10万行)
- 合理设置分区粒度
- 使用`optimize_on_insert`按需合并