CodeWalk

ClickHouse分布式DDL实现原理

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

ClickHouse的分布式DDL(ON CLUSTER语句)是如何在集群中传播和执行的?请说明DDL协调机制、执行顺序、故障处理和状态一致性保证。如何处理分布式DDL执行中的部分节点失败问题?

回答

我是大山

1. 分布式DDL架构

ClickHouse通过ZooKeeper实现分布式DDL协调:

-- ON CLUSTER语句
CREATE TABLE shard_table ON CLUSTER my_cluster (
  id UInt32,
  name String
) ENGINE = Distributed('my_cluster', ...);

执行流程

1. 发起节点生成DDL任务ID(uuid)
2. 将DDL任务写入ZK节点:/clickhouse/task_queue/ddl/
3. 各节点监听该ZK路径
4. 各节点获取任务后,本地执行DDL
5. 执行结果写入ZK:/clickhouse/task_queue/ddl/status/
6. 发起节点汇总所有节点状态

2. DDL ZooKeeper路径结构

/clickhouse/
  task_queue/
    ddl/
      query-{uuid}         # DDL任务
      status/              # 执行状态
        {host:port}        # 各节点状态

3. 执行顺序

  • 串行执行:同一时间只有一个DDL在集群中执行
  • 通过 distributed_ddl_task_timeout 控制超时
  • 重试机制:失败节点自动重试直到成功或超时

4. 故障处理

<!-- config.xml -->
<distributed_ddl>
  <path>/clickhouse/task_queue/ddl</path>
  <pool_size>16</pool_size>
  <max_entries>1000</max_entries>
</distributed_ddl>
  • 节点宕机:DDL任务保留在ZK,节点恢复后自动执行
  • 超时设置mutations_sync 控制同步等待
  • 部分失败
    • 设置 distributed_ddl.task_timeout(默认180秒)
    • 超时后视为失败,需手动清理

5. 最佳实践

-- 检查DDL执行状态
SYSTEM REPLICA QUEUES;

-- 清理卡住的DDL
SYSTEM DROP REPLICA ...;

-- 限制DDL执行时间
SET distributed_ddl.task_timeout = 600;

注意

  • 避免频繁DDL操作
  • 大表ALTER需要大量重写数据,建议低峰期执行
  • 优先使用ReplicatedMergeTree家族引擎