ZooKeeper ZNode类型详解:四种节点及其应用场景
-
- 一、ZNode类型概述
-
- 1.1 四种类型速览
- 1.2 类型对比总表
- 二、持久节点(Persistent Node)
-
- 2.1 基本特性
- 2.2 特性总结
- 2.3 应用场景
-
- 场景1:配置中心
- 场景2:元数据存储
- 场景3:权限信息
- 三、临时节点(Ephemeral Node)
-
- 3.1 基本特性
- 3.2 核心限制
- 3.3 应用场景
-
- 场景1:服务注册与发现
- 场景2:心跳检测
- 场景3:集群成员管理
- 四、持久顺序节点(Persistent Sequential Node)
-
- 4.1 基本特性
- 4.2 序号特性
- 4.3 应用场景
-
- 场景1:分布式任务队列
- 场景2:日志事件存储
- 场景3:唯一ID生成器
- 五、临时顺序节点(Ephemeral Sequential Node)
-
- 5.1 基本特性
- 5.2 特性总结
- 5.3 应用场景
-
- 场景1:分布式锁
- 场景2:Leader选举
- 场景3:分布式屏障
- 六、节点类型选型指南
-
- 6.1 选型决策树
- 6.2 场景推荐表
- 七、总结
-
- 7.1 节点类型速查表
- 7.2 核心要点
- 7.3 选择建议
|
🌺The Begin🌺点点关注,收藏不迷路🌺 |
摘要:ZooKeeper的ZNode分为四种类型:持久节点、临时节点、持久顺序节点、临时顺序节点。每种类型都有其独特的生命周期和行为特性,适用于不同的分布式场景。本文将深入剖析这四种节点的特点、工作原理和典型应用,通过流程图和实战案例帮助读者做出正确的选型决策。
一、ZNode类型概述
1.1 四种类型速览
#mermaid-svg-U2cZ9XmnMDc7FI11{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-U2cZ9XmnMDc7FI11 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-U2cZ9XmnMDc7FI11 .error-icon{fill:#552222;}#mermaid-svg-U2cZ9XmnMDc7FI11 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-U2cZ9XmnMDc7FI11 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-U2cZ9XmnMDc7FI11 .marker.cross{stroke:#333333;}#mermaid-svg-U2cZ9XmnMDc7FI11 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-U2cZ9XmnMDc7FI11 p{margin:0;}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge{stroke-width:3;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section–1 rect,#mermaid-svg-U2cZ9XmnMDc7FI11 .section–1 path,#mermaid-svg-U2cZ9XmnMDc7FI11 .section–1 circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .section–1 polygon,#mermaid-svg-U2cZ9XmnMDc7FI11 .section–1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .section–1 text{fill:#ffffff;}#mermaid-svg-U2cZ9XmnMDc7FI11 .node-icon–1{font-size:40px;color:#ffffff;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-edge–1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-depth–1{stroke-width:17;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section–1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:lightgray;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:#efefef;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-0 rect,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-0 path,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-0 circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-0 polygon,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-0 text{fill:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .node-icon-0{font-size:40px;color:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-depth-0{stroke-width:14;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:lightgray;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:#efefef;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-1 rect,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-1 path,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-1 circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-1 polygon,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-1 text{fill:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .node-icon-1{font-size:40px;color:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-depth-1{stroke-width:11;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:lightgray;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:#efefef;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-2 rect,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-2 path,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-2 circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-2 polygon,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-2 text{fill:#ffffff;}#mermaid-svg-U2cZ9XmnMDc7FI11 .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-depth-2{stroke-width:8;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:lightgray;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:#efefef;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-3 rect,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-3 path,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-3 circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-3 polygon,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-3 text{fill:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .node-icon-3{font-size:40px;color:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-depth-3{stroke-width:5;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:lightgray;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:#efefef;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-4 rect,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-4 path,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-4 circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-4 polygon,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-4 text{fill:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .node-icon-4{font-size:40px;color:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-depth-4{stroke-width:2;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:lightgray;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:#efefef;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-5 rect,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-5 path,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-5 circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-5 polygon,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-5 text{fill:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .node-icon-5{font-size:40px;color:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-depth-5{stroke-width:-1;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:lightgray;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:#efefef;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-6 rect,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-6 path,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-6 circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-6 polygon,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-6 text{fill:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .node-icon-6{font-size:40px;color:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-depth-6{stroke-width:-4;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:lightgray;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:#efefef;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-7 rect,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-7 path,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-7 circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-7 polygon,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-7 text{fill:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .node-icon-7{font-size:40px;color:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-depth-7{stroke-width:-7;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:lightgray;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:#efefef;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-8 rect,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-8 path,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-8 circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-8 polygon,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-8 text{fill:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .node-icon-8{font-size:40px;color:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-depth-8{stroke-width:-10;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:lightgray;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:#efefef;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-9 rect,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-9 path,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-9 circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-9 polygon,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-9 text{fill:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .node-icon-9{font-size:40px;color:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-depth-9{stroke-width:-13;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:lightgray;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:#efefef;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-10 rect,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-10 path,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-10 circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-10 polygon,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-10 text{fill:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .node-icon-10{font-size:40px;color:black;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge-depth-10{stroke-width:-16;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:lightgray;}#mermaid-svg-U2cZ9XmnMDc7FI11 .disabled text{fill:#efefef;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-root rect,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-root path,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-root circle,#mermaid-svg-U2cZ9XmnMDc7FI11 .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-root text{fill:#ffffff;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-root span{color:#ffffff;}#mermaid-svg-U2cZ9XmnMDc7FI11 .section-2 span{color:#ffffff;}#mermaid-svg-U2cZ9XmnMDc7FI11 .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-U2cZ9XmnMDc7FI11 .edge{fill:none;}#mermaid-svg-U2cZ9XmnMDc7FI11 .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-U2cZ9XmnMDc7FI11 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
ZNode类型
持久节点
持久存在
需手动删除
临时节点
会话绑定
自动删除
持久顺序节点
持久+序号
任务队列
临时顺序节点
临时+序号
分布式锁
1.2 类型对比总表
| 持久节点 | create path data | 直到显式删除 | 可以 | 路径唯一 | 配置信息、元数据 |
| 临时节点 | create -e path data | 会话结束自动删除 | 不能有子节点 | 路径唯一 | 服务注册、心跳检测 |
| 持久顺序节点 | create -s path data | 持久存在,带递增序号 | 可以 | 自动序号保证唯一 | 任务队列、事件顺序 |
| 临时顺序节点 | create -e -s path data | 会话结束自动删除,带序号 | 不能有子节点 | 自动序号保证唯一 | 分布式锁、Leader选举 |
二、持久节点(Persistent Node)
2.1 基本特性
持久节点是ZooKeeper中最基本的节点类型,创建后会一直存在,直到被显式删除。
# 创建持久节点
[zk: localhost:2181(CONNECTED) 0] create /config "database-config"
Created /config
# 创建多级持久节点
[zk: localhost:2181(CONNECTED) 1] create /config/database "localhost:3306"
Created /config/database
# 退出客户端重新连接
[zk: localhost:2181(CONNECTED) 2] quit
$ ./zkCli.sh -server localhost:2181
# 节点依然存在
[zk: localhost:2181(CONNECTED) 0] ls /config
[database]
2.2 特性总结
| 生命周期 | 永久存在,直到调用delete命令 |
| 会话无关 | 创建它的客户端断开不影响节点 |
| 子节点 | 可以拥有任意多个子节点 |
| 数据持久化 | 数据会持久化到磁盘 |
2.3 应用场景
场景1:配置中心
# 创建配置根节点
create /app-config "application configuration"
# 创建各个配置项
create /app-config/database '{"host":"mysql","port":3306}'
create /app-config/redis '{"host":"redis","port":6379}'
create /app-config/threadpool '{"core":10,"max":50}'
# 所有应用共享这些配置
# 配置变更时通知所有应用
场景2:元数据存储
# 存储集群元信息
create /cluster "cluster metadata"
create /cluster/brokers "broker list"
create /cluster/topics "topic list"
# 这些元数据永久保存,不会因为某个节点重启而丢失
场景3:权限信息
# 存储用户权限信息
create /auth "authentication data"
create /auth/users "user list"
create /auth/roles "role list"
三、临时节点(Ephemeral Node)
3.1 基本特性
临时节点的生命周期绑定于客户端会话。当创建它的客户端会话结束时(主动断开或超时),节点会被自动删除。
# 终端1:创建临时节点
[zk: localhost:2181(CONNECTED) 0] create -e /temp-node "temporary"
Created /temp-node
# 查看节点状态(ephemeralOwner非0)
[zk: localhost:2181(CONNECTED) 1] stat /temp-node | grep ephemeralOwner
ephemeralOwner = 0x100001d6d2d0003
# 终端2:验证节点存在
[zk: localhost:2181(CONNECTED) 0] ls /
[temp-node, zookeeper]
# 终端1退出
[zk: localhost:2181(CONNECTED) 2] quit
# 终端2重新查看
[zk: localhost:2181(CONNECTED) 1] ls /
[zookeeper] # 临时节点已自动删除
3.2 核心限制
#mermaid-svg-4YuVAikTxNRHD9L7{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-4YuVAikTxNRHD9L7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4YuVAikTxNRHD9L7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4YuVAikTxNRHD9L7 .error-icon{fill:#552222;}#mermaid-svg-4YuVAikTxNRHD9L7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4YuVAikTxNRHD9L7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4YuVAikTxNRHD9L7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4YuVAikTxNRHD9L7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4YuVAikTxNRHD9L7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4YuVAikTxNRHD9L7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4YuVAikTxNRHD9L7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4YuVAikTxNRHD9L7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4YuVAikTxNRHD9L7 .marker.cross{stroke:#333333;}#mermaid-svg-4YuVAikTxNRHD9L7 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4YuVAikTxNRHD9L7 p{margin:0;}#mermaid-svg-4YuVAikTxNRHD9L7 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-4YuVAikTxNRHD9L7 .cluster-label text{fill:#333;}#mermaid-svg-4YuVAikTxNRHD9L7 .cluster-label span{color:#333;}#mermaid-svg-4YuVAikTxNRHD9L7 .cluster-label span p{background-color:transparent;}#mermaid-svg-4YuVAikTxNRHD9L7 .label text,#mermaid-svg-4YuVAikTxNRHD9L7 span{fill:#333;color:#333;}#mermaid-svg-4YuVAikTxNRHD9L7 .node rect,#mermaid-svg-4YuVAikTxNRHD9L7 .node circle,#mermaid-svg-4YuVAikTxNRHD9L7 .node ellipse,#mermaid-svg-4YuVAikTxNRHD9L7 .node polygon,#mermaid-svg-4YuVAikTxNRHD9L7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4YuVAikTxNRHD9L7 .rough-node .label text,#mermaid-svg-4YuVAikTxNRHD9L7 .node .label text,#mermaid-svg-4YuVAikTxNRHD9L7 .image-shape .label,#mermaid-svg-4YuVAikTxNRHD9L7 .icon-shape .label{text-anchor:middle;}#mermaid-svg-4YuVAikTxNRHD9L7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-4YuVAikTxNRHD9L7 .rough-node .label,#mermaid-svg-4YuVAikTxNRHD9L7 .node .label,#mermaid-svg-4YuVAikTxNRHD9L7 .image-shape .label,#mermaid-svg-4YuVAikTxNRHD9L7 .icon-shape .label{text-align:center;}#mermaid-svg-4YuVAikTxNRHD9L7 .node.clickable{cursor:pointer;}#mermaid-svg-4YuVAikTxNRHD9L7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-4YuVAikTxNRHD9L7 .arrowheadPath{fill:#333333;}#mermaid-svg-4YuVAikTxNRHD9L7 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-4YuVAikTxNRHD9L7 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-4YuVAikTxNRHD9L7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4YuVAikTxNRHD9L7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-4YuVAikTxNRHD9L7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4YuVAikTxNRHD9L7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-4YuVAikTxNRHD9L7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-4YuVAikTxNRHD9L7 .cluster text{fill:#333;}#mermaid-svg-4YuVAikTxNRHD9L7 .cluster span{color:#333;}#mermaid-svg-4YuVAikTxNRHD9L7 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-4YuVAikTxNRHD9L7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-4YuVAikTxNRHD9L7 rect.text{fill:none;stroke-width:0;}#mermaid-svg-4YuVAikTxNRHD9L7 .icon-shape,#mermaid-svg-4YuVAikTxNRHD9L7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4YuVAikTxNRHD9L7 .icon-shape p,#mermaid-svg-4YuVAikTxNRHD9L7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-4YuVAikTxNRHD9L7 .icon-shape rect,#mermaid-svg-4YuVAikTxNRHD9L7 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4YuVAikTxNRHD9L7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-4YuVAikTxNRHD9L7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-4YuVAikTxNRHD9L7 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
临时节点
生命周期与会话绑定
不能有子节点
ephemeralOwner记录会话ID
会话结束自动删除
网络闪断时超时后删除
设计原因避免孤儿节点
只能作为叶子节点
不能有子节点的原因:
- 如果允许有子节点,会话结束时,这些子节点的处理会变得复杂
- 避免出现"孤儿节点"(父节点已删除,子节点残留)
- 简化生命周期管理
3.3 应用场景
场景1:服务注册与发现
服务消费者
ZooKeeper
服务提供者
服务消费者
ZooKeeper
服务提供者
#mermaid-svg-WXCTf7afDbxbjgQ2{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-WXCTf7afDbxbjgQ2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WXCTf7afDbxbjgQ2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WXCTf7afDbxbjgQ2 .error-icon{fill:#552222;}#mermaid-svg-WXCTf7afDbxbjgQ2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WXCTf7afDbxbjgQ2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WXCTf7afDbxbjgQ2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WXCTf7afDbxbjgQ2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WXCTf7afDbxbjgQ2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WXCTf7afDbxbjgQ2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WXCTf7afDbxbjgQ2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WXCTf7afDbxbjgQ2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WXCTf7afDbxbjgQ2 .marker.cross{stroke:#333333;}#mermaid-svg-WXCTf7afDbxbjgQ2 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WXCTf7afDbxbjgQ2 p{margin:0;}#mermaid-svg-WXCTf7afDbxbjgQ2 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-WXCTf7afDbxbjgQ2 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-WXCTf7afDbxbjgQ2 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-WXCTf7afDbxbjgQ2 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-WXCTf7afDbxbjgQ2 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-WXCTf7afDbxbjgQ2 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-WXCTf7afDbxbjgQ2 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-WXCTf7afDbxbjgQ2 .sequenceNumber{fill:white;}#mermaid-svg-WXCTf7afDbxbjgQ2 #sequencenumber{fill:#333;}#mermaid-svg-WXCTf7afDbxbjgQ2 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-WXCTf7afDbxbjgQ2 .messageText{fill:#333;stroke:none;}#mermaid-svg-WXCTf7afDbxbjgQ2 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-WXCTf7afDbxbjgQ2 .labelText,#mermaid-svg-WXCTf7afDbxbjgQ2 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-WXCTf7afDbxbjgQ2 .loopText,#mermaid-svg-WXCTf7afDbxbjgQ2 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-WXCTf7afDbxbjgQ2 .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-WXCTf7afDbxbjgQ2 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-WXCTf7afDbxbjgQ2 .noteText,#mermaid-svg-WXCTf7afDbxbjgQ2 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-WXCTf7afDbxbjgQ2 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-WXCTf7afDbxbjgQ2 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-WXCTf7afDbxbjgQ2 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-WXCTf7afDbxbjgQ2 .actorPopupMenu{position:absolute;}#mermaid-svg-WXCTf7afDbxbjgQ2 .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-WXCTf7afDbxbjgQ2 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-WXCTf7afDbxbjgQ2 .actor-man circle,#mermaid-svg-WXCTf7afDbxbjgQ2 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-WXCTf7afDbxbjgQ2 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
/services/api/instance-001
启动时创建临时节点
获取服务列表
[instance-001, instance-002]
进程崩溃
会话超时,自动删除临时节点
重新获取服务列表
[instance-002] (instance-001已移除)
# 服务提供者注册
create -e /services/api-gateway-1 "192.168.1.10:8080"
create -e /services/api-gateway-2 "192.168.1.11:8080"
# 服务消费者发现
ls /services
[api-gateway-1, api-gateway-2]
# 监听服务变化
ls -w /services
场景2:心跳检测
public class HeartbeatDetector {
private ZooKeeper zk;
private String path = "/heartbeat/client-1";
public void start() throws Exception {
// 创建临时节点作为心跳标记
zk.create(path, "alive".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
// 启动心跳线程
startHeartbeatThread();
}
private void startHeartbeatThread() {
new Thread(() -> {
while (true) {
try {
// 定期更新数据,维持会话
zk.setData(path, "alive".getBytes(), –1);
Thread.sleep(5000);
} catch (Exception e) {
// 心跳失败
break;
}
}
}).start();
}
}
场景3:集群成员管理
# 每个集群节点注册为临时节点
create -e /cluster/nodes/node-1 "192.168.1.1:8080"
create -e /cluster/nodes/node-2 "192.168.1.2:8080"
create -e /cluster/nodes/node-3 "192.168.1.3:8080"
# 监控集群成员变化
ls -w /cluster/nodes
# 节点宕机后自动从列表移除
四、持久顺序节点(Persistent Sequential Node)
4.1 基本特性
持久顺序节点在创建时会自动在路径后添加一个10位数的递增序号,保证节点名称的唯一性。
# 创建持久顺序节点
[zk: localhost:2181(CONNECTED) 0] create -s /task/task- "task1"
Created /task/task-0000000001
[zk: localhost:2181(CONNECTED) 1] create -s /task/task- "task2"
Created /task/task-0000000002
[zk: localhost:2181(CONNECTED) 2] create -s /task/task- "task3"
Created /task/task-0000000003
# 查看所有任务
[zk: localhost:2181(CONNECTED) 3] ls /task
[task-0000000001, task-0000000002, task-0000000003]
4.2 序号特性
| 序号格式 | 10位十进制数,从1开始 |
| 递增规则 | 严格递增,不会重复 |
| 存储方式 | 序号保存在节点路径中 |
| 跨会话 | 序号在整个集群范围内递增 |
4.3 应用场景
场景1:分布式任务队列
渲染错误: Mermaid 渲染失败: Lexical error on line 3. Unrecognized text. … T1[/task-0000000001] Q –> T2[/ ———————–^
public class TaskQueue {
private ZooKeeper zk;
private String queuePath = "/tasks";
// 提交任务
public String submitTask(byte[] taskData) throws Exception {
return zk.create(queuePath + "/task-",
taskData,
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT_SEQUENTIAL);
}
// 获取并处理最早的任务
public void processTasks() throws Exception {
while (true) {
List<String> tasks = zk.getChildren(queuePath, false);
if (tasks.isEmpty()) {
Thread.sleep(1000);
continue;
}
// 按序号排序,获取最早的任务
Collections.sort(tasks);
String earliest = tasks.get(0);
// 获取任务数据
byte[] data = zk.getData(queuePath + "/" + earliest, false, null);
// 处理任务
processTask(data);
// 删除已完成的任务
zk.delete(queuePath + "/" + earliest, –1);
}
}
}
场景2:日志事件存储
# 存储按时间顺序的事件
create -s /events/event- '{"type":"login","user":"alice"}'
create -s /events/event- '{"type":"logout","user":"bob"}'
create -s /events/event- '{"type":"error","msg":"timeout"}'
# 按顺序读取事件
ls /events
[event-0000000001, event-0000000002, event-0000000003]
场景3:唯一ID生成器
# 利用顺序节点生成全局唯一ID
create -s /id-generator/id- ""
Created /id-generator/id-0000000042
# 从返回的路径中提取ID
# id-0000000042 -> 42
五、临时顺序节点(Ephemeral Sequential Node)
5.1 基本特性
临时顺序节点结合了临时节点和顺序节点的特性:会话结束时自动删除,同时带有序号。
# 创建临时顺序节点
[zk: localhost:2181(CONNECTED) 0] create -e -s /lock/lock- "client1"
Created /lock/lock-0000000001
[zk: localhost:2181(CONNECTED) 1] create -e -s /lock/lock- "client2"
Created /lock/lock-0000000002
# 查看所有等待者
[zk: localhost:2181(CONNECTED) 2] ls /lock
[lock-0000000001, lock-0000000002]
# 退出客户端1
[zk: localhost:2181(CONNECTED) 3] quit
# 重新连接查看
[zk: localhost:2181(CONNECTED) 0] ls /lock
[lock-0000000002] # client1的节点自动删除
5.2 特性总结
| 会话绑定 | 会话结束时自动删除 |
| 有序性 | 自动添加递增序号 |
| 唯一性 | 序号保证路径唯一 |
| 无子节点 | 继承临时节点限制,不能有子节点 |
5.3 应用场景
场景1:分布式锁
ZooKeeper
客户端3
客户端2
客户端1
ZooKeeper
客户端3
客户端2
客户端1
#mermaid-svg-CEZLmjEVyZxfF9Pj{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-CEZLmjEVyZxfF9Pj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CEZLmjEVyZxfF9Pj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CEZLmjEVyZxfF9Pj .error-icon{fill:#552222;}#mermaid-svg-CEZLmjEVyZxfF9Pj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CEZLmjEVyZxfF9Pj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CEZLmjEVyZxfF9Pj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CEZLmjEVyZxfF9Pj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CEZLmjEVyZxfF9Pj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CEZLmjEVyZxfF9Pj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CEZLmjEVyZxfF9Pj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CEZLmjEVyZxfF9Pj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CEZLmjEVyZxfF9Pj .marker.cross{stroke:#333333;}#mermaid-svg-CEZLmjEVyZxfF9Pj svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CEZLmjEVyZxfF9Pj p{margin:0;}#mermaid-svg-CEZLmjEVyZxfF9Pj .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-CEZLmjEVyZxfF9Pj text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-CEZLmjEVyZxfF9Pj .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-CEZLmjEVyZxfF9Pj .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-CEZLmjEVyZxfF9Pj .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-CEZLmjEVyZxfF9Pj .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-CEZLmjEVyZxfF9Pj #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-CEZLmjEVyZxfF9Pj .sequenceNumber{fill:white;}#mermaid-svg-CEZLmjEVyZxfF9Pj #sequencenumber{fill:#333;}#mermaid-svg-CEZLmjEVyZxfF9Pj #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-CEZLmjEVyZxfF9Pj .messageText{fill:#333;stroke:none;}#mermaid-svg-CEZLmjEVyZxfF9Pj .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-CEZLmjEVyZxfF9Pj .labelText,#mermaid-svg-CEZLmjEVyZxfF9Pj .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-CEZLmjEVyZxfF9Pj .loopText,#mermaid-svg-CEZLmjEVyZxfF9Pj .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-CEZLmjEVyZxfF9Pj .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-CEZLmjEVyZxfF9Pj .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-CEZLmjEVyZxfF9Pj .noteText,#mermaid-svg-CEZLmjEVyZxfF9Pj .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-CEZLmjEVyZxfF9Pj .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-CEZLmjEVyZxfF9Pj .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-CEZLmjEVyZxfF9Pj .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-CEZLmjEVyZxfF9Pj .actorPopupMenu{position:absolute;}#mermaid-svg-CEZLmjEVyZxfF9Pj .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-CEZLmjEVyZxfF9Pj .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-CEZLmjEVyZxfF9Pj .actor-man circle,#mermaid-svg-CEZLmjEVyZxfF9Pj line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-CEZLmjEVyZxfF9Pj :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
获得锁
获得锁
创建锁节点 /lock/lock-000001
创建锁节点 /lock/lock-000002
创建锁节点 /lock/lock-000003
检查序号,最小
执行业务
监听前一个节点 /lock/lock-000001
监听前一个节点 /lock/lock-000002
释放锁(删除节点)
通知锁释放
重新检查序号
public class DistributedLock {
private ZooKeeper zk;
private String lockPath = "/locks";
private String lockNode;
public boolean tryLock() throws Exception {
// 1. 创建临时顺序节点
lockNode = zk.create(lockPath + "/lock-",
new byte[0],
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
// 2. 获取所有锁节点
List<String> children = zk.getChildren(lockPath, false);
Collections.sort(children);
// 3. 检查自己是否是最小节点
String myNodeName = lockNode.substring(lockNode.lastIndexOf("/") + 1);
int myIndex = children.indexOf(myNodeName);
if (myIndex == 0) {
// 获得锁
return true;
} else {
// 监听前一个节点
String prevNode = lockPath + "/" + children.get(myIndex – 1);
CountDownLatch latch = new CountDownLatch(1);
Stat stat = zk.exists(prevNode, event -> {
if (event.getType() == Event.EventType.NodeDeleted) {
latch.countDown();
}
});
if (stat != null) {
latch.await(); // 等待前一个节点释放
}
return tryLock(); // 重新尝试获取锁
}
}
public void unlock() throws Exception {
zk.delete(lockNode, –1);
}
}
场景2:Leader选举
public class LeaderElection {
private ZooKeeper zk;
private String electionPath = "/election";
private String participantNode;
private boolean isLeader = false;
public void participate() throws Exception {
// 创建临时顺序节点参与选举
participantNode = zk.create(electionPath + "/participant-",
"host:8080".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
// 检查是否为Leader
checkLeader();
}
private void checkLeader() throws Exception {
List<String> participants = zk.getChildren(electionPath, false);
Collections.sort(participants);
String smallest = participants.get(0);
String myName = participantNode.substring(participantNode.lastIndexOf("/") + 1);
if (myName.equals(smallest)) {
isLeader = true;
System.out.println("成为Leader");
startLeaderTasks();
} else {
// 监听前一个节点
int myIndex = participants.indexOf(myName);
String prevNode = electionPath + "/" + participants.get(myIndex – 1);
zk.exists(prevNode, event -> {
if (event.getType() == Event.EventType.NodeDeleted) {
try {
checkLeader(); // 重新检查
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
private void startLeaderTasks() {
// Leader执行的任务
}
}
场景3:分布式屏障
# 创建屏障节点
create /barrier "distributed barrier"
# 多个参与者到达屏障
create -e -s /barrier/participant- "node1"
create -e -s /barrier/participant- "node2"
create -e -s /barrier/participant- "node3"
# 等待所有参与者到达(通过监听子节点数量)
# 当所有参与者都离开(会话结束或主动删除)时,屏障解除
六、节点类型选型指南
6.1 选型决策树
#mermaid-svg-5RQ60iaEVJoPUv2m{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-5RQ60iaEVJoPUv2m .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-5RQ60iaEVJoPUv2m .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-5RQ60iaEVJoPUv2m .error-icon{fill:#552222;}#mermaid-svg-5RQ60iaEVJoPUv2m .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-5RQ60iaEVJoPUv2m .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-5RQ60iaEVJoPUv2m .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-5RQ60iaEVJoPUv2m .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-5RQ60iaEVJoPUv2m .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-5RQ60iaEVJoPUv2m .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-5RQ60iaEVJoPUv2m .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-5RQ60iaEVJoPUv2m .marker{fill:#333333;stroke:#333333;}#mermaid-svg-5RQ60iaEVJoPUv2m .marker.cross{stroke:#333333;}#mermaid-svg-5RQ60iaEVJoPUv2m svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-5RQ60iaEVJoPUv2m p{margin:0;}#mermaid-svg-5RQ60iaEVJoPUv2m .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-5RQ60iaEVJoPUv2m .cluster-label text{fill:#333;}#mermaid-svg-5RQ60iaEVJoPUv2m .cluster-label span{color:#333;}#mermaid-svg-5RQ60iaEVJoPUv2m .cluster-label span p{background-color:transparent;}#mermaid-svg-5RQ60iaEVJoPUv2m .label text,#mermaid-svg-5RQ60iaEVJoPUv2m span{fill:#333;color:#333;}#mermaid-svg-5RQ60iaEVJoPUv2m .node rect,#mermaid-svg-5RQ60iaEVJoPUv2m .node circle,#mermaid-svg-5RQ60iaEVJoPUv2m .node ellipse,#mermaid-svg-5RQ60iaEVJoPUv2m .node polygon,#mermaid-svg-5RQ60iaEVJoPUv2m .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-5RQ60iaEVJoPUv2m .rough-node .label text,#mermaid-svg-5RQ60iaEVJoPUv2m .node .label text,#mermaid-svg-5RQ60iaEVJoPUv2m .image-shape .label,#mermaid-svg-5RQ60iaEVJoPUv2m .icon-shape .label{text-anchor:middle;}#mermaid-svg-5RQ60iaEVJoPUv2m .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-5RQ60iaEVJoPUv2m .rough-node .label,#mermaid-svg-5RQ60iaEVJoPUv2m .node .label,#mermaid-svg-5RQ60iaEVJoPUv2m .image-shape .label,#mermaid-svg-5RQ60iaEVJoPUv2m .icon-shape .label{text-align:center;}#mermaid-svg-5RQ60iaEVJoPUv2m .node.clickable{cursor:pointer;}#mermaid-svg-5RQ60iaEVJoPUv2m .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-5RQ60iaEVJoPUv2m .arrowheadPath{fill:#333333;}#mermaid-svg-5RQ60iaEVJoPUv2m .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-5RQ60iaEVJoPUv2m .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-5RQ60iaEVJoPUv2m .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5RQ60iaEVJoPUv2m .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-5RQ60iaEVJoPUv2m .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5RQ60iaEVJoPUv2m .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-5RQ60iaEVJoPUv2m .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-5RQ60iaEVJoPUv2m .cluster text{fill:#333;}#mermaid-svg-5RQ60iaEVJoPUv2m .cluster span{color:#333;}#mermaid-svg-5RQ60iaEVJoPUv2m 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-5RQ60iaEVJoPUv2m .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-5RQ60iaEVJoPUv2m rect.text{fill:none;stroke-width:0;}#mermaid-svg-5RQ60iaEVJoPUv2m .icon-shape,#mermaid-svg-5RQ60iaEVJoPUv2m .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5RQ60iaEVJoPUv2m .icon-shape p,#mermaid-svg-5RQ60iaEVJoPUv2m .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-5RQ60iaEVJoPUv2m .icon-shape rect,#mermaid-svg-5RQ60iaEVJoPUv2m .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5RQ60iaEVJoPUv2m .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-5RQ60iaEVJoPUv2m .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-5RQ60iaEVJoPUv2m :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
是
否
是
否
是
否
需要哪种节点?
数据需要永久保存?
需要顺序?
需要顺序?
持久顺序节点
持久节点
临时顺序节点
临时节点
6.2 场景推荐表
| 配置信息存储 | 持久节点 | 需要永久保存,不能丢失 |
| 服务实例注册 | 临时节点 | 宕机时自动注销 |
| 任务队列 | 持久顺序节点 | 需要持久保存,同时保证顺序 |
| 分布式锁 | 临时顺序节点 | 自动释放+顺序公平 |
| Leader选举 | 临时顺序节点 | 自动退出+顺序确定 |
| 心跳检测 | 临时节点 | 检测会话存活 |
| 唯一ID生成 | 持久顺序节点 | 全局唯一递增 |
| 集群成员管理 | 临时节点 | 自动感知成员变化 |
七、总结
7.1 节点类型速查表
| 持久节点 | create path data | 永久 | 无 | 配置信息、元数据 |
| 临时节点 | create -e path data | 会话结束 | 无 | 服务注册、心跳 |
| 持久顺序节点 | create -s path data | 永久 | 有 | 任务队列、ID生成 |
| 临时顺序节点 | create -e -s path data | 会话结束 | 有 | 分布式锁、选举 |
7.2 核心要点
7.3 选择建议
- 需要永久存储:选持久节点
- 需要动态感知:选临时节点
- 需要顺序保证:选顺序节点
- 需要公平锁:选临时顺序节点
- 需要任务队列:选持久顺序节点
掌握这四种节点类型的特点和适用场景,是使用ZooKeeper构建分布式应用的基础。正确的节点类型选择可以让应用逻辑更简洁,系统行为更可预测。

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





