在分散式系統中,協調多節點對共享資源的互斥存取是核心課題。Apache Curator 是 ZooKeeper 的高階客戶端框架,提供 InterProcessMutex 實現可重入的分散式鎖,自動處理連線重試、Session 過期、羊群效應等複雜情境。本文以完整可執行範例示範基本用法。
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.6.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.6.0</version>
</dependency>
import java.util.concurrent.*;
import com.netflix.curator.*;
import com.netflix.curator.framework.*;
import com.netflix.curator.framework.recipes.locks.*;
import com.netflix.curator.retry.*;
public class CuratorLockDemo {
private static final String ZK_CONNECTION = "localhost:2181";
private static final String LOCK_PATH = "/shared_lock/demo";
public static void main(String[] args) throws Exception {
// 1. 建立客戶端,指數退避重試
RetryPolicy retry = new ExponentialBackoffRetry(1000, 3);
CuratorFramework client = CuratorFrameworkFactory.newClient(ZK_CONNECTION, retry);
client.start();
System.out.println("ZooKeeper 客戶端已啟動");
// 2. 模擬 5 個客戶端搶鎖
ExecutorService executor = Executors.newFixedThreadPool(5);
CountDownLatch latch = new CountDownLatch(5);
for (int i = 0; i < 5; i++) {
final String clientName = "Client-" + i;
executor.submit(() -> {
InterProcessMutex lock = new InterProcessMutex(client, LOCK_PATH);
try {
if (lock.acquire(30, TimeUnit.SECONDS)) {
try {
System.out.println("[" + clientName + "] 獲得鎖,開始處理業務");
Thread.sleep(2000); // 模擬業務處理
System.out.println("[" + clientName + "] 業務完成");
} finally {
lock.release();
System.out.println("[" + clientName + "] 釋放鎖");
}
} else {
System.out.println("[" + clientName + "] 獲取鎖超時");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
latch.countDown();
}
});
}
latch.await(); // 等待所有任務結束
executor.shutdown();
client.close();
System.out.println("示範結束");
}
}
| 類別 | 用途 |
|---|---|
ExponentialBackoffRetry | 連線失敗時指數退避重試策略 |
InterProcessMutex | 可重入分散式鎖,基於 ZooKeeper 臨時有序節點 |
acquire(timeout, unit) | 阻塞等待鎖,支援超時控制 |
release() | 釋放鎖,必須在 finally 區塊呼叫 |
acquire 需對應次數 release。ConnectionStateListener,Session 失效時自動釋放鎖並拋出例外。InterProcessReadWriteLock。LOCK_PATH 必須所有參與者共享相同路徑。finally 釋放鎖,否則造成死鎖。