分布鎖的三種實現方式


在很多分布式的環境中都要求實現分布式事務、分布式鎖,但是java在單機環境中是無法實現的,必須借助外部工具來實現

1、基於數據庫

2、基於redis或者memcached

3、基於Zookeeper

但是這三種的實現也各有有缺點:

性能:緩存 > Zookeeper >= 數據庫

可靠:Zookeeper > 緩存 > 數據庫


一、基於數據庫來實現分布鎖

原理:

最簡單的就是直接創建一張鎖表,然后通過操作該表中的數據來實現了。

當我們要鎖住某個方法或資源時,我們就在該表中增加一條記錄,想要釋放鎖的時候就刪除這條記錄。

1、數據庫的性能以及可靠性都會影響性能,數據庫必須實現高可用性部署,防止主機掛了,整個業務就掛了

2、這把鎖只能是非阻塞的,沒法重入,也無法實現隊列機制。重入必須一直while,直到有最終結果回應

3、加大數據庫的開銷影響其他的業務的進行


二、基於緩存實現分布鎖

這里主講redis

1、選用Redis實現分布式鎖原因:

Redis有很高的性能; 

Redis命令對此支持較好,實現起來比較方便

Redis是單線程的,天生就能處理並發

2、使用命令介紹:

(1)SETNX

SETNX key val:當且僅當key不存在時,set一個key為val的字符串,返回1;若key存在,則什么都不做,返回0
  • 1

(2)expire

expire key timeout:為key設置一個超時時間,單位為second,超過這個時間鎖會自動釋放,避免死鎖。
  • 1

(3)delete

delete key:刪除key
  • 1

在使用Redis實現分布式鎖的時候,主要就會使用到這三個命令。

3、實現原理:

(1)獲取鎖的時候,使用setnx加鎖,並使用expire命令為鎖添加一個超時時間,超過該時間則自動釋放鎖,鎖的value值為一個隨機生成的UUID,通過此在釋放鎖的時候進行判斷。

(2)獲取鎖的時候還設置一個獲取的超時時間,若超過這個時間則放棄獲取鎖。

(3)釋放鎖的時候,通過UUID判斷是不是該鎖,若是該鎖,則執行delete進行鎖釋放。


三、基於zookeeper實現分布鎖

原理:ZooKeeper是一個為分布式應用提供一致性服務的開源組件,它內部是一個分層的文件系統目錄樹結構,規定同一個目錄下只能有一個唯一文件名

實現步驟:

(1)創建一個目錄mylock; 
(2)線程A想獲取鎖就在mylock目錄下創建臨時順序節點; 
(3)獲取mylock目錄下所有的子節點,然后獲取比自己小的兄弟節點,如果不存在,則說明當前線程順序號最小,獲得鎖; 
(4)線程B獲取所有節點,判斷自己不是最小節點,設置監聽比自己次小的節點; 
(5)線程A處理完,刪除自己的節點,線程B監聽到變更事件,判斷自己是不是最小的節點,如果是則獲得鎖。

這里推薦一個Apache的開源庫Curator,它是一個ZooKeeper客戶端,Curator提供的InterProcessMutex是分布式鎖的實現,acquire方法用於獲取鎖,release方法用於釋放鎖。

public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
    try {
        return interProcessMutex.acquire(timeout, unit);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return true;
}
public boolean unlock() {
    try {
        interProcessMutex.release();
    } catch (Throwable e) {
        log.error(e.getMessage(), e);
    } finally {
        executorService.schedule(new Cleaner(client, path), delayTimeForClean, TimeUnit.MILLISECONDS);
    }
    return true;
}

優點:具備高可用、可重入、阻塞鎖特性,可解決失效死鎖問題。

缺點:因為需要頻繁的創建和刪除節點,性能上不如Redis方式。



參考:https://blog.csdn.net/xlgen157387/article/details/79036337

https://www.cnblogs.com/yuyutianxia/p/7149363.html



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com