首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

分布式任務調度與分布式鎖:基於 ZooKeeper 的實戰方案詳解

     編輯:Java 綜合教學

分布式任務調度與分布式鎖:ZooKeeper 實戰方案詳解

一、業務背景與痛點

系統中存在批量審批、批量授權等高併發操作。因處理機器、線程不同,導致緩存刷新時出現數據互相覆蓋丟失:例如同一用戶多個權限申請並發發送至 ACL 不同服務器,機器 A 處理授權 A,機器 B 同時處理授權 B,事務隔離導致雙方看不見對方提交的數據,刷新緩存時從 DB 讀取各自可見數據,最終造成權限丟失。核心需求:跨機器、跨線程的協調同步,即分布式鎖。

誤區警示:ReentrantLock 僅能解決單進程內線程同步,其 lock/unlock 必須在同一線程,無法用於分布式場景。

二、ZooKeeper 核心機制

ZooKeeper 是分布式協調服務框架,基於觀察者模式,提供類文件系統的目錄節點樹(ZNode)存儲數據並監控狀態變化。核心特性:

  • 節點類型:PERSISTENT(持久)、EPHEMERAL(臨時,會話結束自動刪除)、SEQUENTIAL(順序編號)。
  • Watch 監聽:一次性觸發,節點數據/子節點變化通知客戶端。
  • ACL 權限控制:perms(READ/WRITE/CREATE/DELETE/ADMIN)+ id(world/auth/ip)。

三、常用 API 速查

方法功能
create(path, data, acl, mode)創建節點,mode 指定四類節點類型
exists(path, watch/watcher)判斷節點存在並註冊監聽
getChildren(path, watch/watcher)獲取子節點列表
setData(path, data, version)更新節點數據,版本號樂觀鎖
getData(path, watch/watcher, stat)讀取節點數據及元數據
delete(path, version)刪除節點,-1 匹配所有版本

四、基礎操作 Demo

ZooKeeper zk = new ZooKeeper("localhost:2181", 3000, event -> 
    System.out.println("觸發事件: " + event.getType()));
zk.create("/testRootPath", "testRootData".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create("/testRootPath/testChildPathOne", "testChildDataOne".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(new String(zk.getData("/testRootPath", false, null))); // testRootData
System.out.println(zk.getChildren("/testRootPath", true)); // [testChildPathOne]
zk.setData("/testRootPath/testChildPathOne", "modifyChildDataOne".getBytes(), -1);
zk.create("/testRootPath/testChildPathTwo", "testChildDataTwo".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.delete("/testRootPath/testChildPathTwo", -1);
zk.delete("/testRootPath/testChildPathOne", -1);
zk.delete("/testRootPath", -1);
zk.close();

五、四大經典應用場景實現原理

1. 統一命名服務

利用 ZNode 唯一路徑特性生成全局唯一名稱,類似 JNDI 但更輕量,調用 create 即可實現。

2. 配置管理

將配置存儲於 ZNode,所有應用機器 getData + watch 監聽,配置變更推送通知,各機器拉取最新配置熱加載,實現配置中心核心功能。

3. 集群管理與 Leader 選舉

  • 機器存活監控:各 Server 創建 EPHEMERAL 節點,父節點註冊 getChildren + watch,節點刪減/新增觸發變更通知。
  • Master 選舉:創建 EPHEMERAL_SEQUENTIAL 節點,編號最小者為 Master;Master 掛掉節點自動刪除,次小編號自動升級,避免單點故障。
void findLeader() {
    byte[] leader = zk.getData(root + "/leader", true, null);
    if (leader != null) { following(); }
    else {
        String newLeader = zk.create(root + "/leader", localhostBytes, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        if (newLeader != null) leading(); else mutex.wait();
    }
}

4. 分布式鎖(共享鎖 / 排他鎖)

加鎖流程:

  1. 客戶端創建 _locknode_/lock- 臨時順序節點。
  2. getChildren 獲取所有鎖節點,取最小編號。
  3. 若最小節點是自己創建的 → 獲得鎖,執行業務。
  4. 否則 exists(比自己小一號節點, watch=true) 監聽,收到刪除通知回到第 2 步。

解鎖:刪除自己創建的臨時節點即可。

void getLock() {
    List<String> list = zk.getChildren(root, false);
    String[] nodes = list.toArray(new String[0]);
    Arrays.sort(nodes);
    if (myZnode.equals(root + "/" + nodes[0])) doAction();
    else waitForLock(nodes[0]);
}
void waitForLock(String lower) {
    Stat stat = zk.exists(root + "/" + lower, true);
    if (stat != null) mutex.wait(); else getLock();
}

5. 隊列管理

  • 同步隊列:成員創建 EPHEMERAL_SEQUENTIAL 節點入隊,數量達標創建 /start 觸發所有成員 watch 執行任務。
  • FIFO 隊列:生產者創建 PERSISTENT_SEQUENTIAL 節點 /queue_i,消費者 getChildren 取最小編號消費並刪除,保證先進先出。

六、總結與避坑指南

ZooKeeper 作為 Hadoop 生態核心組件,通過層次化目錄樹 + Watch 機制,優雅解決了分布式系統中的配置管理、服務發現、主從選舉、分布式鎖、隊列協調等經典問題。實際落地注意:

  • 會話超時時間設定合理,避免網絡抖動誤觸發節點刪除。
  • 大量 Watch 註冊可能導致羊群效應,關鍵路徑考慮緩存或分佈式鎖優化(如 Curator 框架的 InterProcessMutex)。
  • 生產環境建議使用成熟客端庫(Apache Curator),封裝了重試、連接狀態管理、Recipe 模板,降低開發難度。

參考資料:ZooKeeper 典型應用場景深度解析

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved