分布式鎖實現方案

2022-07-25 13:03:14 字數 1236 閱讀 1118

在這種情況下,如果我們實現鎖可以使用synchronized或reentrantlock,但是在分布式情況下,它們最多只能鎖住當前jvm的執行緒,對於其它server的執行緒無能為力。那麼怎麼處理呢? 

一般是通過為資料庫表新增乙個 「version」欄位來實現讀取出資料時,將此版本號一同讀出,之後更新時,對此版本號加1。在更新過程中,會對版本號進行比較,如果是一致的,沒有發生改變,則會成功執行本次操作;如果版本號不一致,則會更新失敗。

該命令只有key不存在時,才進行新增,或者不會處理。memcached 所有命令都是原子性的,併發下add 同乙個key ,只會乙個會成功。

我們需要在add()的使用指定當前新增的這個key的有效時間,如果不指定有效時間,正常情況下執行完自己的業務後,使用delete方法將這個key刪除掉,也就是釋放了占用的資源。但是,如果在佔位成功後,memecached或者自己的業務伺服器發生宕機了,那麼這個資源將無法得到釋放。所以通過對key設定超時時間,即便發生了宕機的情況,也不會將資源一直占用,可以避免死鎖的問題。

這個方案相對於memcached()的add()方案,redis佔優勢的是,其支援的資料型別更多,而memcached只支援string一種資料型別。

具體使用步驟如下:

setnx()該方法是原子的,如果key不存在,則設定當前key成功,返回1;如果當前key已經存在,則設定當前key失敗,返回0;

但是要注意的是setnx命令不能設定key的超時時間,只能通過expire()來對key設定;

首先我們來了解一下zookeeper的特性,看看它為什麼適合做分布式鎖,

zookeeper是乙個為分布式應用提供一致性服務的軟體,它內部是乙個分層的檔案系統目錄樹結構,規定統一個目錄下只能有乙個唯一檔名。

資料模型:

監視器(watcher):

根據zookeeper的這些特性,我們來看看如何利用這些特性來實現分布式鎖:

1. 建立乙個鎖目錄lock

2. 希望獲得鎖的執行緒a就在lock目錄下,建立臨時順序節點

3. 獲取鎖目錄下所有的子節點,然後獲取比自己小的兄弟節點,如果不存在,則說明當前執行緒順序號最小,獲得鎖

4. 執行緒b獲取所有節點,判斷自己不是最小節點,設定監聽(watcher)比自己次小的節點(只關注比自己次小的節點是為了防止發生「羊群效應」)

5. 執行緒a處理完,刪除自己的節點,執行緒b監聽到變更事件,判斷自己是最小的節點,獲得鎖。

使用zookeeper的優點

參考文章:

實現分布式鎖的幾種方案

分布式系統中,原子執行一段 比如減庫存 redisvalue token environment.machinename lock key表示的是redis資料庫中該鎖的名稱,不可重複。token用來標識誰擁有該鎖並用來釋放鎖。timespan表示該鎖的有效時間。10秒後自動釋放,避免死鎖。if d...

分布式鎖 使用Redis實現分布式鎖

關於分布式鎖的實現,我的前一篇文章講解了如何使用zookeeper實現分布式鎖。關於分布式鎖的背景此處不再做贅述,我們直接討論下如何使用redis實現分布式鎖。關於redis,筆主不打算做長篇大論的介紹,只介紹下redis優秀的特性。支援豐富的資料型別,如string list map set zs...

分布式鎖實現

1,資料庫實現原理 資料庫的行級x鎖。優點 不需要引入第三方應用。缺點 死鎖 對資料庫效能影響,可能較長時間占用資料庫連線資源 如果業務是分庫分表的,可能支援不了 示例 2,快取實現原理 通過setnx是否成功。當且僅當 key 不存在,將 key 的值設為 value 並返回1 若給定的 key ...