bigywater.tech
ClickHouse 内部原理 · 64

Replication Queue:副本落后时在排什么队

真实停止一个副本的fetch并插入多批新数据,验证replication_queue如何真实堆积任务,以及恢复后如何几秒内追平数据。

5个真实待执行任务
真实queue_size精确对应5批未同步的INSERT
几秒内追平
真实恢复fetch后队列清空、数据完全一致

做的事:真实让node2停止拉取,看它的队列如何真实堆积

代码-- 真实模拟node2"跟不上"的场景 SYSTEM STOP FETCHES demo.repl_tbl; -- 在node2上执行 -- node1继续真实插入5批新数据 INSERT INTO demo.repl_tbl SELECT number+10000*1, toString(number) FROM numbers(1000); -- ...(重复5次,每次block递增) SELECT queue_size, absolute_delay FROM system.replicas WHERE table='repl_tbl'; -- 在node2上查 SELECT type, source_replica, new_part_name FROM system.replication_queue WHERE table='repl_tbl';

验证:真实排了5个GET_PART任务,延迟2秒,行数差了5000

实测 · 本机执行输出(node2,停止fetch后node1插入了5批新数据)
SELECT queue_size, absolute_delay FROM system.replicas WHERE table='repl_tbl';
→ queue_size=5   absolute_delay=2

SELECT type, source_replica, new_part_name FROM system.replication_queue;
→ GET_PART  replica1  all_1_1_0
  GET_PART  replica1  all_2_2_0
  GET_PART  replica1  all_3_3_0
  GET_PART  replica1  all_4_4_0
  GET_PART  replica1  all_5_5_0

node1: count() = 15000
node2: count() = 10000   ← 真实差了5000行,正好是被跳过的5批

每一批新数据在node1插入之后,真实都会在Keeper里留下一条"replica1有一个新part,动作是get"的记录(本系列上一篇《Keeper》验证过的日志结构),node2因为暂停了fetch,没有真实去执行这些指令,它们就真实原样堆积在了system.replication_queue里,每一条都清楚标注了任务类型(GET_PART)、来源副本(replica1)和目标part名。

验证:恢复fetch之后,队列真实几秒内清空,数据完全追平

实测 · 本机执行输出
SYSTEM START FETCHES demo.repl_tbl;

-- 几秒后
SELECT queue_size, absolute_delay FROM system.replicas WHERE table='repl_tbl';
→ queue_size=0   absolute_delay=0

SELECT count() FROM demo.repl_tbl;
→ 15000   ← 真实追平了node1
这条队列真实是理解"副本延迟"这个概念的关键——queue_size不是一个抽象的百分比或者时间估计,而是真实待执行任务的数量,每一条都能在system.replication_queue里查到具体是哪个part、从哪个副本来、什么类型的操作(除了本文这次的GET_PART,队列里也可能出现MERGE_PARTS、MUTATE_PART等其他任务类型)。absolute_delay真实反映的是队列里最老的那条任务,从被创建到现在过去了多久——本文的2秒,对应的正是从第一批新数据在node1插入、到查询时的时间差。这套机制在真实生产环境里最直接的用途是排查"为什么这个副本读到的数据不对/是旧的":先查queue_size和absolute_delay判断副本是不是真的落后了,如果是,再查replication_queue看具体卡在哪个任务、卡了多久,比盲目猜测"是不是网络问题"或者"是不是数据丢了"要精确得多。本文这次的堆积是真实的,但也在几秒内被完全消化掉了——本系列下一篇会验证副本落后的时间足够长、甚至底层part被真实删除之后,恢复过程会遇到什么真实的额外情况。

分步演示:从队列堆积到真实清空追平的完整过程

每一步都是本文上面用真实system.replication_queue跑出来的原始结果。

真实的5个待执行任务,几秒内清空追平
这一步新验证的状态

    本文用到的工具

    • 本机真实的3节点集群,真实的 SYSTEM STOP/START FETCHES
    • 真实的 system.replicas(queue_size/absolute_delay)与 system.replication_queue
    京ICP备2026067502号-1京公网安备11010502063487号