欢迎光临
我们一直在努力

Apache Curator 分布式协调模式全解析:七大利器助你构建健壮分布式系统

Apache Curator 分布式协调模式全解析:七大利器助你构建健壮分布式系统

    • 一、Apache Curator 与分布式协调模式概述
      • 1.1 什么是分布式协调模式?
      • 1.2 Curator 的 Recipes 模块
    • 二、分布式锁:保证资源互斥访问
      • 2.1 可重入共享锁(InterProcessMutex)
        • 使用示例
      • 2.2 共享可重入读写锁(InterProcessReadWriteLock)
      • 2.3 共享信号量(InterProcessSemaphore)
    • 三、领导选举:协调分布式任务
      • 3.1 LeaderSelector vs LeaderLatch
      • 3.2 LeaderSelector 使用示例
    • 四、分布式计数器:原子性的数字操作
      • 4.1 DistributedAtomicLong / DistributedAtomicInteger
    • 五、分布式缓存:本地监听与数据同步
      • 5.1 三种缓存模式对比
      • 5.2 NodeCache 示例
      • 5.3 PathChildrenCache 示例
      • 5.4 TreeCache 示例
    • 六、分布式队列:任务的有序管理
      • 6.1 队列类型对比
      • 6.2 DistributedQueue 使用示例
    • 七、分布式屏障:节点同步利器
      • 7.1 单屏障(DistributedBarrier)
      • 7.2 双屏障(DistributedDoubleBarrier)
    • 八、总结与选择指南
      • 8.1 七种协调模式核心要点
      • 8.2 如何选择合适的模式?
      • 8.3 最佳实践总结

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

摘要:在分布式系统的开发中,协调服务是不可或缺的基石。Apache Curator 作为 ZooKeeper 的高级客户端库,不仅简化了 ZooKeeper 的使用,更提供了一系列开箱即用的分布式协调模式(Recipes)。本文将深入剖析 Curator 的七种核心协调模式,包括分布式锁、领导选举、分布式计数器、分布式队列、缓存机制、分布式屏障等,通过流程图和实战代码帮助读者全面掌握这些强大的分布式工具。

一、Apache Curator 与分布式协调模式概述

1.1 什么是分布式协调模式?

分布式协调模式是指在分布式系统中解决特定协调问题的通用解决方案,如多个进程互斥访问资源、选举主节点、任务队列管理等。ZooKeeper 凭借其强一致性和 Watcher 机制,为实现这些模式提供了理想的基础 。

1.2 Curator 的 Recipes 模块

Apache Curator 将 ZooKeeper 官方文档中列出的分布式协调模式(除了两阶段提交)全部实现为开箱即用的工具,即 Recipes 模块 。这些工具封装了 ZooKeeper 复杂的底层操作,提供简洁的 API,让开发者能够专注于业务逻辑。

#mermaid-svg-Iz9XHGPBEXUGepbK{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-Iz9XHGPBEXUGepbK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Iz9XHGPBEXUGepbK .error-icon{fill:#552222;}#mermaid-svg-Iz9XHGPBEXUGepbK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Iz9XHGPBEXUGepbK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Iz9XHGPBEXUGepbK .marker.cross{stroke:#333333;}#mermaid-svg-Iz9XHGPBEXUGepbK svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Iz9XHGPBEXUGepbK p{margin:0;}#mermaid-svg-Iz9XHGPBEXUGepbK .edge{stroke-width:3;}#mermaid-svg-Iz9XHGPBEXUGepbK .section–1 rect,#mermaid-svg-Iz9XHGPBEXUGepbK .section–1 path,#mermaid-svg-Iz9XHGPBEXUGepbK .section–1 circle,#mermaid-svg-Iz9XHGPBEXUGepbK .section–1 polygon,#mermaid-svg-Iz9XHGPBEXUGepbK .section–1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .section–1 text{fill:#ffffff;}#mermaid-svg-Iz9XHGPBEXUGepbK .node-icon–1{font-size:40px;color:#ffffff;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-edge–1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-depth–1{stroke-width:17;}#mermaid-svg-Iz9XHGPBEXUGepbK .section–1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled circle,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:lightgray;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:#efefef;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-0 rect,#mermaid-svg-Iz9XHGPBEXUGepbK .section-0 path,#mermaid-svg-Iz9XHGPBEXUGepbK .section-0 circle,#mermaid-svg-Iz9XHGPBEXUGepbK .section-0 polygon,#mermaid-svg-Iz9XHGPBEXUGepbK .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-Iz9XHGPBEXUGepbK .section-0 text{fill:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .node-icon-0{font-size:40px;color:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-depth-0{stroke-width:14;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled circle,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:lightgray;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:#efefef;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-1 rect,#mermaid-svg-Iz9XHGPBEXUGepbK .section-1 path,#mermaid-svg-Iz9XHGPBEXUGepbK .section-1 circle,#mermaid-svg-Iz9XHGPBEXUGepbK .section-1 polygon,#mermaid-svg-Iz9XHGPBEXUGepbK .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .section-1 text{fill:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .node-icon-1{font-size:40px;color:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-depth-1{stroke-width:11;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled circle,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:lightgray;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:#efefef;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-2 rect,#mermaid-svg-Iz9XHGPBEXUGepbK .section-2 path,#mermaid-svg-Iz9XHGPBEXUGepbK .section-2 circle,#mermaid-svg-Iz9XHGPBEXUGepbK .section-2 polygon,#mermaid-svg-Iz9XHGPBEXUGepbK .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .section-2 text{fill:#ffffff;}#mermaid-svg-Iz9XHGPBEXUGepbK .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-depth-2{stroke-width:8;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled circle,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:lightgray;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:#efefef;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-3 rect,#mermaid-svg-Iz9XHGPBEXUGepbK .section-3 path,#mermaid-svg-Iz9XHGPBEXUGepbK .section-3 circle,#mermaid-svg-Iz9XHGPBEXUGepbK .section-3 polygon,#mermaid-svg-Iz9XHGPBEXUGepbK .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .section-3 text{fill:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .node-icon-3{font-size:40px;color:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-depth-3{stroke-width:5;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled circle,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:lightgray;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:#efefef;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-4 rect,#mermaid-svg-Iz9XHGPBEXUGepbK .section-4 path,#mermaid-svg-Iz9XHGPBEXUGepbK .section-4 circle,#mermaid-svg-Iz9XHGPBEXUGepbK .section-4 polygon,#mermaid-svg-Iz9XHGPBEXUGepbK .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .section-4 text{fill:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .node-icon-4{font-size:40px;color:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-depth-4{stroke-width:2;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled circle,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:lightgray;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:#efefef;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-5 rect,#mermaid-svg-Iz9XHGPBEXUGepbK .section-5 path,#mermaid-svg-Iz9XHGPBEXUGepbK .section-5 circle,#mermaid-svg-Iz9XHGPBEXUGepbK .section-5 polygon,#mermaid-svg-Iz9XHGPBEXUGepbK .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .section-5 text{fill:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .node-icon-5{font-size:40px;color:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-depth-5{stroke-width:-1;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled circle,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:lightgray;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:#efefef;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-6 rect,#mermaid-svg-Iz9XHGPBEXUGepbK .section-6 path,#mermaid-svg-Iz9XHGPBEXUGepbK .section-6 circle,#mermaid-svg-Iz9XHGPBEXUGepbK .section-6 polygon,#mermaid-svg-Iz9XHGPBEXUGepbK .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .section-6 text{fill:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .node-icon-6{font-size:40px;color:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-depth-6{stroke-width:-4;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled circle,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:lightgray;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:#efefef;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-7 rect,#mermaid-svg-Iz9XHGPBEXUGepbK .section-7 path,#mermaid-svg-Iz9XHGPBEXUGepbK .section-7 circle,#mermaid-svg-Iz9XHGPBEXUGepbK .section-7 polygon,#mermaid-svg-Iz9XHGPBEXUGepbK .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .section-7 text{fill:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .node-icon-7{font-size:40px;color:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-depth-7{stroke-width:-7;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled circle,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:lightgray;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:#efefef;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-8 rect,#mermaid-svg-Iz9XHGPBEXUGepbK .section-8 path,#mermaid-svg-Iz9XHGPBEXUGepbK .section-8 circle,#mermaid-svg-Iz9XHGPBEXUGepbK .section-8 polygon,#mermaid-svg-Iz9XHGPBEXUGepbK .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .section-8 text{fill:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .node-icon-8{font-size:40px;color:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-depth-8{stroke-width:-10;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled circle,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:lightgray;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:#efefef;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-9 rect,#mermaid-svg-Iz9XHGPBEXUGepbK .section-9 path,#mermaid-svg-Iz9XHGPBEXUGepbK .section-9 circle,#mermaid-svg-Iz9XHGPBEXUGepbK .section-9 polygon,#mermaid-svg-Iz9XHGPBEXUGepbK .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .section-9 text{fill:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .node-icon-9{font-size:40px;color:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-depth-9{stroke-width:-13;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled circle,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:lightgray;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:#efefef;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-10 rect,#mermaid-svg-Iz9XHGPBEXUGepbK .section-10 path,#mermaid-svg-Iz9XHGPBEXUGepbK .section-10 circle,#mermaid-svg-Iz9XHGPBEXUGepbK .section-10 polygon,#mermaid-svg-Iz9XHGPBEXUGepbK .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .section-10 text{fill:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .node-icon-10{font-size:40px;color:black;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .edge-depth-10{stroke-width:-16;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled circle,#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:lightgray;}#mermaid-svg-Iz9XHGPBEXUGepbK .disabled text{fill:#efefef;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-root rect,#mermaid-svg-Iz9XHGPBEXUGepbK .section-root path,#mermaid-svg-Iz9XHGPBEXUGepbK .section-root circle,#mermaid-svg-Iz9XHGPBEXUGepbK .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-Iz9XHGPBEXUGepbK .section-root text{fill:#ffffff;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-root span{color:#ffffff;}#mermaid-svg-Iz9XHGPBEXUGepbK .section-2 span{color:#ffffff;}#mermaid-svg-Iz9XHGPBEXUGepbK .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-Iz9XHGPBEXUGepbK .edge{fill:none;}#mermaid-svg-Iz9XHGPBEXUGepbK .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-Iz9XHGPBEXUGepbK :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

Curator Recipes

分布式锁

InterProcessMutex

InterProcessReadWriteLock

InterProcessSemaphore

领导选举

LeaderSelector

LeaderLatch

分布式计数器

DistributedAtomicLong

DistributedAtomicInteger

缓存

NodeCache

PathChildrenCache

TreeCache

分布式队列

DistributedQueue

DistributedPriorityQueue

分布式屏障

DistributedBarrier

DistributedDoubleBarrier

二、分布式锁:保证资源互斥访问

分布式锁是分布式系统中应用最广泛的协调模式之一,用于防止多个进程同时执行临界区代码 。

2.1 可重入共享锁(InterProcessMutex)

InterProcessMutex 是一个完全分布式的、全局同步的可重入锁,在任何时间点,不会有多个客户端认为自己持有同一把锁 。

ZooKeeper

客户端2

客户端1

ZooKeeper

客户端2

客户端1

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

尝试获取锁

创建临时顺序节点

尝试获取锁

创建临时顺序节点

检查是否为最小节点

是,获得锁

监听前一个节点

执行业务逻辑

释放锁(删除节点)

前一个节点被删除

重新检查锁状态

获得锁

使用示例

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import java.util.concurrent.TimeUnit;

public class DistributedLockExample {
private CuratorFramework client;
private InterProcessMutex lock;
private String lockPath = "/locks/mylock";

public DistributedLockExample(CuratorFramework client) {
this.client = client;
// 创建可重入分布式锁
this.lock = new InterProcessMutex(client, lockPath);
}

public void doWithLock() {
try {
// 尝试获取锁,最多等待10秒
if (lock.acquire(10, TimeUnit.SECONDS)) {
try {
System.out.println("获得锁,执行临界区代码");
// 执行需要互斥的操作
Thread.sleep(5000);
} finally {
lock.release(); // 释放锁
System.out.println("释放锁");
}
} else {
System.out.println("获取锁超时");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

注意事项 :

  • InterProcessMutex 实例是可重用的,不需要每次都创建新实例
  • 建议添加 ConnectionStateListener 监听 SUSPENDED 和 LOST 状态
  • 如果收到 LOST 状态,可以确定不再持有锁

2.2 共享可重入读写锁(InterProcessReadWriteLock)

读写锁维护一对锁:读锁和写锁。读锁可以被多个进程同时持有(只要没有写锁),写锁是独占的 。这对于读多写少的场景特别有用。

import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;

public class ReadWriteLockExample {
private InterProcessReadWriteLock lock;
private String lockPath = "/locks/rwlock";

public ReadWriteLockExample(CuratorFramework client) {
this.lock = new InterProcessReadWriteLock(client, lockPath);
}

public void doRead() throws Exception {
// 获取读锁
lock.readLock().acquire();
try {
System.out.println("获取读锁,执行读操作");
// 读取共享资源
} finally {
lock.readLock().release();
}
}

public void doWrite() throws Exception {
// 获取写锁
lock.writeLock().acquire();
try {
System.out.println("获取写锁,执行写操作");
// 修改共享资源
} finally {
lock.writeLock().release();
}
}
}

2.3 共享信号量(InterProcessSemaphore)

信号量是一种限制资源并发访问数的机制。Curator 提供的 InterProcessSemaphore 可以在多个 JVM 之间协调租约 。

import org.apache.curator.framework.recipes.locks.InterProcessSemaphoreV2;
import org.apache.curator.framework.recipes.locks.Lease;

public class SemaphoreExample {
private InterProcessSemaphoreV2 semaphore;
private String semaphorePath = "/semaphore/mysemaphore";

public SemaphoreExample(CuratorFramework client) {
// 设置最大租约数为 5
this.semaphore = new InterProcessSemaphoreV2(client, semaphorePath, 5);
}

public void useResource() throws Exception {
Lease lease = null;
try {
// 获取一个租约
lease = semaphore.acquire();
System.out.println("获得资源使用许可");
// 使用资源
Thread.sleep(3000);
} finally {
if (lease != null) {
semaphore.returnLease(lease); // 归还租约
}
}
}
}

三、领导选举:协调分布式任务

领导选举是指从多个节点中选出一个唯一的"领导者"节点,负责执行全局性的管理任务 。

3.1 LeaderSelector vs LeaderLatch

Curator 提供了两种领导选举实现 :

实现特点适用场景
LeaderLatch 一旦成为领导者,就一直维持领导直到发生异常或显式关闭 长期领导任务
LeaderSelector 领导者可以自愿放弃领导角色,支持领导权切换 需要轮流领导的场景

3.2 LeaderSelector 使用示例

ZooKeeper

节点3

节点2

节点1

ZooKeeper

节点3

节点2

节点1

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

takeLeadership() 被调用

开始执行领导任务

启动,参与选举

启动,参与选举

启动,参与选举

成为领导者

执行领导任务

领导权释放(退出takeLeadership)

成为新领导者

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.leader.LeaderSelector;
import org.apache.curator.framework.recipes.leader.LeaderSelectorListenerAdapter;

public class LeaderElectionExample {
private CuratorFramework client;
private LeaderSelector leaderSelector;
private String leaderPath = "/leader";

public LeaderElectionExample(CuratorFramework client) {
this.client = client;

// 创建 LeaderSelector
this.leaderSelector = new LeaderSelector(client, leaderPath,
new LeaderSelectorListenerAdapter() {
@Override
public void takeLeadership(CuratorFramework client) throws Exception {
// 成为领导者时执行的方法
System.out.println("成为领导者,开始执行领导任务");

// 执行领导任务(此方法返回时领导权会释放)
performLeaderTasks();

System.out.println("领导任务完成,释放领导权");
}
});

// 设置为领导权释放后自动重新加入竞选
leaderSelector.autoRequeue();
}

public void start() {
leaderSelector.start(); // 开始参与选举
}

private void performLeaderTasks() throws Exception {
// 模拟领导任务,比如定期清理、资源分配等
for (int i = 0; i < 10; i++) {
System.out.println("领导任务执行中: " + i);
Thread.sleep(1000);
}
}

public void close() {
leaderSelector.close();
}
}

错误处理 :LeaderSelectorListener 必须关注连接状态变化。如果收到 SUSPENDED 或 LOST 状态,应抛出 CancelLeadershipException,让 LeaderSelector 尝试中断执行领导任务的线程。使用 LeaderSelectorListenerAdapter 可以简化这一处理。

四、分布式计数器:原子性的数字操作

分布式计数器用于在分布式环境中对数字进行原子性的增减操作 。

4.1 DistributedAtomicLong / DistributedAtomicInteger

Curator 提供了两种分布式计数器 :

类名数据类型特点
DistributedAtomicLong long 支持原子增减,使用乐观锁,失败时回退到互斥锁
DistributedAtomicInteger int 同上,使用 int 类型

import org.apache.curator.framework.recipes.atomic.AtomicValue;
import org.apache.curator.framework.recipes.atomic.DistributedAtomicLong;
import org.apache.curator.retry.ExponentialBackoffRetry;

public class DistributedCounterExample {
private DistributedAtomicLong counter;
private String counterPath = "/counter";

public DistributedCounterExample(CuratorFramework client) {
// 创建分布式计数器,指定重试策略
this.counter = new DistributedAtomicLong(
client,
counterPath,
new ExponentialBackoffRetry(1000, 3)
);
}

public void increment() throws Exception {
AtomicValue<Long> result = counter.increment();
if (result.succeeded()) {
System.out.println("计数器增加成功,新值: " + result.postValue());
} else {
System.out.println("操作失败,当前值: " + result.preValue());
}
}

public void add(long delta) throws Exception {
AtomicValue<Long> result = counter.add(delta);
if (result.succeeded()) {
System.out.println("增加 " + delta + " 成功,新值: " + result.postValue());
}
}

public void set(long newValue) throws Exception {
AtomicValue<Long> result = counter.forceSet(newValue);
System.out.println("设置计数器为: " + newValue);
}

public long get() throws Exception {
AtomicValue<Long> result = counter.get();
return result.succeeded() ? result.postValue() : 1;
}
}

工作原理 :

  • 首先尝试使用乐观锁进行原子更新
  • 如果乐观锁失败(数据被其他客户端修改),则使用 InterProcessMutex 进行加锁后更新
  • 支持自定义重试策略

五、分布式缓存:本地监听与数据同步

缓存机制让客户端能够在本地维护 ZooKeeper 节点数据的副本,并实时监听变化,避免了频繁的远程调用 。

5.1 三种缓存模式对比

缓存类型监听范围用途
NodeCache 单个节点 监听单个节点的数据变化
PathChildrenCache 节点的子节点 监听子节点列表变化和子节点数据变化
TreeCache 整个子树 综合 NodeCache 和 PathChildrenCache 功能,监听所有变化

渲染错误: Mermaid 渲染失败: Lexical error on line 3. Unrecognized text. … 数据树" Root[/] –> App[/app] ———————-^

5.2 NodeCache 示例

import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.NodeCache;

public class NodeCacheExample {
private CuratorFramework client;
private NodeCache nodeCache;
private String path = "/config/database";

public NodeCacheExample(CuratorFramework client) throws Exception {
this.client = client;

// 创建 NodeCache
this.nodeCache = new NodeCache(client, path);

// 添加监听器
nodeCache.getListenable().addListener(() -> {
ChildData currentData = nodeCache.getCurrentData();
if (currentData != null) {
System.out.println("节点数据已更新: " +
new String(currentData.getData()));
} else {
System.out.println("节点已被删除");
}
});

// 启动缓存,设置为 true 表示启动时同步获取数据
nodeCache.start(true);
}

public void close() {
nodeCache.close();
}
}

5.3 PathChildrenCache 示例

import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;

public class PathChildrenCacheExample {
private CuratorFramework client;
private PathChildrenCache cache;
private String path = "/services";

public PathChildrenCacheExample(CuratorFramework client) throws Exception {
this.client = client;

// 创建 PathChildrenCache,第三个参数表示是否缓存数据
this.cache = new PathChildrenCache(client, path, true);

// 添加监听器
cache.getListenable().addListener((curator, event) -> {
switch (event.getType()) {
case CHILD_ADDED:
System.out.println("子节点添加: " + event.getData().getPath());
break;
case CHILD_UPDATED:
System.out.println("子节点更新: " + event.getData().getPath());
break;
case CHILD_REMOVED:
System.out.println("子节点删除: " + event.getData().getPath());
break;
case CONNECTION_LOST:
System.out.println("连接断开");
break;
case CONNECTION_RECONNECTED:
System.out.println("连接重连");
break;
}
});

// 启动缓存
cache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);
}

public void close() {
cache.close();
}
}

5.4 TreeCache 示例

import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;

public class TreeCacheExample {
private CuratorFramework client;
private TreeCache treeCache;
private String path = "/app";

public TreeCacheExample(CuratorFramework client) throws Exception {
this.client = client;

// 创建 TreeCache,监听整个子树
this.treeCache = TreeCache.newBuilder(client, path).build();

// 添加监听器
treeCache.getListenable().addListener((curator, event) -> {
TreeCacheEvent.Type type = event.getType();
String eventPath = event.getData() != null ?
event.getData().getPath() : "null";

System.out.println("事件类型: " + type + ", 路径: " + eventPath);

if (event.getData() != null && event.getData().getData() != null) {
System.out.println("数据: " + new String(event.getData().getData()));
}
});

// 启动缓存
treeCache.start();
}

public void close() {
treeCache.close();
}
}

六、分布式队列:任务的有序管理

Curator 提供了多种分布式队列实现,用于管理多个节点之间的任务或数据排序 。

6.1 队列类型对比

队列类型特点适用场景
DistributedQueue 标准 FIFO 队列 普通任务队列
DistributedPriorityQueue 支持优先级排序 需要优先级的任务
DistributedDelayQueue 延迟队列 定时任务
DistributedIdQueue 支持根据 ID 移除任务 需要取消任务

6.2 DistributedQueue 使用示例

重要提示:官方文档建议,不要使用 ZooKeeper 实现队列,如需队列功能应使用更专业的消息中间件 。但如果简单场景需要,可以参考以下实现。

import org.apache.curator.framework.recipes.queue.*;
import java.io.Closeable;
import java.io.IOException;

public class DistributedQueueExample {
private CuratorFramework client;
private DistributedQueue<String> queue;
private String queuePath = "/taskqueue";

public DistributedQueueExample(CuratorFramework client) throws Exception {
this.client = client;

// 创建队列序列化器
QueueSerializer<String> serializer = new QueueSerializer<String>() {
@Override
public byte[] serialize(String item) {
return item.getBytes();
}

@Override
public String deserialize(byte[] bytes) {
return new String(bytes);
}
};

// 创建消费者
QueueConsumer<String> consumer = new QueueConsumer<String>() {
@Override
public void consumeMessage(String message) throws Exception {
System.out.println("消费消息: " + message);
}

@Override
public void stateChanged(CuratorFramework client, ConnectionState newState) {
System.out.println("连接状态变化: " + newState);
}
};

// 构建队列
this.queue = QueueBuilder.builder(client, consumer, serializer, queuePath)
.maxItems(100) // 最大队列长度
.buildQueue();

queue.start(); // 启动队列
}

public void produce(String message) throws Exception {
queue.put(message);
System.out.println("生产消息: " + message);
}

public void close() throws IOException {
queue.close();
}
}

七、分布式屏障:节点同步利器

分布式屏障用于阻塞一组节点的处理,直到满足某个条件,所有节点才能继续执行 。

7.1 单屏障(DistributedBarrier)

import org.apache.curator.framework.recipes.barriers.DistributedBarrier;

public class DistributedBarrierExample {
private DistributedBarrier barrier;
private String barrierPath = "/barrier";

public DistributedBarrierExample(CuratorFramework client) {
this.barrier = new DistributedBarrier(client, barrierPath);
}

public void waitOnBarrier() throws Exception {
System.out.println("等待屏障释放…");
barrier.waitOnBarrier(); // 阻塞直到屏障被移除
System.out.println("屏障释放,继续执行");
}

public void setBarrier() throws Exception {
barrier.setBarrier(); // 设置屏障
System.out.println("屏障已设置");
}

public void removeBarrier() throws Exception {
barrier.removeBarrier(); // 移除屏障
System.out.println("屏障已移除");
}
}

7.2 双屏障(DistributedDoubleBarrier)

双屏障允许一组节点同步计算的开始和结束 。

ZooKeeper

节点3

节点2

节点1

ZooKeeper

节点3

节点2

节点1

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

等待所有节点进入

等待所有节点完成

进入屏障

进入屏障

进入屏障

屏障开放,开始执行

屏障开放,开始执行

屏障开放,开始执行

执行计算

执行计算

执行计算

完成,等待其他节点

完成,等待其他节点

完成,等待其他节点

所有节点完成,退出

所有节点完成,退出

所有节点完成,退出

import org.apache.curator.framework.recipes.barriers.DistributedDoubleBarrier;

public class DistributedDoubleBarrierExample {
private DistributedDoubleBarrier doubleBarrier;
private String barrierPath = "/doublebarrier";

public DistributedDoubleBarrierExample(CuratorFramework client, int memberQty) {
// memberQty: 参与屏障的节点总数
this.doubleBarrier = new DistributedDoubleBarrier(client, barrierPath, memberQty);
}

public void execute() throws Exception {
System.out.println("进入屏障,等待其他节点…");
doubleBarrier.enter(); // 等待所有节点进入

System.out.println("所有节点已进入,开始执行计算");
// 执行并行计算
Thread.sleep(3000);

System.out.println("计算完成,等待其他节点…");
doubleBarrier.leave(); // 等待所有节点完成

System.out.println("所有节点已完成,退出");
}
}

八、总结与选择指南

8.1 七种协调模式核心要点

模式核心类主要用途
分布式锁 InterProcessMutex 资源互斥访问、防止并发冲突
领导选举 LeaderSelector 主节点选举、任务协调
分布式计数器 DistributedAtomicLong 全局唯一序号、计数统计
节点缓存 NodeCache 监听单个节点数据变化
子节点缓存 PathChildrenCache 监听子节点列表变化
树缓存 TreeCache 监听整个子树变化
分布式队列 DistributedQueue 任务队列(谨慎使用)
分布式屏障 DistributedBarrier 节点同步、协调开始/结束

8.2 如何选择合适的模式?

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

单个节点

子节点列表

整个子树

需要什么协调能力?

资源互斥?

使用分布式锁

需要唯一主节点?

使用领导选举

需要全局计数?

使用分布式计数器

需要实时感知数据变化?

监听范围

使用 NodeCache

使用 PathChildrenCache

使用 TreeCache

需要节点同步?

使用分布式屏障

需要任务队列?

考虑专业消息队列如 Kafka、RabbitMQ

8.3 最佳实践总结

  • 锁模式:优先使用 InterProcessMutex,注意处理连接状态变化
  • 领导选举:LeaderSelector 更灵活,LeaderLatch 更简单
  • 缓存:选择适当的缓存类型,避免不必要的资源消耗
  • 队列:除非非常简单,否则建议使用专业消息队列
  • 重试策略:所有操作都配置合适的重试策略,提高容错性
  • Apache Curator 的 Recipes 模块将分布式系统的复杂性封装成简洁的 API,让开发者能够像使用本地工具一样轻松实现分布式协调。掌握这七大利器,你将能够应对绝大多数分布式系统开发中的协调挑战。

    在这里插入图片描述

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

    赞(0)
    未经允许不得转载:171主机测评 » Apache Curator 分布式协调模式全解析:七大利器助你构建健壮分布式系统
    分享到: 更多 (0)

    评论 抢沙发

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