欢迎光临
我们一直在努力

ZooKeeper Leader选举机制详解:从理论到实践

ZooKeeper Leader选举机制详解:从理论到实践

    • 一、Leader选举概述
      • 1.1 什么是Leader选举?
      • 1.2 服务器角色与状态
      • 1.3 选举的核心依据:ZXID和myid
    • 二、选举触发场景
      • 2.1 场景一:服务器初始化启动
      • 2.2 场景二:运行期间Leader故障
    • 三、Leader选举完整流程
      • 3.1 选举的五个核心步骤
      • 3.2 步骤详解
        • 步骤1:发起投票
        • 步骤2:接收投票
        • 步骤3:处理投票(核心规则)
        • 步骤4:统计投票
        • 步骤5:改变服务器状态
      • 3.3 过半机制的重要性
    • 四、选举算法:FastLeaderElection
      • 4.1 算法概述
      • 4.2 选举过程中的通信机制
      • 4.3 逻辑时钟(electionEpoch)
    • 五、不同节点数量的选举示例
      • 5.1 3节点集群选举
      • 5.2 5节点集群选举(数据不一致场景)
    • 六、故障恢复与数据同步
      • 6.1 选举后的数据同步
      • 6.2 四种同步策略
    • 七、常见问题解答
      • 7.1 为什么需要奇数台服务器?
      • 7.2 为什么ZXID更大的节点优先当选?
      • 7.3 Observer为什么不能参与选举?
      • 7.4 选举期间集群可用吗?
    • 八、总结
      • 8.1 核心要点回顾
      • 8.2 选举流程图解
      • 8.3 一句话总结

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

摘要:Leader选举是ZooKeeper保证分布式数据一致性的核心机制。当集群启动或Leader节点故障时,ZooKeeper通过一套基于投票的选举算法,从众多节点中选出一个Leader,负责处理所有写请求和事务协调。本文将深入剖析Leader选举的完整流程、核心规则、算法原理以及实际应用场景。

一、Leader选举概述

1.1 什么是Leader选举?

Leader选举是ZooKeeper中保证分布式数据一致性的关键所在。在ZooKeeper集群中,所有写请求必须经过Leader处理,Leader将事务以Proposal形式广播给所有Follower,当收到过半Follower的确认(ACK)后,才提交该事务。当集群启动或Leader节点故障时,需要从剩余节点中选举出新的Leader。

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

Leader选举触发条件

ZooKeeper集群

集群初始化启动

运行期间Leader故障

Leader与集群失联

1.2 服务器角色与状态

在Leader选举过程中,服务器可能处于以下几种状态:

状态说明角色
LOOKING 寻找Leader状态,认为集群中没有Leader,需要进入选举流程 候选者
LEADING 领导者状态,表明当前服务器是Leader Leader
FOLLOWING 跟随者状态,表明当前服务器是Follower Follower
OBSERVING 观察者状态,表明当前服务器是Observer(不参与选举) Observer

1.3 选举的核心依据:ZXID和myid

Leader选举的投票信息包含两个核心字段:(myid, ZXID)。

字段全称说明作用
myid Server ID 服务器的唯一标识,在myid文件中配置 当ZXID相同时,myid大的优先
ZXID ZooKeeper Transaction ID 事务ID,64位数字(高32位epoch+低32位计数器) ZXID大的服务器数据更新,优先当选

二、选举触发场景

2.1 场景一:服务器初始化启动

当ZooKeeper集群首次启动时,需要进行Leader选举。选举至少需要两台机器才能进行。以3台机器组成的集群为例:

Server3 (myid=3)

Server2 (myid=2)

Server1 (myid=1)

Server3 (myid=3)

Server2 (myid=2)

Server1 (myid=1)

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

启动,状态LOOKING

只有自己,无法选举

比较ZXID(0=0),myid(1<2)

更新投票为(2,0)

比较ZXID(0=0),myid(2>1)

保持投票(2,0)

统计投票,都收到(2,0)两票

成为Leader,状态变LEADING

成为Follower,状态变FOLLOWING

启动,状态LOOKING

相互通信,开始选举

投票给自己(1,0)

投票给自己(2,0)

发送投票(1,0)

发送投票(2,0)

启动,发现已有Leader

直接成为Follower

2.2 场景二:运行期间Leader故障

当Leader服务器出现网络中断、崩溃退出或重启等异常情况时,ZAB协议会进入恢复模式,重新选举Leader。

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

Leader故障

剩余节点状态变更为LOOKING

开始Leader选举

比较ZXID和myid

选出数据最新的节点

新Leader产生

集群恢复服务

关键点:运行期间各节点的ZXID可能不同,因为有的节点可能已经处理了更多事务。选举时优先选择ZXID最大的节点,以确保数据恢复最大化。

三、Leader选举完整流程

3.1 选举的五个核心步骤

无论是启动期还是运行期的选举,都遵循以下五个步骤:

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

发起投票

接收投票

处理投票

统计投票

改变服务器状态

3.2 步骤详解

步骤1:发起投票

每个Server都会将自己作为Leader服务器来进行投票,投票信息为(myid, ZXID)。在初始启动时,所有节点的ZXID都是0。

步骤2:接收投票

集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票、是否来自LOOKING状态的服务器。

步骤3:处理投票(核心规则)

针对每一个投票,服务器都需要将别人的投票和自己的投票进行PK,规则如下:

// 投票PK规则伪代码
public Vote compareVotes(Vote myVote, Vote otherVote) {
// 规则一:优先比较ZXID
if (otherVote.zxid > myVote.zxid) {
return otherVote; // 认可对方的投票
} else if (otherVote.zxid < myVote.zxid) {
return myVote; // 坚持自己的投票
} else {
// 规则二:ZXID相等时比较myid
if (otherVote.myid > myVote.myid) {
return otherVote; // 认可对方的投票
} else {
return myVote; // 坚持自己的投票
}
}
}

规则总结:

  • 优先检查ZXID:ZXID比较大的服务器优先作为Leader
  • ZXID相同:比较myid,myid较大的服务器作为Leader
步骤4:统计投票

每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息。当收到超过半数的相同投票时,就认为已经选出Leader。

步骤5:改变服务器状态

一旦确定了Leader,每个服务器就会更新自己的状态:

  • 被选为Leader的服务器:状态变更为LEADING
  • 其他服务器:状态变更为FOLLOWING

3.3 过半机制的重要性

过半机制是ZooKeeper选举的核心原则之一:

  • 选举需要获得超过半数的投票
  • 3节点集群需要2票,5节点集群需要3票
  • 过半机制保证了集群中最多只有一个Leader

四、选举算法:FastLeaderElection

4.1 算法概述

从3.4.0版本开始,ZooKeeper只保留了FastLeaderElection选举算法。这是一种优化过的算法,通过TCP进行网络通信。

4.2 选举过程中的通信机制

FastLeaderElection通过QuorumCnxManager管理底层网络通信:

组件作用
recvQueue 消息接收队列,存放从其他服务器接收到的消息
queueSendMap 消息发送队列,按SID分组保存待发送消息
senderWorkerMap 发送器集合,为每个远程服务器分配发送器
lastMessageSent 最近发送过的消息

连接建立规则:为了避免两台机器之间重复创建TCP连接,ZooKeeper只允许SID大的服务器主动和其他机器建立连接。

4.3 逻辑时钟(electionEpoch)

在选举过程中,每个服务器维护一个逻辑时钟(electionEpoch):

  • 用于判断多个投票是否在同一轮选举周期中
  • 每次进入新一轮投票,该值自增1
  • 确保不会混淆不同轮次的投票

五、不同节点数量的选举示例

5.1 3节点集群选举

服务器myid初始ZXID最终结果
Server1 1 0 Follower
Server2 2 0 Leader
Server3 3 0 Follower(后启动)

选举过程:

  • Server1启动,自投票(1,0),未过半
  • Server2启动,自投票(2,0)
  • Server1和Server2交换投票,Server2的myid大,Server1更新投票为(2,0)
  • 统计:两票(2,0),过半(2/3),Server2成为Leader
  • Server3启动,发现已有Leader,直接成为Follower
  • 5.2 5节点集群选举(数据不一致场景)

    服务器myidZXID结果
    Server1 1 9 Follower
    Server2 2 9 Follower
    Server3 3 9 Leader
    Server4 4 8 Follower
    Server5 5 8 Follower

    选举过程:

  • 所有节点状态变LOOKING
  • 比较ZXID:Server1、2、3的ZXID=9最大,Server4、5的ZXID=8较小
  • ZXID=9的节点中,比较myid:Server3的myid最大
  • 最终Server3获得多数票(至少来自Server1、2、3三票)
  • 六、故障恢复与数据同步

    6.1 选举后的数据同步

    Leader选举完成后,需要进行数据同步以确保集群一致性:

    新Leader

    Follower

    新Leader

    Follower

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

    收到过半ACK

    发送FOLLOWERINFO(lastZxid)

    计算同步策略

    发送同步指令

    ACK确认

    UPTODATE

    6.2 四种同步策略

    策略触发条件操作
    DIFF Follower落后少量事务 增量发送缺失事务
    TRUNC Follower有多余事务 回滚多余事务
    SNAP Follower落后太多 全量发送快照

    七、常见问题解答

    7.1 为什么需要奇数台服务器?

    过半机制要求存活节点数超过半数。奇数台服务器在相同容错能力下资源利用率更高:

    • 3台集群:容忍1台故障,需要2台存活
    • 4台集群:同样容忍1台故障,需要3台存活

    7.2 为什么ZXID更大的节点优先当选?

    ZXID更大的节点意味着它拥有更新的数据,优先当选可以最大程度地恢复数据,减少数据丢失。

    7.3 Observer为什么不能参与选举?

    Observer没有投票权,不参与过半机制。它的作用是:

    • 线性扩展读能力
    • 不影响写性能
    • 可用于异地机房数据同步

    7.4 选举期间集群可用吗?

    在Leader选举过程中,集群无法正常对外提供服务,会暂停处理事务性请求。这是为了保证数据一致性而做出的权衡。

    八、总结

    8.1 核心要点回顾

  • 触发条件:集群启动或Leader故障时触发选举
  • 选举依据:优先比较ZXID,ZXID大的当选;ZXID相同比较myid,myid大的当选
  • 投票规则:每台服务器初始投票给自己,收到更好的投票后更新
  • 过半机制:获得超过半数的投票才能成为Leader
  • 最终一致性:选举完成后进行数据同步,确保所有节点数据一致
  • 8.2 选举流程图解

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

    对方更好

    自己更好

    未过半

    已过半

    进入LOOKING状态

    发起投票

    接收其他投票

    比较ZXID/myid

    更新投票

    保持投票

    重新广播

    统计投票

    选举完成

    成为LEADING

    成为FOLLOWING

    8.3 一句话总结

    ZooKeeper的Leader选举通过基于ZXID和myid的投票PK规则,结合过半机制,在集群启动或Leader故障时快速选出数据最新的节点作为新Leader,并通过数据同步确保所有节点最终一致,是ZooKeeper保证数据一致性的核心机制。

    在这里插入图片描述

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

    赞(0)
    未经允许不得转载:171主机测评 » ZooKeeper Leader选举机制详解:从理论到实践
    分享到: 更多 (0)

    评论 抢沙发

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