在這種情況下,如果我們實現鎖可以使用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 ...