https://www.cnblogs.com/mengchunchen/p/9647756.html
Redis實現分佈式鎖
1.根據lockKey區進行setnx(set not exist,如果key值爲空,則正常設置,返回1,否則不會進行設置並返回0)操作,如果設置成功,表示已經獲得鎖,否則並沒有獲取鎖。
2.如果沒有獲得鎖,去Redis上拿到該key對應的值,在該key上我們存儲一個時間戳(用毫秒錶示,t1),爲了避免死鎖以及其他客戶端佔用該鎖超過一定時間(5秒),使用該客戶端當前時間戳,與存儲的時間戳作比較。
3.如果沒有超過該key的使用時限,返回false,表示其他人正在佔用該key,不能強制使用;如果已經超過時限,那我們就可以進行解鎖,使用我們的時間戳來代替該字段的值。
4.但是如果在setnx失敗後,get該值卻無法拿到該字段時,說明操作之前該鎖已經被釋放,這個時候,最好的辦法就是重新執行一遍setnx方法來獲取其值以獲得該鎖。
釋放鎖:刪除redis中key
Zookeeper實現分佈式鎖(性能沒另一個版本好,創建和刪除比較多)
基於臨時順序節點:
1.客戶端調用create()方法創建名爲“locknode/guid-lock-”的節點,需要注意的是,這裏節點的創建類型需要設置爲EPHEMERAL_SEQUENTIAL。
2.客戶端調用getChildren(“locknode”)方法來獲取所有已經創建的子節點。
3.客戶端獲取到所有子節點path之後,如果發現自己在步驟1中創建的節點是所有節點中序號最小的,那麼就認爲這個客戶端獲得了鎖。
4.如果創建的節點不是所有節點中序號最小的,那麼則監視比自己創建節點的序列號小的最大的節點,進入等待。直到下次監視的子節點變更的時候,再進行子節點的獲取,判斷是否獲取鎖。
釋放鎖的過程相對比較簡單,就是刪除自己創建的那個子節點即可。
Zookeeper另一個版本:
zk分佈式鎖,就是某個節點嘗試創建臨時znode,此時創建成功了就獲取了這個鎖;這個時候別的客戶端來創建鎖會失敗,只能註冊個監聽器監聽這個鎖。
釋放鎖就是刪除這個znode,一旦釋放掉就會通知客戶端,然後有一個等待着的客戶端就可以再次重新加鎖。
區別
zk分佈式鎖,獲取不到鎖,註冊個監聽器即可,不需要不斷主動嘗試獲取鎖,性能開銷較小。
redis分佈式鎖,其實需要自己不斷去嘗試獲取鎖,比較消耗性能。
如果是redis獲取鎖的那個客戶端bug了或者掛了,那麼只能等待超時時間之後才能釋放鎖;而zk的話,因爲創建的是臨時 znode,只要客戶端掛了,znode就沒了,此時就自動釋放鎖
Spring Cloud 實現全局鎖(內置的)