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节点集群选举
| Server1 | 1 | 0 | Follower |
| Server2 | 2 | 0 | Leader |
| Server3 | 3 | 0 | Follower(后启动) |
选举过程:
5.2 5节点集群选举(数据不一致场景)
| Server1 | 1 | 9 | Follower |
| Server2 | 2 | 9 | Follower |
| Server3 | 3 | 9 | Leader |
| Server4 | 4 | 8 | Follower |
| Server5 | 5 | 8 | Follower |
选举过程:
六、故障恢复与数据同步
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 核心要点回顾
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🌺点点关注,收藏不迷路🌺 |




