0x01、基於mysql實現分布式鎖
基於分布式鎖的實現,首先肯定是想單獨分離出一台mysql資料庫,所有服務要想操作檔案(共享資源),那麼必須先在mysql資料庫中插入乙個標誌,插入標誌的服務就持有了鎖,並對檔案進行操作,操作完成後,主動刪除標誌進行鎖釋放,其與服務會一直查詢資料庫,看是否標誌有被占用,直到沒有標誌占用時自己才能寫入標誌獲取鎖。
但是這樣有這麼乙個問題,如果服務(jvm1)宕機或者卡頓了,會一直持有鎖未釋放,這樣就造成了死鎖,因此就需要有乙個監視鎖程序時刻監視鎖的狀態,如果超過一定時間未釋放就要進行主動清理鎖標記,然後供其與服務繼續獲取鎖。
如果監視鎖欄位程序和jvm1同時掛掉,依舊不能解決死鎖問題,於是又增加乙個監視鎖欄位程序,這樣乙個程序掛掉,還有另乙個監視鎖欄位程序可以對鎖進行管理。這樣又誕生乙個新的問題,兩個監視程序必須進行同步,否則對於過期的情況管理存在不一致問題。
因此存在以下問題,並且方案變得很複雜:
相比較於基於資料庫實現分布式鎖的方案來說,基於快取來實現在效能方面會表現的更好一點,redis就是其中一種。由於redis可以設定欄位的有效期,因此可以實現自動釋放超期的鎖,不需要多個監視鎖欄位程序進行鎖守護,可以依舊存在上述mysql實現中除了3以外1、2、4中的問題。
基於以上兩種實現方式,有了基於zookeeper實現分布式鎖的方案。由於zookeeper有以下特點:
zookeeper的每乙個節點,都是乙個天然的順序發號器。
在每乙個節點下面建立子節點時,只要選擇的建立型別是有序(ephemeral_sequential 臨時有序或者persistent_sequential 永久有序)型別,那麼,新的子節點後面,會加上乙個次序編號。這個次序編號,是上乙個生成的次序編號加一
比如,建立乙個用於發號的節點「/test/lock」,然後以他為父親節點,可以在這個父節點下面建立相同字首的子節點,假定相同的字首為「/test/lock/seq-」,在建立子節點時,同時指明是有序型別。如果是第乙個建立的子節點,那麼生成的子節點為/test/lock/seq-0000000000,下乙個節點則為/test/lock/seq-0000000001,依次類推,等等。
三種常見分布式鎖實現方案
1.1 資料庫分布式鎖的優勢 1.2 資料庫分布式鎖的缺點 1.3 實現原理 在資料庫中建立乙個表,表中包含方法名等字段,並在方法名字段上建立唯一索引 想要執行某個方法,就使用這個方法名向表中插入資料 成功插入則獲取鎖,執行完成後刪除對應的行資料釋放鎖。1.1 redis分布式鎖的優勢 1.2 re...
實現分布式鎖的三種方式
1 資料庫的樂觀鎖 版本號機制 悲觀鎖與樂觀鎖 2 基於redis的分布式鎖 加鎖public class redistool return false 我們加鎖就一行 jedis.set string key,string value,string n string expx,int time 這...
實現分布式鎖的三種方式
類似的文章網上一搜一大把,實現方式也無非這三種,不過自己還是總結一下吧,實際應用中只採用過快取來實現 通過增刪操作,借助資料庫唯一索引的唯一性或主鍵唯一性,來實現 缺點 資料庫單點問題,如果資料庫掛了,會導致業務系統不可用 獲取鎖後,沒有失效時間,如果解鎖失敗,就會導致鎖記錄始終在資料庫中,其他執行...