欢迎光临
我们一直在努力

ZooKeeper 选举核心解密:投票五元组的含义与作用

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;
}

规则总结:

  • 逻辑时钟小的选举结果被忽略,重新投票
  • 统一逻辑时钟后,ZXID 大的胜出
  • ZXID 相同的情况下,提议的 Leader ID 大的胜出
  • 五、完整选举流程图解

    #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) 投(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🌺点点关注,收藏不迷路🌺

    赞(0)
    未经允许不得转载:171主机测评 » ZooKeeper 选举核心解密:投票五元组的含义与作用
    分享到: 更多 (0)

    评论 抢沙发

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