一.可以使用redis,zookeeper,etcd是實現分布式鎖
二.redis主要是通過setnx、get、getset、del命令來完成加鎖,搶鎖和釋放鎖的操作的。
1.setnx實現加鎖,返回1加鎖成功
2.get查看鎖是否超時
3.超時了使用getset搶鎖
4.del實現釋放鎖
redis存在的問題
1、redis如果是單機的話是有單點問題的。
redis集群因為是ap模型,是不能保證一致性的,官方提供了redlock算法來解決這個問題,但是至少需要3個master-slave節點才能完成,成本也較大。redlock相當于是來實現一致性協議的。
2、鎖的超時時間設定問題,太長太短都不合適,太長了如果服務掛掉了會一直阻塞業務,太短了有可能業務還沒執行完成就釋放了。當然可以用官方提供redisson解決。
三.zookeeper是基于順序臨時節點和watch機制實現分布式鎖的
1.順序節點可以保證最小的節點獲取鎖
2.臨時節點可以保證業務掛了,可以釋放鎖
3.監聽機制可以保證鎖釋放后及時得到通知,再次獲取鎖
zk采用zab協議保證一致性,并且不用設置超時時間了,如果服務加鎖掛掉了,臨時節點也會自動刪除。也可用使用Apache開源的curator框架,自帶了分布式鎖解決方案,原理和上述差不多。zk加鎖釋放鎖都是通過動態創建節點、銷毀節點來實現的,性能消耗較大。
四.etcd調用可以通過restfulAPI的方式進行,這些需要通過prevExist實現分布式鎖,如果prevExist為true,則這是一個更新請求,如果prevExist的值是false,則是一個創建請求。
1.server1獲取鎖,設置超時時間是3秒http://127.0.0.1:2379/v2/keys/locks?value=xxx&ttl=3&prevExist=false
2.為了防止業務還沒有執行完,鎖釋放,所以每隔1秒需求重新設置下值。這個就是鎖續租約。http://127.0.0.1:2379/v2/keys/locks?value=xxx&ttl=3&prevExist=true
3.server2這時候去獲取鎖,則會失敗http://127.0.0.1:2379/v2/keys/locks?value=xxx&ttl=3&prevExist=false
4.server2可以監聽lock的變化。當lock目錄有變化的時候就會接到通知,然后重復步驟3。這里要注意watch事件不能太多。http://127.0.0.1:2379/v2/keys/lock?wait=true
上面這個是etcd2的實現,etcd3本身已經支持分布式鎖了,key增加Revision了,客戶端可以判定自己key對應的Revision是不是最小來獲取鎖,機制和zk獲取最小值類似。
上面就是redis、zk、etcd怎么實現分布式鎖的過程了。每種方案都有公司在使用,也比較成熟了。
只要能保持讀取和修改狀態是原子性操作都能當鎖使用,但是分布式鎖需要明確的幾個條件:
獲取鎖的業務無論正常還是異常,都需要保證可以釋放,否則會出現死鎖的情況,還有就是鎖釋放后需要及時讓等待鎖的一方知道,方便再次獲取鎖。
希望對你有幫助,可以看我分享的另一文章,里面有每一步操作的截圖。
我,后續會持續分享架構方面文章,謝謝。