分布式服務需要乙個全域性鎖來實現同乙個模組多個服務之間的同步。就需要用到分布式鎖。
實現方式:資料庫主鍵、redis、zookeeper
1、資料庫
利用資料庫主鍵唯一規則,在爭搶鎖的時候向db中寫一條記錄,這條記錄主要包含鎖的id、當前占用鎖的執行緒名、重入的次數和建立時間等,如果插入成功表示當前執行緒獲取到了鎖,如果插入失敗那麼證明鎖被其他人占用,等待一會兒繼續爭搶,直到爭搶到或者超時為止。
優點:實現簡單
缺點:沒有超時保護機制、沒有執行緒喚醒機制。
2、redis(推薦)
基於setnx實現:
setnx是redis提供的乙個原子操作,如果指定key存在,那麼setnx失敗,如果不存在會進行set操作並返回成功。我們可以利用這個來實現乙個分布式的鎖,主要思路就是,set成功表示獲取鎖,set失敗表示獲取失敗,失敗後需要重試。
優點:實現簡單,吞吐量十分可觀,對於高併發情況應付自如,自帶超時保護,對於網路抖動的情況也可以利用超時刪除策略保證不會阻塞所有流程。
缺點:沒有執行緒喚醒機制。
對key設定失效時間,這個超時時間需要把控好,過大那麼系統吞吐量低。如果過小那麼會有併發安全問題。
3、zookeeper
方式一:zookeeper的寫入都是順序的,在乙個節點建立之後,其他請求再次建立便會失敗,同時可以對這個節點進行watch,如果節點刪除會通知其他節點搶占鎖。
由於zookeeper本身需要維護自己的一致性,所以效能上較redis還是有一定差距的。
方式二:建立乙個 ephemeral_sequential (臨時自動編號)目錄節點,然後呼叫 getchildren方法獲取當前的目錄節點列表中最小的目錄節點是不是就是自己建立的目錄節點,如果正是自己建立的,那麼它就獲得了這個鎖,如果不是那麼它就呼叫 exists(string path, boolean watch) 方法並監控 zookeeper 上目錄節點列表的變化,一直到自己建立的節點是列表中最小編號的目錄節點,從而獲得鎖,釋放鎖很簡單,只要刪除前面它自己所建立的目錄節點就行了。
專案中使用:
分布式鎖 使用Redis實現分布式鎖
關於分布式鎖的實現,我的前一篇文章講解了如何使用zookeeper實現分布式鎖。關於分布式鎖的背景此處不再做贅述,我們直接討論下如何使用redis實現分布式鎖。關於redis,筆主不打算做長篇大論的介紹,只介紹下redis優秀的特性。支援豐富的資料型別,如string list map set zs...
分布式鎖實現
1,資料庫實現原理 資料庫的行級x鎖。優點 不需要引入第三方應用。缺點 死鎖 對資料庫效能影響,可能較長時間占用資料庫連線資源 如果業務是分庫分表的,可能支援不了 示例 2,快取實現原理 通過setnx是否成功。當且僅當 key 不存在,將 key 的值設為 value 並返回1 若給定的 key ...
分布式鎖的實現
分布式鎖的實現方式通常有三種,第一種是基於資料庫實現分布式鎖,第二種是基於快取實現分布式鎖,第三種是基於zookeeper實現分布式鎖.第一種 基於資料庫實現分布式鎖 特點 效能較差,容易出現單點故障 鎖沒有失效時間,容易思死鎖 非阻塞式的 不可重入 第二種基於快取實現分布式鎖 鎖沒有失效時間,容易...