一、為什么要使用分布式鎖
在多實例喻圃,負載均衡的情景下萤彩,需要使用分布式鎖來保證業(yè)務(wù)不會重復處理
二、分布式鎖應(yīng)該具備哪些條件
1斧拍、在分布式系統(tǒng)環(huán)境下雀扶,一個方法在同一時間只能被一個機器的一個線程執(zhí)行;
2、高可用的獲取鎖與釋放鎖愚墓;
3予权、高性能的獲取鎖與釋放鎖;
4浪册、具備可重入特性扫腺;
5、具備鎖失效機制村象,防止死鎖笆环;
6、具備非阻塞鎖特性厚者,即沒有獲取到鎖將直接返回獲取鎖失敗躁劣。
三、常見的分布式鎖的三種實現(xiàn)方式
1.基于數(shù)據(jù)庫實現(xiàn)排他鎖
- 基于數(shù)據(jù)庫表做樂觀鎖库菲,用于分布式鎖账忘。(version)
- 基于數(shù)據(jù)庫表做悲觀鎖(InnoDB,for update)
- 基于數(shù)據(jù)庫表數(shù)據(jù)記錄做唯一約束(表中記錄方法名稱)
缺點:
1熙宇、這把鎖強依賴數(shù)據(jù)庫的可用性闪萄,數(shù)據(jù)庫是一個單點,一旦數(shù)據(jù)庫掛掉奇颠,會導致業(yè)務(wù)系統(tǒng)不可用败去。
2、這把鎖沒有失效時間烈拒,一旦解鎖操作失敗圆裕,就會導致鎖記錄一直在數(shù)據(jù)庫中,其他線程無法再獲得到鎖荆几。
3吓妆、這把鎖只能是非阻塞的,因為數(shù)據(jù)的insert操作吨铸,一旦插入失敗就會直接報錯行拢。沒有獲得鎖的線程并不會進入排隊隊列,要想再次獲得鎖就要再次觸發(fā)獲得鎖操作诞吱。
4舟奠、這把鎖是非重入的,同一個線程在沒有釋放鎖之前無法再次獲得該鎖房维。因為數(shù)據(jù)中數(shù)據(jù)已經(jīng)存在了沼瘫。
2.基于zookeeper實現(xiàn)
每個客戶端對某個方法加鎖時,在zookeeper上的與該方法對應(yīng)的指定節(jié)點的目錄下咙俩,生成一個唯一的瞬時有序節(jié)點耿戚。 判斷是否獲取鎖只需要判斷有序節(jié)點中序號最小的一個。 當釋放鎖的時候,只需將這個瞬時節(jié)點刪除即可膜蛔。
缺點:
性能上可能并沒有緩存服務(wù)那么高坛猪。因為每次在創(chuàng)建鎖和釋放鎖的過程中,都要動態(tài)創(chuàng)建皂股、銷毀瞬時節(jié)點來實現(xiàn)鎖功能墅茉。ZK中創(chuàng)建和刪除節(jié)點只能通過Leader服務(wù)器來執(zhí)行,然后將數(shù)據(jù)同不到所有的Follower機器上
3.基于redis實現(xiàn)
使用命令SET lockKey lock_value NX PX 30000
原子化命令屑墨,加鎖和設(shè)置失效時間。
缺點:
在這種場景(主從結(jié)構(gòu))中存在明顯的競態(tài):
客戶端A從master獲取到鎖纷铣,
在master將鎖同步到slave之前卵史,master宕掉了。
slave節(jié)點被晉級為master節(jié)點搜立,
客戶端B取得了同一個資源被客戶端A已經(jīng)獲取到的另外一個鎖以躯。安全失效!