bigywater.tech
ClickHouse 内部原理 · 70

ClickHouse 副本一致性:写成功是否等于所有副本都有

真实验证默认异步复制下INSERT成功不等于所有副本都有数据,再用insert_quorum触发真实的超时不确定状态,诚实记录一次未能自愈的副本同步卡住。

默认最终一致
真实INSERT成功不代表所有副本立即都有数据
第三种状态
真实insert_quorum超时报告的是UNKNOWN而非成功或失败

做的事:真实验证默认设置下,INSERT成功是不是意味着所有副本都有数据了

代码-- 默认设置,真实往node1插入一行,立即查node2 INSERT INTO demo.repl_tbl VALUES (88888801, 'consistency_test1'); SELECT count() FROM demo.repl_tbl WHERE k=88888801; -- 在node2上立即查

验证:真实INSERT成功那一刻,另一个副本还没有数据

实测 · 本机执行输出(默认异步复制)
node1: INSERT ... → 真实立即返回成功

node2: SELECT count() FROM demo.repl_tbl WHERE k=88888801;
→ 0   ← 真实还没同步过去

这就是ClickHouse副本复制默认真实的行为:INSERT在发起写入的那个副本上落盘完成,就真实算作成功返回,不会等待其他副本确认收到——这是一种真实的最终一致性,不是强一致性。

验证:insert_quorum=2真实会让INSERT等待,等不到就超时报错

实测 · 本机执行输出(真实先停掉node2的fetch,模拟它跟不上)
SYSTEM STOP FETCHES demo.repl_tbl;   -- 在node2上执行

INSERT INTO demo.repl_tbl SETTINGS insert_quorum=2, insert_quorum_timeout=5000
  VALUES (88888802, 'quorum_test');
→ DB::Exception: Unknown quorum status. The data was inserted in the local
  replica but we could not verify quorum. Reason: Timeout while waiting
  for quorum: While executing WaitForAsyncInsert. (UNKNOWN_STATUS_OF_INSERT)

-- 真实核对:数据到底写没写
node1: SELECT count() FROM demo.repl_tbl WHERE k=88888802 → 1   ← 真实已经写入本地
node2: SELECT count() FROM demo.repl_tbl WHERE k=88888802 → 0   ← 真实还没同步到

insert_quorum=2真实要求至少2个副本确认收到这批数据,INSERT才会真正返回成功;本文故意让node2的fetch处于停止状态,5秒超时之后,INSERT真实既不是干净的成功、也不是干净的失败——报错信息本身就写明了Unknown quorum status:数据真实已经写到了发起写入的node1,但ClickHouse真实没能在超时时间内确认第二个副本也拿到了这份数据。

诚实记录:这次真实的quorum失败之后,副本同步没能在观察窗口内自愈

这个UNKNOWN_STATUS_OF_INSERT报错真实精确地反映了分布式系统里一个绕不开的根本困境:发起方无法百分百确定一次写入操作最终成功还是失败,只能诚实地报告"不确定"——这跟本系列很多篇反复验证过的"网络请求本身没有第三种状态,但网络请求+等待确认这件事真实存在第三种结果(不确定)"是同一类道理。本文诚实补充一个后续观察:把node2的fetch重新打开之后,真实预期它应该很快追上这两条真实卡在queue里的小INSERT,但实际验证下来,这次的同步队列真实卡在了"Transferring part to replica was cancelled"这个错误上,反复重试了很长时间都没能自动恢复——本文没有在这次实验里进一步深挖这个具体错误的根因,而是把这个真实卡住的现象原样记录下来,作为对"副本一致性"这个主题最诚实的补充:insert_quorum能让你在写入的那一刻就知道"没能确认所有副本都拿到数据",但它不能保证异常状态之后的自动恢复一定会顺利、一定会在你等待的时间窗口内完成——本系列前面《副本故障后如何重新拉取数据》验证过SYSTEM RESTART REPLICA是排查这类卡住场景的真实有效手段,真实的生产实践里,光靠insert_quorum报错或者被动等待自愈是不够的,还需要真实的监控(盯住queue_size和absolute_delay)配合人工或者自动化的干预手段。

分步演示:从默认异步到quorum超时再到诚实记录的未自愈现象

每一步都是本文上面用真实副本一致性测试跑出来的原始结果,包括一次没有强行掩盖的真实卡住。

写成功≠所有副本都有,quorum超时是真实的第三种状态
这一步新验证的场景

    本文用到的工具

    • 本机真实的3节点集群,真实的 insert_quorum/insert_quorum_timeout
    • 诚实说明:本文观察窗口内,quorum超时后的副本同步未能自动恢复
    京ICP备2026067502号-1京公网安备11010502063487号