ReplicatedMergeTree天然支持多副本自动同步,无需“双向”配置;关键在于ZooKeeper路径全局唯一且模板统一、macros正确配置并重载、各节点建表语句完全一致、ZK集群高可用及时钟同步。

ReplicatedMergeTree 本身不支持“双向副本”这种说法——它天然就是多副本协同机制,写入任意一个副本,其他副本自动同步,不存在主从单向或手动指定方向的问题。所谓“跨节点双向”,其实是对 ReplicatedMergeTree 基本行为的误解;真正要配的是「跨节点自动同步」,核心在于 ZooKeeper 路径一致性 + 宏变量正确展开 + 表结构完全一致。
ReplicatedMergeTree 的 zk_path 必须全局唯一且路径模板统一
每个分片(shard)对应一个 ZooKeeper 路径前缀,所有该分片下的副本必须共用同一路径,否则无法感知彼此为同一组副本。
-
/clickhouse/tables/{shard}/metrics是推荐写法,{shard}和{replica}必须由 macros 配置真实展开,不能硬编码成固定字符串 - 若在 node1 上建表用了
'/clickhouse/tables/01/metrics',node2 就绝不能写成'/clickhouse/tables/02/metrics',否则两个副本各自独立,互不同步 - ZooKeeper 路径中不能出现节点 IP 或主机名等易变字段,否则扩容或重装后路径不一致,导致副本“失联”
macros.xml 配置必须存在且被正确加载
ClickHouse 不会自动推导 {shard} 和 {replica},全靠 macros 配置文件注入。漏配、错配、未 reload 都会导致建表失败或副本静默失效。
- 在
/etc/clickhouse-server/config.d/macros.xml中定义(不是 config.xml): <?xml version="1.0"?> <yandex> <macros> <shard>01</shard> <replica>replica-01</replica> </macros> </yandex>- 每个节点的
<replica>值必须唯一(如replica-01、replica-02),<shard>值按分片分组(同分片内所有节点相同) - 修改后需执行
sudo systemctl reload clickhouse-server,仅 restart 不保证 macros 生效
建表语句必须在每个节点单独执行,且结构完全一致
ReplicatedMergeTree 不复制 DDL,只同步 INSERT/ALTER PARTITION 等数据变更。表结构差异(哪怕只是注释或 TTL 表达式顺序不同)都会导致后台 merge 失败或查询报错。
- 不要依赖
CREATE TABLE ... ON CLUSTER自动下发——它只保证语句执行,不校验结果是否成功,也不处理宏变量上下文 - 所有副本节点上执行的
CREATE TABLE语句,除了{replica}宏展开值不同,其余字面量必须逐字符一致 - 验证方式:查
system.tables确认engine_full字段含相同参数;查system.replicas确认is_leader有且仅有一个为 1(选举正常) - 常见错误:
Code: 252. DB::Exception: Table was not found on replica—— 通常是某节点漏建表,或 zk_path 展开后实际不匹配
insert_quorum 和 read_from_replicas 影响实际“可见性”
即使副本同步完成,客户端读写行为仍受配置影响。默认情况下写入任意副本即返回成功,但可能还没来得及同步到其他节点就被读到了(脏读风险)。
- 写强一致性:在用户级设置
insert_quorum = 2,确保至少 2 个副本落盘才返回成功 - 读负载分散:连接时加参数
?load_balancing=in_order&prefer_localhost_replica=0,避免总打到同一副本 - 注意:
distributed_replica_max_delay_ms默认 30000,若副本延迟超 30 秒,查询可能跳过该副本——这不是故障,是主动降级策略
最容易被忽略的一点:ZooKeeper 节点列表必须全部可达,且时间同步误差不能超过 30 秒。哪怕只有一个 ZK node 不响应,ReplicatedMergeTree 后台线程就会卡住日志消费,表现为 system.replicas 中 queue_size > 0 持续增长,新数据迟迟不出现。

















