欢迎光临
我们一直在努力

ZooKeeper数据变更实时性解析:修改后其他客户端能否立即获取?

ZooKeeper数据变更实时性解析:修改后其他客户端能否立即获取?

    • 一、快速回答:不保证立即获取
    • 二、ZooKeeper的一致性模型
      • 2.1 顺序一致性
      • 2.2 单一系统映像
    • 三、影响数据可见性的因素
      • 3.1 客户端连接的节点类型
      • 3.2 同步延迟
      • 3.3 读操作的处理方式
    • 四、实验验证
      • 4.1 实验设计
      • 4.2 实验代码
      • 4.3 预期实验结果
    • 五、保证读最新数据的方案
      • 5.1 方案一:使用sync命令
      • 5.2 方案二:统一读Leader
      • 5.3 方案三:使用Watch确保新鲜度
    • 六、实际应用中的权衡
      • 6.1 一致性 vs 性能
      • 6.2 业务场景选型建议
    • 七、总结
      • 7.1 核心要点
      • 7.2 可见性时间线
      • 7.3 一句话总结

🌺The Begin🌺点点关注,收藏不迷路🌺

摘要:在分布式系统中,数据变更的可见性是一个核心问题。当ZooKeeper客户端修改了节点数据,其他客户端能否立即看到最新数据?答案并不简单。本文将深入剖析ZooKeeper的数据一致性模型,探讨影响数据可见性的各种因素,并通过实验验证不同场景下的实际表现。

一、快速回答:不保证立即获取

核心结论:ZooKeeper不保证其他客户端能够立即获取到最新数据。数据的可见性受到多种因素影响,包括客户端连接节点、是否使用Watch机制、网络延迟等。

#mermaid-svg-KhU1kPDDrZ6Uoz2i{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KhU1kPDDrZ6Uoz2i .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .error-icon{fill:#552222;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .marker.cross{stroke:#333333;}#mermaid-svg-KhU1kPDDrZ6Uoz2i svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KhU1kPDDrZ6Uoz2i p{margin:0;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .cluster-label text{fill:#333;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .cluster-label span{color:#333;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .cluster-label span p{background-color:transparent;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .label text,#mermaid-svg-KhU1kPDDrZ6Uoz2i span{fill:#333;color:#333;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .node rect,#mermaid-svg-KhU1kPDDrZ6Uoz2i .node circle,#mermaid-svg-KhU1kPDDrZ6Uoz2i .node ellipse,#mermaid-svg-KhU1kPDDrZ6Uoz2i .node polygon,#mermaid-svg-KhU1kPDDrZ6Uoz2i .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .rough-node .label text,#mermaid-svg-KhU1kPDDrZ6Uoz2i .node .label text,#mermaid-svg-KhU1kPDDrZ6Uoz2i .image-shape .label,#mermaid-svg-KhU1kPDDrZ6Uoz2i .icon-shape .label{text-anchor:middle;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .rough-node .label,#mermaid-svg-KhU1kPDDrZ6Uoz2i .node .label,#mermaid-svg-KhU1kPDDrZ6Uoz2i .image-shape .label,#mermaid-svg-KhU1kPDDrZ6Uoz2i .icon-shape .label{text-align:center;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .node.clickable{cursor:pointer;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .arrowheadPath{fill:#333333;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KhU1kPDDrZ6Uoz2i .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KhU1kPDDrZ6Uoz2i .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KhU1kPDDrZ6Uoz2i .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .cluster text{fill:#333;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .cluster span{color:#333;}#mermaid-svg-KhU1kPDDrZ6Uoz2i div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KhU1kPDDrZ6Uoz2i rect.text{fill:none;stroke-width:0;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .icon-shape,#mermaid-svg-KhU1kPDDrZ6Uoz2i .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .icon-shape p,#mermaid-svg-KhU1kPDDrZ6Uoz2i .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .icon-shape rect,#mermaid-svg-KhU1kPDDrZ6Uoz2i .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KhU1kPDDrZ6Uoz2i .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KhU1kPDDrZ6Uoz2i .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KhU1kPDDrZ6Uoz2i :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

数据变更传播路径

可能立即看到

可能延迟

可能延迟

客户端1修改数据

Leader处理

同步到Follower1

同步到Follower2

同步到Follower3

客户端2连接Follower1

客户端3连接Follower2

客户端4连接Follower3

二、ZooKeeper的一致性模型

2.1 顺序一致性

ZooKeeper提供的是顺序一致性,而不是强一致性:

一致性类型特点ZooKeeper是否支持
强一致性 所有节点同时看到最新数据 ❌ 不支持
顺序一致性 所有节点看到的操作顺序一致 ✅ 支持
最终一致性 最终所有节点数据一致 ✅ 支持

2.2 单一系统映像

ZooKeeper保证单一系统映像:客户端无论连接到哪个节点,最终看到的数据视图是一致的,但可能存在短暂的不一致窗口。

/**
* ZooKeeper的一致性保证(来自官方文档):
*
* 1. 顺序一致性:来自任何客户端的更新都会按照它们发送的顺序应用
* 2. 原子性:更新要么成功要么失败,没有部分结果
* 3. 单一系统映像:无论连接到哪个服务器,客户端都将看到相同的服务视图
* 4. 持久性:一旦更新成功,它就会持久存在并且不会被回滚
* 5. 及时性:系统的滞后窗口有限,通常小于几十秒
*/

三、影响数据可见性的因素

3.1 客户端连接的节点类型

客户端2(读取者)

Follower节点

Leader节点

客户端1(修改者)

客户端2(读取者)

Follower节点

Leader节点

客户端1(修改者)

#mermaid-svg-GxemU57e8Gb6BM2H{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GxemU57e8Gb6BM2H .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GxemU57e8Gb6BM2H .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GxemU57e8Gb6BM2H .error-icon{fill:#552222;}#mermaid-svg-GxemU57e8Gb6BM2H .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GxemU57e8Gb6BM2H .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GxemU57e8Gb6BM2H .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GxemU57e8Gb6BM2H .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GxemU57e8Gb6BM2H .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GxemU57e8Gb6BM2H .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GxemU57e8Gb6BM2H .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GxemU57e8Gb6BM2H .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GxemU57e8Gb6BM2H .marker.cross{stroke:#333333;}#mermaid-svg-GxemU57e8Gb6BM2H svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GxemU57e8Gb6BM2H p{margin:0;}#mermaid-svg-GxemU57e8Gb6BM2H .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GxemU57e8Gb6BM2H text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-GxemU57e8Gb6BM2H .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-GxemU57e8Gb6BM2H .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-GxemU57e8Gb6BM2H .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-GxemU57e8Gb6BM2H .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-GxemU57e8Gb6BM2H #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-GxemU57e8Gb6BM2H .sequenceNumber{fill:white;}#mermaid-svg-GxemU57e8Gb6BM2H #sequencenumber{fill:#333;}#mermaid-svg-GxemU57e8Gb6BM2H #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-GxemU57e8Gb6BM2H .messageText{fill:#333;stroke:none;}#mermaid-svg-GxemU57e8Gb6BM2H .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GxemU57e8Gb6BM2H .labelText,#mermaid-svg-GxemU57e8Gb6BM2H .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-GxemU57e8Gb6BM2H .loopText,#mermaid-svg-GxemU57e8Gb6BM2H .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-GxemU57e8Gb6BM2H .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-GxemU57e8Gb6BM2H .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-GxemU57e8Gb6BM2H .noteText,#mermaid-svg-GxemU57e8Gb6BM2H .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-GxemU57e8Gb6BM2H .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GxemU57e8Gb6BM2H .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GxemU57e8Gb6BM2H .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GxemU57e8Gb6BM2H .actorPopupMenu{position:absolute;}#mermaid-svg-GxemU57e8Gb6BM2H .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-GxemU57e8Gb6BM2H .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GxemU57e8Gb6BM2H .actor-man circle,#mermaid-svg-GxemU57e8Gb6BM2H line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-GxemU57e8Gb6BM2H :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

同步可能需要几毫秒到几十毫秒

如果C2连接到Leader

则可能立即看到新值

setData(/config, "new-value")

同步数据(异步)

getData(/config)

可能返回旧值"old-value"

3.2 同步延迟

数据从Leader同步到Follower需要时间,这个延迟受以下因素影响:

因素影响程度典型值
网络延迟 0.1ms ~ 100ms
服务器负载 同步队列长度
磁盘I/O 事务日志写入时间
集群规模 与节点数成正比

3.3 读操作的处理方式

ZooKeeper的读操作可以在任意节点执行,这带来了性能优势,但也导致了可能的读旧数据问题:

public class ReadConsistencyDemo {
private ZooKeeper zk;

/**
* 可能读到旧数据
*/

public byte[] readFromAnyNode(String path) throws Exception {
// 可以在Follower上执行,可能读到旧数据
return zk.getData(path, false, null);
}

/**
* 强制读最新数据(通过sync命令)
*/

public byte[] readWithSync(String path) throws Exception {
// 1. 先执行sync,确保看到最新数据
zk.sync(path, null, null);

// 2. 再读取
return zk.getData(path, false, null);
}

/**
* 读Leader确保最新
*/

public byte[] readFromLeader(String path) throws Exception {
// 直接连接Leader读取
// 但这需要知道谁是Leader,通常不现实
return null;
}
}

四、实验验证

4.1 实验设计

#mermaid-svg-qF7eeMCQsyLlWs5X{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qF7eeMCQsyLlWs5X .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qF7eeMCQsyLlWs5X .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qF7eeMCQsyLlWs5X .error-icon{fill:#552222;}#mermaid-svg-qF7eeMCQsyLlWs5X .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qF7eeMCQsyLlWs5X .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qF7eeMCQsyLlWs5X .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qF7eeMCQsyLlWs5X .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qF7eeMCQsyLlWs5X .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qF7eeMCQsyLlWs5X .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qF7eeMCQsyLlWs5X .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qF7eeMCQsyLlWs5X .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qF7eeMCQsyLlWs5X .marker.cross{stroke:#333333;}#mermaid-svg-qF7eeMCQsyLlWs5X svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qF7eeMCQsyLlWs5X p{margin:0;}#mermaid-svg-qF7eeMCQsyLlWs5X .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-qF7eeMCQsyLlWs5X .cluster-label text{fill:#333;}#mermaid-svg-qF7eeMCQsyLlWs5X .cluster-label span{color:#333;}#mermaid-svg-qF7eeMCQsyLlWs5X .cluster-label span p{background-color:transparent;}#mermaid-svg-qF7eeMCQsyLlWs5X .label text,#mermaid-svg-qF7eeMCQsyLlWs5X span{fill:#333;color:#333;}#mermaid-svg-qF7eeMCQsyLlWs5X .node rect,#mermaid-svg-qF7eeMCQsyLlWs5X .node circle,#mermaid-svg-qF7eeMCQsyLlWs5X .node ellipse,#mermaid-svg-qF7eeMCQsyLlWs5X .node polygon,#mermaid-svg-qF7eeMCQsyLlWs5X .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qF7eeMCQsyLlWs5X .rough-node .label text,#mermaid-svg-qF7eeMCQsyLlWs5X .node .label text,#mermaid-svg-qF7eeMCQsyLlWs5X .image-shape .label,#mermaid-svg-qF7eeMCQsyLlWs5X .icon-shape .label{text-anchor:middle;}#mermaid-svg-qF7eeMCQsyLlWs5X .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qF7eeMCQsyLlWs5X .rough-node .label,#mermaid-svg-qF7eeMCQsyLlWs5X .node .label,#mermaid-svg-qF7eeMCQsyLlWs5X .image-shape .label,#mermaid-svg-qF7eeMCQsyLlWs5X .icon-shape .label{text-align:center;}#mermaid-svg-qF7eeMCQsyLlWs5X .node.clickable{cursor:pointer;}#mermaid-svg-qF7eeMCQsyLlWs5X .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qF7eeMCQsyLlWs5X .arrowheadPath{fill:#333333;}#mermaid-svg-qF7eeMCQsyLlWs5X .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qF7eeMCQsyLlWs5X .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qF7eeMCQsyLlWs5X .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qF7eeMCQsyLlWs5X .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qF7eeMCQsyLlWs5X .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qF7eeMCQsyLlWs5X .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qF7eeMCQsyLlWs5X .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qF7eeMCQsyLlWs5X .cluster text{fill:#333;}#mermaid-svg-qF7eeMCQsyLlWs5X .cluster span{color:#333;}#mermaid-svg-qF7eeMCQsyLlWs5X div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qF7eeMCQsyLlWs5X .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qF7eeMCQsyLlWs5X rect.text{fill:none;stroke-width:0;}#mermaid-svg-qF7eeMCQsyLlWs5X .icon-shape,#mermaid-svg-qF7eeMCQsyLlWs5X .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qF7eeMCQsyLlWs5X .icon-shape p,#mermaid-svg-qF7eeMCQsyLlWs5X .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qF7eeMCQsyLlWs5X .icon-shape rect,#mermaid-svg-qF7eeMCQsyLlWs5X .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qF7eeMCQsyLlWs5X .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qF7eeMCQsyLlWs5X .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qF7eeMCQsyLlWs5X :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

3节点ZooKeeper集群

Leader节点

Follower1

Follower2

客户端1修改数据

客户端2连接Follower1

客户端3连接Follower2

客户端4连接Leader

4.2 实验代码

public class VisibilityExperiment {
private static final String ZK_SERVER = "localhost:2181,localhost:2182,localhost:2183";
private static final String PATH = "/test-node";

public static void main(String[] args) throws Exception {
// 创建3个客户端,分别连接到不同节点
ZooKeeper client1 = createClient("客户端1", 2181); // 连接Leader
ZooKeeper client2 = createClient("客户端2", 2182); // 连接Follower1
ZooKeeper client3 = createClient("客户端3", 2183); // 连接Follower2

// 创建测试节点
ensurePath(client1, PATH);

// 实验1:修改后立即读取
experimentImmediateRead(client1, client2, client3);

// 实验2:使用Watch监听
experimentWithWatcher(client1, client2);

// 实验3:使用Sync命令
experimentWithSync(client1, client3);
}

private static void experimentImmediateRead(ZooKeeper writer,
ZooKeeper reader1,
ZooKeeper reader2) throws Exception {
System.out.println("\\n=== 实验1:修改后立即读取 ===");

// 写入新数据
String newValue = "value-" + System.currentTimeMillis();
writer.setData(PATH, newValue.getBytes(), 1);
System.out.println("写入数据: " + newValue);

// 立即读取
String value1 = readData(reader1, "Reader1(Follower1)");
String value2 = readData(reader2, "Reader2(Follower2)");

System.out.println("结果: Reader1看到 " + value1);
System.out.println("结果: Reader2看到 " + value2);

// 等待片刻后再次读取
Thread.sleep(100);
String value1Later = readData(reader1, "Reader1(Follower1)");
System.out.println("100ms后 Reader1看到 " + value1Later);
}

private static void experimentWithWatcher(ZooKeeper writer,
ZooKeeper reader) throws Exception {
System.out.println("\\n=== 实验2:使用Watch机制 ===");

CountDownLatch watchTriggered = new CountDownLatch(1);

// 注册Watcher
reader.getData(PATH, event -> {
if (event.getType() == Watcher.Event.EventType.NodeDataChanged) {
System.out.println("收到数据变更通知");
watchTriggered.countDown();
}
}, null);

// 修改数据
String newValue = "watch-value-" + System.currentTimeMillis();
writer.setData(PATH, newValue.getBytes(), 1);
System.out.println("写入数据: " + newValue);

// 等待Watch触发
boolean triggered = watchTriggered.await(1, TimeUnit.SECONDS);
if (triggered) {
// 收到通知后读取数据
String value = readData(reader, "Reader");
System.out.println("收到通知后读取到: " + value);
} else {
System.out.println("Watch未触发");
}
}

private static void experimentWithSync(ZooKeeper writer,
ZooKeeper reader) throws Exception {
System.out.println("\\n=== 实验3:使用Sync命令 ===");

String newValue = "sync-value-" + System.currentTimeMillis();
writer.setData(PATH, newValue.getBytes(), 1);
System.out.println("写入数据: " + newValue);

// 执行sync
CountDownLatch syncLatch = new CountDownLatch(1);
reader.sync(PATH, (rc, path, ctx) -> {
syncLatch.countDown();
}, null);
syncLatch.await(1, TimeUnit.SECONDS);

// sync后读取
String value = readData(reader, "Reader after sync");
System.out.println("Sync后读取到: " + value);
}

private static ZooKeeper createClient(String name, int port) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
ZooKeeper zk = new ZooKeeper("localhost:" + port, 5000, event -> {
if (event.getState() == Watcher.Event.KeeperState.SyncConnected) {
System.out.println(name + " 连接成功");
latch.countDown();
}
});
latch.await();
return zk;
}

private static String readData(ZooKeeper zk, String readerName) throws Exception {
byte[] data = zk.getData(PATH, false, null);
String value = new String(data);
System.out.println(readerName + " 读取到: " + value);
return value;
}

private static void ensurePath(ZooKeeper zk, String path) throws Exception {
if (zk.exists(path, false) == null) {
zk.create(path, "initial".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
}
}

4.3 预期实验结果

场景是否能立即获取最新数据原因
连接Leader的客户端 ✅ 通常能 Leader拥有最新数据
连接Follower的客户端 ❌ 可能不能 同步延迟导致
使用Watch的客户端 ✅ 最终能 收到通知后主动拉取
使用Sync的客户端 ✅ 能 Sync强制同步

五、保证读最新数据的方案

5.1 方案一:使用sync命令

public class SyncReadExample {
private ZooKeeper zk;

public byte[] readWithSync(String path) throws Exception {
// 同步方式
zk.sync(path, null, null);
return zk.getData(path, false, null);
}

// 异步方式
public void readWithAsyncSync(String path) throws Exception {
zk.sync(path, (rc, path1, ctx) -> {
try {
byte[] data = zk.getData(path1, false, null);
System.out.println("Sync后读取: " + new String(data));
} catch (Exception e) {
e.printStackTrace();
}
}, null);
}
}

5.2 方案二:统一读Leader

public class LeaderReadStrategy {
private ZooKeeper zk;

public byte[] readFromLeader(String path) throws Exception {
// 通过四字命令获取Leader信息
String leader = getLeaderInfo();

// 创建临时连接读取
ZooKeeper leaderConn = new ZooKeeper(leader + ":2181", 5000, null);
try {
return leaderConn.getData(path, false, null);
} finally {
leaderConn.close();
}
}

private String getLeaderInfo() {
// 实现Leader发现逻辑
return "localhost"; // 简化示例
}
}

5.3 方案三:使用Watch确保新鲜度

public class WatcherReadStrategy {
private ZooKeeper zk;
private volatile byte[] latestData;
private final Object lock = new Object();

public void init(String path) throws Exception {
// 初始读取并注册Watcher
refreshData(path);
}

private void refreshData(String path) throws Exception {
byte[] data = zk.getData(path, event -> {
if (event.getType() == Watcher.Event.EventType.NodeDataChanged) {
try {
// 数据变更,重新读取并注册
refreshData(path);
} catch (Exception e) {
e.printStackTrace();
}
}
}, null);

synchronized (lock) {
latestData = data;
lock.notifyAll();
}
}

public byte[] getData() {
synchronized (lock) {
return latestData.clone();
}
}
}

六、实际应用中的权衡

6.1 一致性 vs 性能

方案一致性级别性能开销适用场景
直接读Follower 最终一致 配置缓存、服务发现
Sync + 读 强一致 关键配置变更
读Leader 强一致 核心元数据
Watch + 缓存 最终一致 频繁读场景

6.2 业务场景选型建议

public class ConsistencySelector {

/**
* 根据业务场景选择合适的一致性级别
*/

public ConsistencyLevel selectConsistencyLevel(String business) {
switch (business) {
case "service_discovery":
// 服务发现可以容忍短暂不一致
return ConsistencyLevel.EVENTUAL;

case "configuration_center":
// 配置变更需要尽快生效
return ConsistencyLevel.STRONG;

case "distributed_lock":
// 分布式锁必须强一致
return ConsistencyLevel.STRONG;

case "monitoring_data":
// 监控数据可以接受最终一致
return ConsistencyLevel.EVENTUAL;

default:
return ConsistencyLevel.EVENTUAL;
}
}

public enum ConsistencyLevel {
EVENTUAL, // 最终一致,读Follower
STRONG // 强一致,使用sync或读Leader
}
}

七、总结

7.1 核心要点

  • 不保证立即获取:ZooKeeper不保证其他客户端能立即看到最新数据
  • 存在短暂不一致窗口:数据从Leader同步到Follower需要时间
  • 连接节点决定可见性:连接Leader的客户端看到最新数据的概率更高
  • Watch机制提供通知:通过Watch可以感知数据变更,但需主动拉取
  • Sync命令强制同步:需要强一致读时,先执行sync再读取
  • 7.2 可见性时间线

    #mermaid-svg-OchFO7Juw0DdzQub{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-OchFO7Juw0DdzQub .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-OchFO7Juw0DdzQub .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-OchFO7Juw0DdzQub .error-icon{fill:#552222;}#mermaid-svg-OchFO7Juw0DdzQub .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-OchFO7Juw0DdzQub .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-OchFO7Juw0DdzQub .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-OchFO7Juw0DdzQub .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-OchFO7Juw0DdzQub .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-OchFO7Juw0DdzQub .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-OchFO7Juw0DdzQub .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-OchFO7Juw0DdzQub .marker{fill:#333333;stroke:#333333;}#mermaid-svg-OchFO7Juw0DdzQub .marker.cross{stroke:#333333;}#mermaid-svg-OchFO7Juw0DdzQub svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-OchFO7Juw0DdzQub p{margin:0;}#mermaid-svg-OchFO7Juw0DdzQub .edge{stroke-width:3;}#mermaid-svg-OchFO7Juw0DdzQub .section–1 rect,#mermaid-svg-OchFO7Juw0DdzQub .section–1 path,#mermaid-svg-OchFO7Juw0DdzQub .section–1 circle,#mermaid-svg-OchFO7Juw0DdzQub .section–1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .section–1 text{fill:#ffffff;}#mermaid-svg-OchFO7Juw0DdzQub .node-icon–1{font-size:40px;color:#ffffff;}#mermaid-svg-OchFO7Juw0DdzQub .section-edge–1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .edge-depth–1{stroke-width:17;}#mermaid-svg-OchFO7Juw0DdzQub .section–1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-OchFO7Juw0DdzQub .lineWrapper line{stroke:#ffffff;}#mermaid-svg-OchFO7Juw0DdzQub .disabled,#mermaid-svg-OchFO7Juw0DdzQub .disabled circle,#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:lightgray;}#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:#efefef;}#mermaid-svg-OchFO7Juw0DdzQub .section-0 rect,#mermaid-svg-OchFO7Juw0DdzQub .section-0 path,#mermaid-svg-OchFO7Juw0DdzQub .section-0 circle,#mermaid-svg-OchFO7Juw0DdzQub .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-OchFO7Juw0DdzQub .section-0 text{fill:black;}#mermaid-svg-OchFO7Juw0DdzQub .node-icon-0{font-size:40px;color:black;}#mermaid-svg-OchFO7Juw0DdzQub .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-OchFO7Juw0DdzQub .edge-depth-0{stroke-width:14;}#mermaid-svg-OchFO7Juw0DdzQub .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-OchFO7Juw0DdzQub .lineWrapper line{stroke:black;}#mermaid-svg-OchFO7Juw0DdzQub .disabled,#mermaid-svg-OchFO7Juw0DdzQub .disabled circle,#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:lightgray;}#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:#efefef;}#mermaid-svg-OchFO7Juw0DdzQub .section-1 rect,#mermaid-svg-OchFO7Juw0DdzQub .section-1 path,#mermaid-svg-OchFO7Juw0DdzQub .section-1 circle,#mermaid-svg-OchFO7Juw0DdzQub .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .section-1 text{fill:black;}#mermaid-svg-OchFO7Juw0DdzQub .node-icon-1{font-size:40px;color:black;}#mermaid-svg-OchFO7Juw0DdzQub .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .edge-depth-1{stroke-width:11;}#mermaid-svg-OchFO7Juw0DdzQub .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-OchFO7Juw0DdzQub .lineWrapper line{stroke:black;}#mermaid-svg-OchFO7Juw0DdzQub .disabled,#mermaid-svg-OchFO7Juw0DdzQub .disabled circle,#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:lightgray;}#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:#efefef;}#mermaid-svg-OchFO7Juw0DdzQub .section-2 rect,#mermaid-svg-OchFO7Juw0DdzQub .section-2 path,#mermaid-svg-OchFO7Juw0DdzQub .section-2 circle,#mermaid-svg-OchFO7Juw0DdzQub .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .section-2 text{fill:#ffffff;}#mermaid-svg-OchFO7Juw0DdzQub .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-OchFO7Juw0DdzQub .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .edge-depth-2{stroke-width:8;}#mermaid-svg-OchFO7Juw0DdzQub .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-OchFO7Juw0DdzQub .lineWrapper line{stroke:#ffffff;}#mermaid-svg-OchFO7Juw0DdzQub .disabled,#mermaid-svg-OchFO7Juw0DdzQub .disabled circle,#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:lightgray;}#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:#efefef;}#mermaid-svg-OchFO7Juw0DdzQub .section-3 rect,#mermaid-svg-OchFO7Juw0DdzQub .section-3 path,#mermaid-svg-OchFO7Juw0DdzQub .section-3 circle,#mermaid-svg-OchFO7Juw0DdzQub .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .section-3 text{fill:black;}#mermaid-svg-OchFO7Juw0DdzQub .node-icon-3{font-size:40px;color:black;}#mermaid-svg-OchFO7Juw0DdzQub .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .edge-depth-3{stroke-width:5;}#mermaid-svg-OchFO7Juw0DdzQub .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-OchFO7Juw0DdzQub .lineWrapper line{stroke:black;}#mermaid-svg-OchFO7Juw0DdzQub .disabled,#mermaid-svg-OchFO7Juw0DdzQub .disabled circle,#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:lightgray;}#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:#efefef;}#mermaid-svg-OchFO7Juw0DdzQub .section-4 rect,#mermaid-svg-OchFO7Juw0DdzQub .section-4 path,#mermaid-svg-OchFO7Juw0DdzQub .section-4 circle,#mermaid-svg-OchFO7Juw0DdzQub .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .section-4 text{fill:black;}#mermaid-svg-OchFO7Juw0DdzQub .node-icon-4{font-size:40px;color:black;}#mermaid-svg-OchFO7Juw0DdzQub .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .edge-depth-4{stroke-width:2;}#mermaid-svg-OchFO7Juw0DdzQub .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-OchFO7Juw0DdzQub .lineWrapper line{stroke:black;}#mermaid-svg-OchFO7Juw0DdzQub .disabled,#mermaid-svg-OchFO7Juw0DdzQub .disabled circle,#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:lightgray;}#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:#efefef;}#mermaid-svg-OchFO7Juw0DdzQub .section-5 rect,#mermaid-svg-OchFO7Juw0DdzQub .section-5 path,#mermaid-svg-OchFO7Juw0DdzQub .section-5 circle,#mermaid-svg-OchFO7Juw0DdzQub .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .section-5 text{fill:black;}#mermaid-svg-OchFO7Juw0DdzQub .node-icon-5{font-size:40px;color:black;}#mermaid-svg-OchFO7Juw0DdzQub .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .edge-depth-5{stroke-width:-1;}#mermaid-svg-OchFO7Juw0DdzQub .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-OchFO7Juw0DdzQub .lineWrapper line{stroke:black;}#mermaid-svg-OchFO7Juw0DdzQub .disabled,#mermaid-svg-OchFO7Juw0DdzQub .disabled circle,#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:lightgray;}#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:#efefef;}#mermaid-svg-OchFO7Juw0DdzQub .section-6 rect,#mermaid-svg-OchFO7Juw0DdzQub .section-6 path,#mermaid-svg-OchFO7Juw0DdzQub .section-6 circle,#mermaid-svg-OchFO7Juw0DdzQub .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .section-6 text{fill:black;}#mermaid-svg-OchFO7Juw0DdzQub .node-icon-6{font-size:40px;color:black;}#mermaid-svg-OchFO7Juw0DdzQub .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .edge-depth-6{stroke-width:-4;}#mermaid-svg-OchFO7Juw0DdzQub .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-OchFO7Juw0DdzQub .lineWrapper line{stroke:black;}#mermaid-svg-OchFO7Juw0DdzQub .disabled,#mermaid-svg-OchFO7Juw0DdzQub .disabled circle,#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:lightgray;}#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:#efefef;}#mermaid-svg-OchFO7Juw0DdzQub .section-7 rect,#mermaid-svg-OchFO7Juw0DdzQub .section-7 path,#mermaid-svg-OchFO7Juw0DdzQub .section-7 circle,#mermaid-svg-OchFO7Juw0DdzQub .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .section-7 text{fill:black;}#mermaid-svg-OchFO7Juw0DdzQub .node-icon-7{font-size:40px;color:black;}#mermaid-svg-OchFO7Juw0DdzQub .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .edge-depth-7{stroke-width:-7;}#mermaid-svg-OchFO7Juw0DdzQub .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-OchFO7Juw0DdzQub .lineWrapper line{stroke:black;}#mermaid-svg-OchFO7Juw0DdzQub .disabled,#mermaid-svg-OchFO7Juw0DdzQub .disabled circle,#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:lightgray;}#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:#efefef;}#mermaid-svg-OchFO7Juw0DdzQub .section-8 rect,#mermaid-svg-OchFO7Juw0DdzQub .section-8 path,#mermaid-svg-OchFO7Juw0DdzQub .section-8 circle,#mermaid-svg-OchFO7Juw0DdzQub .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .section-8 text{fill:black;}#mermaid-svg-OchFO7Juw0DdzQub .node-icon-8{font-size:40px;color:black;}#mermaid-svg-OchFO7Juw0DdzQub .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .edge-depth-8{stroke-width:-10;}#mermaid-svg-OchFO7Juw0DdzQub .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-OchFO7Juw0DdzQub .lineWrapper line{stroke:black;}#mermaid-svg-OchFO7Juw0DdzQub .disabled,#mermaid-svg-OchFO7Juw0DdzQub .disabled circle,#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:lightgray;}#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:#efefef;}#mermaid-svg-OchFO7Juw0DdzQub .section-9 rect,#mermaid-svg-OchFO7Juw0DdzQub .section-9 path,#mermaid-svg-OchFO7Juw0DdzQub .section-9 circle,#mermaid-svg-OchFO7Juw0DdzQub .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .section-9 text{fill:black;}#mermaid-svg-OchFO7Juw0DdzQub .node-icon-9{font-size:40px;color:black;}#mermaid-svg-OchFO7Juw0DdzQub .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .edge-depth-9{stroke-width:-13;}#mermaid-svg-OchFO7Juw0DdzQub .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-OchFO7Juw0DdzQub .lineWrapper line{stroke:black;}#mermaid-svg-OchFO7Juw0DdzQub .disabled,#mermaid-svg-OchFO7Juw0DdzQub .disabled circle,#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:lightgray;}#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:#efefef;}#mermaid-svg-OchFO7Juw0DdzQub .section-10 rect,#mermaid-svg-OchFO7Juw0DdzQub .section-10 path,#mermaid-svg-OchFO7Juw0DdzQub .section-10 circle,#mermaid-svg-OchFO7Juw0DdzQub .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .section-10 text{fill:black;}#mermaid-svg-OchFO7Juw0DdzQub .node-icon-10{font-size:40px;color:black;}#mermaid-svg-OchFO7Juw0DdzQub .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .edge-depth-10{stroke-width:-16;}#mermaid-svg-OchFO7Juw0DdzQub .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-OchFO7Juw0DdzQub .lineWrapper line{stroke:black;}#mermaid-svg-OchFO7Juw0DdzQub .disabled,#mermaid-svg-OchFO7Juw0DdzQub .disabled circle,#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:lightgray;}#mermaid-svg-OchFO7Juw0DdzQub .disabled text{fill:#efefef;}#mermaid-svg-OchFO7Juw0DdzQub .section-root rect,#mermaid-svg-OchFO7Juw0DdzQub .section-root path,#mermaid-svg-OchFO7Juw0DdzQub .section-root circle{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-OchFO7Juw0DdzQub .section-root text{fill:#ffffff;}#mermaid-svg-OchFO7Juw0DdzQub .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-OchFO7Juw0DdzQub .edge{fill:none;}#mermaid-svg-OchFO7Juw0DdzQub .eventWrapper{filter:brightness(120%);}#mermaid-svg-OchFO7Juw0DdzQub :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    阶段1

    T0

    客户端1提交修改

    T0

    Leader处理完成

    阶段2

    T0+1ms

    同步到部分Follower

    T0+5ms

    同步到所有Follower

    阶段3

    T0+2ms

    连接已同步Follower的客户端可见

    T0+10ms

    所有客户端最终可见

    数据变更到可见的过程

    7.3 一句话总结

    ZooKeeper的数据变更不是立即对所有客户端可见,存在短暂的最终一致性窗口。需要强一致读时,应使用sync命令或通过Watch机制主动拉取最新数据,而不能假设修改后其他客户端立即就能看到。

    在这里插入图片描述

    🌺The End🌺点点关注,收藏不迷路🌺

    赞(0)
    未经允许不得转载:171主机测评 » ZooKeeper数据变更实时性解析:修改后其他客户端能否立即获取?
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址