ZooKeeper 选举核心解密:投票五元组的含义与作用
-
- 一、选举机制概述
-
- 1.1 为什么需要选举?
- 1.2 选举中的核心概念
- 二、投票五元组的完整内容
-
- 2.1 为什么需要五元组?
- 三、五元组各元素深度解析
-
- 3.1 投票服务器的 ID(myid)
- 3.2 提议的新领导者的 ID(proposedLeader)
- 3.3 选举周期(electionEpoch / 逻辑时钟)
- 3.4 数据日志 epoch(peerEpoch)
- 3.5 事务 ID(ZXID)
- 四、投票比较规则
- 五、完整选举流程图解
-
- 选举过程示例
- 六、源码中的五元组实现
- 七、总结
-
- 7.1 五元组核心要点
- 7.2 一句话总结
|
🌺The Begin🌺点点关注,收藏不迷路🌺 |
摘要:在 ZooKeeper 的 Leader 选举过程中,节点之间通过交换投票信息来达成共识。这些投票信息并非简单的"我选谁",而是一个包含五个关键元素的复杂数据结构——五元组。深入理解这五个元素的含义和作用,是掌握 ZooKeeper 选举机制的关键。本文将详细剖析投票五元组的每个成员,解释它们在选举中的具体作用,并通过流程图和源码分析帮助读者全面理解这一核心概念。
一、选举机制概述
1.1 为什么需要选举?
在 ZooKeeper 集群中,Leader 节点负责处理所有写请求和事务协调。当集群启动或 Leader 故障时,需要在剩余的节点中选出一个新的 Leader,以确保集群能继续提供服务。
#mermaid-svg-24mSkthSvyV4ezjH{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-24mSkthSvyV4ezjH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-24mSkthSvyV4ezjH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-24mSkthSvyV4ezjH .error-icon{fill:#552222;}#mermaid-svg-24mSkthSvyV4ezjH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-24mSkthSvyV4ezjH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-24mSkthSvyV4ezjH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-24mSkthSvyV4ezjH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-24mSkthSvyV4ezjH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-24mSkthSvyV4ezjH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-24mSkthSvyV4ezjH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-24mSkthSvyV4ezjH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-24mSkthSvyV4ezjH .marker.cross{stroke:#333333;}#mermaid-svg-24mSkthSvyV4ezjH svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-24mSkthSvyV4ezjH p{margin:0;}#mermaid-svg-24mSkthSvyV4ezjH .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-24mSkthSvyV4ezjH .cluster-label text{fill:#333;}#mermaid-svg-24mSkthSvyV4ezjH .cluster-label span{color:#333;}#mermaid-svg-24mSkthSvyV4ezjH .cluster-label span p{background-color:transparent;}#mermaid-svg-24mSkthSvyV4ezjH .label text,#mermaid-svg-24mSkthSvyV4ezjH span{fill:#333;color:#333;}#mermaid-svg-24mSkthSvyV4ezjH .node rect,#mermaid-svg-24mSkthSvyV4ezjH .node circle,#mermaid-svg-24mSkthSvyV4ezjH .node ellipse,#mermaid-svg-24mSkthSvyV4ezjH .node polygon,#mermaid-svg-24mSkthSvyV4ezjH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-24mSkthSvyV4ezjH .rough-node .label text,#mermaid-svg-24mSkthSvyV4ezjH .node .label text,#mermaid-svg-24mSkthSvyV4ezjH .image-shape .label,#mermaid-svg-24mSkthSvyV4ezjH .icon-shape .label{text-anchor:middle;}#mermaid-svg-24mSkthSvyV4ezjH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-24mSkthSvyV4ezjH .rough-node .label,#mermaid-svg-24mSkthSvyV4ezjH .node .label,#mermaid-svg-24mSkthSvyV4ezjH .image-shape .label,#mermaid-svg-24mSkthSvyV4ezjH .icon-shape .label{text-align:center;}#mermaid-svg-24mSkthSvyV4ezjH .node.clickable{cursor:pointer;}#mermaid-svg-24mSkthSvyV4ezjH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-24mSkthSvyV4ezjH .arrowheadPath{fill:#333333;}#mermaid-svg-24mSkthSvyV4ezjH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-24mSkthSvyV4ezjH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-24mSkthSvyV4ezjH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-24mSkthSvyV4ezjH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-24mSkthSvyV4ezjH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-24mSkthSvyV4ezjH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-24mSkthSvyV4ezjH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-24mSkthSvyV4ezjH .cluster text{fill:#333;}#mermaid-svg-24mSkthSvyV4ezjH .cluster span{color:#333;}#mermaid-svg-24mSkthSvyV4ezjH 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-24mSkthSvyV4ezjH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-24mSkthSvyV4ezjH rect.text{fill:none;stroke-width:0;}#mermaid-svg-24mSkthSvyV4ezjH .icon-shape,#mermaid-svg-24mSkthSvyV4ezjH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-24mSkthSvyV4ezjH .icon-shape p,#mermaid-svg-24mSkthSvyV4ezjH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-24mSkthSvyV4ezjH .icon-shape rect,#mermaid-svg-24mSkthSvyV4ezjH .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-24mSkthSvyV4ezjH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-24mSkthSvyV4ezjH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-24mSkthSvyV4ezjH :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
是
否
Leader 故障
剩余节点进入 LOOKING 状态
发起投票
交换投票信息
统计得票
达到过半?
选出新 Leader
1.2 选举中的核心概念
| LOOKING | 竞选状态,表示节点正在寻找 Leader |
| FOLLOWING | 跟随者状态,同步 Leader 状态,参与投票 |
| LEADING | 领导者状态 |
| OBSERVING | 观察者状态,不参与投票 |
| 过半机制 | 获得超过半数节点的投票才能当选 |
二、投票五元组的完整内容
在 ZooKeeper 的 FastLeaderElection 选举算法中,每个投票信息是一个五元组,包含以下五个关键元素:
| 投票服务器的 ID | 发出投票的节点自身的唯一标识 |
| 提议的新领导者的 ID | 被提议作为新 Leader 的候选节点 ID |
| 新领导者的选举周期 | 用于区分不同投票阶段的周期号(逻辑时钟) |
| 新领导者的数据日志 epoch | 数据日志的时间纪元,处理数据一致性 |
| 新领导者的 ZXID | 事务 ID,表示数据的新旧程度 |
#mermaid-svg-jlTdtdH5IIsX8Lcr{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-jlTdtdH5IIsX8Lcr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jlTdtdH5IIsX8Lcr .error-icon{fill:#552222;}#mermaid-svg-jlTdtdH5IIsX8Lcr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jlTdtdH5IIsX8Lcr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jlTdtdH5IIsX8Lcr .marker.cross{stroke:#333333;}#mermaid-svg-jlTdtdH5IIsX8Lcr svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jlTdtdH5IIsX8Lcr p{margin:0;}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge{stroke-width:3;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section–1 rect,#mermaid-svg-jlTdtdH5IIsX8Lcr .section–1 path,#mermaid-svg-jlTdtdH5IIsX8Lcr .section–1 circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .section–1 polygon,#mermaid-svg-jlTdtdH5IIsX8Lcr .section–1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .section–1 text{fill:#ffffff;}#mermaid-svg-jlTdtdH5IIsX8Lcr .node-icon–1{font-size:40px;color:#ffffff;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-edge–1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-depth–1{stroke-width:17;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section–1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:lightgray;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:#efefef;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-0 rect,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-0 path,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-0 circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-0 polygon,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-0 text{fill:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .node-icon-0{font-size:40px;color:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-depth-0{stroke-width:14;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:lightgray;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:#efefef;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-1 rect,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-1 path,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-1 circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-1 polygon,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-1 text{fill:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .node-icon-1{font-size:40px;color:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-depth-1{stroke-width:11;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:lightgray;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:#efefef;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-2 rect,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-2 path,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-2 circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-2 polygon,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-2 text{fill:#ffffff;}#mermaid-svg-jlTdtdH5IIsX8Lcr .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-depth-2{stroke-width:8;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:lightgray;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:#efefef;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-3 rect,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-3 path,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-3 circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-3 polygon,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-3 text{fill:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .node-icon-3{font-size:40px;color:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-depth-3{stroke-width:5;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:lightgray;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:#efefef;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-4 rect,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-4 path,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-4 circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-4 polygon,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-4 text{fill:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .node-icon-4{font-size:40px;color:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-depth-4{stroke-width:2;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:lightgray;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:#efefef;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-5 rect,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-5 path,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-5 circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-5 polygon,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-5 text{fill:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .node-icon-5{font-size:40px;color:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-depth-5{stroke-width:-1;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:lightgray;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:#efefef;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-6 rect,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-6 path,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-6 circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-6 polygon,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-6 text{fill:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .node-icon-6{font-size:40px;color:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-depth-6{stroke-width:-4;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:lightgray;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:#efefef;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-7 rect,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-7 path,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-7 circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-7 polygon,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-7 text{fill:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .node-icon-7{font-size:40px;color:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-depth-7{stroke-width:-7;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:lightgray;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:#efefef;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-8 rect,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-8 path,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-8 circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-8 polygon,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-8 text{fill:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .node-icon-8{font-size:40px;color:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-depth-8{stroke-width:-10;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:lightgray;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:#efefef;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-9 rect,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-9 path,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-9 circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-9 polygon,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-9 text{fill:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .node-icon-9{font-size:40px;color:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-depth-9{stroke-width:-13;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:lightgray;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:#efefef;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-10 rect,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-10 path,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-10 circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-10 polygon,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-10 text{fill:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .node-icon-10{font-size:40px;color:black;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge-depth-10{stroke-width:-16;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:lightgray;}#mermaid-svg-jlTdtdH5IIsX8Lcr .disabled text{fill:#efefef;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-root rect,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-root path,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-root circle,#mermaid-svg-jlTdtdH5IIsX8Lcr .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-root text{fill:#ffffff;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-root span{color:#ffffff;}#mermaid-svg-jlTdtdH5IIsX8Lcr .section-2 span{color:#ffffff;}#mermaid-svg-jlTdtdH5IIsX8Lcr .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-jlTdtdH5IIsX8Lcr .edge{fill:none;}#mermaid-svg-jlTdtdH5IIsX8Lcr .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-jlTdtdH5IIsX8Lcr :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
投票五元组
投票服务器ID
谁发出的投票
提议的领导者ID
推荐谁当Leader
选举周期
逻辑时钟
区分不同选举轮次
数据日志epoch
领导者任期
处理一致性
ZXID
事务ID
数据最新程度
2.1 为什么需要五元组?
这五个元素共同作用,确保选举过程的正确性和高效性:
- 服务器ID:唯一标识节点身份
- 提议的领导者ID:明确支持对象
- 选举周期:防止旧投票干扰新一轮选举
- 数据日志epoch:确保数据一致性
- ZXID:确保数据最新的节点优先当选
三、五元组各元素深度解析
3.1 投票服务器的 ID(myid)
这是发出投票的节点自身的唯一标识,在 myid 文件中配置。
# /var/lib/zookeeper/myid
1 # 节点1的ID
作用:让其他节点知道投票来源,用于统计得票。
3.2 提议的新领导者的 ID(proposedLeader)
这是被推荐的 Leader 候选节点 ID。节点在选举过程中可能会根据规则变更自己的投票。
// 投票信息中的提议领导者ID
public class Vote {
private int proposedLeader; // 推荐的Leader ID
private long proposedZxid; // 推荐的ZXID
// …
}
3.3 选举周期(electionEpoch / 逻辑时钟)
选举周期,也称为逻辑时钟,用于区分不同的选举轮次。
关键特性:
- 每发起新一轮选举,逻辑时钟自增1
- 同一轮选举中,所有节点的逻辑时钟相同
- 逻辑时钟小的选举结果被忽略
// 选举中的比较逻辑
if (otherVote.electionEpoch > currentEpoch) {
// 对方处于更新的选举轮次,更新自己的投票
updateProposal(otherVote);
} else if (otherVote.electionEpoch < currentEpoch) {
// 对方处于旧的选举轮次,忽略该投票
return;
}
3.4 数据日志 epoch(peerEpoch)
数据日志的 epoch,是 ZXID 的高32位部分,代表 Leader 的任期编号。
作用:
- 标识不同 Leader 任期的事务
- 处理跨 Leader 的数据一致性
- 新 Leader 产生后 epoch 自增1
// ZXID 结构
// 高32位:epoch(纪元)- 标识 Leader 任期
// 低32位:counter(计数器)- 事务序号
long zxid = (epoch << 32) | counter;
3.5 事务 ID(ZXID)
ZXID(ZooKeeper Transaction ID)是 64 位的全局唯一递增数字,表示节点的数据新旧程度。
选举规则:
- ZXID 越大,数据越新,优先当选
- ZXID 相同时,比较 myid,myid 大的优先
四、投票比较规则
在 FastLeaderElection 算法中,节点收到其他节点的投票后,会按照以下规则决定是否更新自己的投票:
public boolean isOtherVoteBetter(Vote myVote, Vote otherVote) {
// 规则1:比较逻辑时钟(选举周期)
if (otherVote.electionEpoch > myVote.electionEpoch) {
return true; // 对方处于更新的选举轮次
}
if (otherVote.electionEpoch < myVote.electionEpoch) {
return false; // 自己的选举轮次更新
}
// 规则2:比较 ZXID(数据新旧)
if (otherVote.zxid > myVote.zxid) {
return true; // 对方数据更新
}
if (otherVote.zxid < myVote.zxid) {
return false; // 自己数据更新
}
// 规则3:比较提议的 Leader ID
return otherVote.proposedLeader > myVote.proposedLeader;
}
规则总结:
五、完整选举流程图解
#mermaid-svg-Dml4KF3S9aioqEzM{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-Dml4KF3S9aioqEzM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Dml4KF3S9aioqEzM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Dml4KF3S9aioqEzM .error-icon{fill:#552222;}#mermaid-svg-Dml4KF3S9aioqEzM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Dml4KF3S9aioqEzM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Dml4KF3S9aioqEzM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Dml4KF3S9aioqEzM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Dml4KF3S9aioqEzM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Dml4KF3S9aioqEzM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Dml4KF3S9aioqEzM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Dml4KF3S9aioqEzM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Dml4KF3S9aioqEzM .marker.cross{stroke:#333333;}#mermaid-svg-Dml4KF3S9aioqEzM svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Dml4KF3S9aioqEzM p{margin:0;}#mermaid-svg-Dml4KF3S9aioqEzM .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Dml4KF3S9aioqEzM .cluster-label text{fill:#333;}#mermaid-svg-Dml4KF3S9aioqEzM .cluster-label span{color:#333;}#mermaid-svg-Dml4KF3S9aioqEzM .cluster-label span p{background-color:transparent;}#mermaid-svg-Dml4KF3S9aioqEzM .label text,#mermaid-svg-Dml4KF3S9aioqEzM span{fill:#333;color:#333;}#mermaid-svg-Dml4KF3S9aioqEzM .node rect,#mermaid-svg-Dml4KF3S9aioqEzM .node circle,#mermaid-svg-Dml4KF3S9aioqEzM .node ellipse,#mermaid-svg-Dml4KF3S9aioqEzM .node polygon,#mermaid-svg-Dml4KF3S9aioqEzM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Dml4KF3S9aioqEzM .rough-node .label text,#mermaid-svg-Dml4KF3S9aioqEzM .node .label text,#mermaid-svg-Dml4KF3S9aioqEzM .image-shape .label,#mermaid-svg-Dml4KF3S9aioqEzM .icon-shape .label{text-anchor:middle;}#mermaid-svg-Dml4KF3S9aioqEzM .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Dml4KF3S9aioqEzM .rough-node .label,#mermaid-svg-Dml4KF3S9aioqEzM .node .label,#mermaid-svg-Dml4KF3S9aioqEzM .image-shape .label,#mermaid-svg-Dml4KF3S9aioqEzM .icon-shape .label{text-align:center;}#mermaid-svg-Dml4KF3S9aioqEzM .node.clickable{cursor:pointer;}#mermaid-svg-Dml4KF3S9aioqEzM .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Dml4KF3S9aioqEzM .arrowheadPath{fill:#333333;}#mermaid-svg-Dml4KF3S9aioqEzM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Dml4KF3S9aioqEzM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Dml4KF3S9aioqEzM .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Dml4KF3S9aioqEzM .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Dml4KF3S9aioqEzM .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Dml4KF3S9aioqEzM .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Dml4KF3S9aioqEzM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Dml4KF3S9aioqEzM .cluster text{fill:#333;}#mermaid-svg-Dml4KF3S9aioqEzM .cluster span{color:#333;}#mermaid-svg-Dml4KF3S9aioqEzM 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-Dml4KF3S9aioqEzM .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Dml4KF3S9aioqEzM rect.text{fill:none;stroke-width:0;}#mermaid-svg-Dml4KF3S9aioqEzM .icon-shape,#mermaid-svg-Dml4KF3S9aioqEzM .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Dml4KF3S9aioqEzM .icon-shape p,#mermaid-svg-Dml4KF3S9aioqEzM .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Dml4KF3S9aioqEzM .icon-shape rect,#mermaid-svg-Dml4KF3S9aioqEzM .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Dml4KF3S9aioqEzM .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Dml4KF3S9aioqEzM .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Dml4KF3S9aioqEzM :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
是
否
是
否
是
否
否
是
是
否
节点进入 LOOKING 状态
初始化投票:投票给自己
广播投票:五元组信息
接收其他节点投票
比较五元组
对方选举周期更大?
更新自己的投票周期
对方ZXID更大?
更新投票为对方
对方提议ID更大?
保持自己的投票
统计得票
达到过半?
选举完成
自己是Leader?
成为 LEADING
成为 FOLLOWING
选举过程示例
假设一个5节点集群,SID分别为1-5,其中节点1、2故障。剩余节点的ZXID状态为:3号(9)、4号(8)、5号(8)。
| 初次投票 | 投(3,9) | 投(4,8) | 投(5,8) |
| 交换投票 | 保持(3,9) | 收到(3,9)后因9>8,改投(3,9) | 收到(3,9)后改投(3,9) |
| 统计 | 3票 | – | – |
| 结果 | 成为 Leader | 成为 Follower | 成为 Follower |
六、源码中的五元组实现
在 ZooKeeper 源码中,投票信息由 Vote 类和 Notification 类表示:
// org.apache.zookeeper.server.quorum.Vote
public class Vote {
private final int proposedLeader; // 提议的领导者ID
private final long proposedZxid; // 提议的ZXID
private final long proposedEpoch; // 提议的数据日志epoch
// 构造函数
public Vote(int proposedLeader, long proposedZxid, long proposedEpoch) {
this.proposedLeader = proposedLeader;
this.proposedZxid = proposedZxid;
this.proposedEpoch = proposedEpoch;
}
// getters…
}
// org.apache.zookeeper.server.quorum.Notification
public class Notification {
public final int version; // 协议版本
public final long leader; // 提议的Leader
public final long zxid; // ZXID
public final long electionEpoch; // 选举周期(逻辑时钟)
public final long peerEpoch; // 数据日志epoch
public final int state; // 节点状态(LOOKING/LEADING/FOLLOWING)
public final long sid; // 投票节点自己的ID
public Notification(long leader, long zxid, long electionEpoch,
long peerEpoch, int state, long sid) {
this.leader = leader;
this.zxid = zxid;
this.electionEpoch = electionEpoch;
this.peerEpoch = peerEpoch;
this.state = state;
this.sid = sid;
}
}
七、总结
7.1 五元组核心要点
| 投票服务器ID | 发出投票的节点 | 统计票源 | – |
| 提议的领导者ID | 推荐的Leader | 明确支持对象 | 3 |
| 选举周期 | 逻辑时钟 | 区分选举轮次 | 1(最高) |
| 数据日志epoch | Leader任期 | 保证一致性 | 2(与ZXID结合) |
| ZXID | 事务ID | 衡量数据新旧 | 2 |
7.2 一句话总结
ZooKeeper 选举中的投票五元组是一个精心设计的复合数据结构,通过 选举周期隔离不同轮次的投票,通过 ZXID 和 epoch 保证数据最新的节点优先当选,通过 提议的领导者 ID 明确支持对象,五个元素协同工作,确保选举过程的正确性、高效性和数据一致性。

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






