單機應用架構中,秒殺案例使用ReentrantLcok或者synchronized來達到操做業務互斥的目的。然而在分佈式系統中,會存在多臺機器並行去實現同一個功能。也就是說,在多進程中,若是還使用以上JDK提供的進程鎖,來併發訪問數據庫資源就可能會出現數據重複、不一致的狀況。所以,須要咱們來實現本身的分佈式鎖。數據庫
實現一個分佈式鎖應該具有的特性:緩存
分佈式鎖幾種實現方式:bash
前兩種對於分佈式生產環境來講並非特別推薦,高併發下數據庫鎖性能太差,Redis在鎖時間限制和緩存一致性存在必定問題。重點實現一下 Zookeeper 如何實現分佈式鎖。網絡
ZooKeeper是一個分佈式的,開放源碼的分佈式應用程序協調服務,它內部是一個分層的文件系統目錄樹結構,規定同一個目錄下只能存在惟一文件名。session
數據模型架構
監視器(watcher)併發
當建立一個節點時,能夠註冊一個該節點的監視器,當節點狀態發生改變時,watch被觸發時,ZooKeeper將會向客戶端發送且僅發送一條通知,由於watch只能被觸發一次。分佈式
根據zookeeper的這些特性,咱們來看看如何利用這些特性來實現分佈式鎖:ide
儘管ZooKeeper已經封裝好複雜易出錯的關鍵服務,將簡單易用的接口和性能高效、功能穩定的系統提供給用戶。可是若是讓一個普通開發者去手擼一個分佈式鎖仍是比較困難的,在秒殺案例中咱們直接使用 Apache 開源的curator 開實現 Zookeeper 分佈式鎖。 高併發
同時參考:blog.csdn.net/u011663149/…
/**
* 基於curator的zookeeper分佈式鎖
*/
public class CuratorUtil {
private static String address = "192.168.1.180:2181";
public static void main(String[] args) {
//一、重試策略:初試時間爲1s 重試3次
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
//二、經過工廠建立鏈接
CuratorFramework client = CuratorFrameworkFactory.newClient(address, retryPolicy);
//三、開啓鏈接
client.start();
//4 分佈式鎖
final InterProcessMutex mutex = new InterProcessMutex(client, "/curator/lock");
//讀寫鎖
//InterProcessReadWriteLock readWriteLock = new InterProcessReadWriteLock(client, "/readwriter");
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
fixedThreadPool.submit(new Runnable() {
@Override
public void run() {
boolean flag = false;
try {
//嘗試獲取鎖,最多等待5秒
flag = mutex.acquire(5, TimeUnit.SECONDS);
Thread currentThread = Thread.currentThread();
if(flag){
System.out.println("線程"+currentThread.getId()+"獲取鎖成功");
}else{
System.out.println("線程"+currentThread.getId()+"獲取鎖失敗");
}
//模擬業務邏輯,延時4秒
Thread.sleep(4000);
} catch (Exception e) {
e.printStackTrace();
} finally{
if(flag){
try {
mutex.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
});
}
}
}複製代碼
這裏咱們開啓5個線程,每一個線程獲取鎖的最大等待時間爲5秒,爲了模擬具體業務場景,方法中設置4秒等待時間。開始執行main方法,經過ZooInspector或者zk-ui 可視化監控/curator/lock下的節點以下圖:
觀察控制檯,咱們會發現只有兩個線程獲取鎖成功,另外三個線程超時獲取鎖失敗會自動刪除節點。線程執行完畢咱們刷新一下/curator/lock節點,發現剛纔建立的五個子節點已經不存在了。