類似的文章網上一搜一大把,實現方式也無非這三種,不過自己還是總結一下吧,實際應用中只採用過快取來實現
通過增刪操作,借助資料庫唯一索引的唯一性或主鍵唯一性,來實現
缺點:資料庫單點問題,如果資料庫掛了,會導致業務系統不可用
獲取鎖後,沒有失效時間,如果解鎖失敗,就會導致鎖記錄始終在資料庫中,其他執行緒則無法獲取鎖
鎖是非阻塞,沒有機制保證失敗後的阻塞重試
鎖非重入,同乙個執行緒在沒有釋放之前,無法再次獲取該鎖
缺點的解決方案:
單點問題,可以通過主從資料庫的方式解決,資料雙向同步,主庫掛了從庫上
沒有失效時間問題,可以通過定時任務去清理長時間沒有釋放的鎖
非阻塞問題,問題是沒有重試,**中加入迴圈重試即可
鎖非重入問題,在資料庫表中加入獲取鎖的執行緒資訊的字段,執行緒在獲取鎖之前先查詢是否通過當前機器資訊和執行緒資訊可以獲取,如果可以則獲取鎖
基於通過資料庫提供的排它鎖,來實現
通過在 select 語句後追加 for update,資料庫會在查詢過程中給資料庫表增加排它鎖,當某條記錄在查詢時被加上了排它鎖,其他執行緒查詢將無法在查詢時加上排它鎖
只有當獲取到鎖的連線 connection 提交 commit 時,才會將鎖釋放
select*from lock_table where lock_method ='**
'for
update;
相較第一種實現的優點:
阻塞鎖,for update 執行成功後立即返回,若失敗,則 while(true) 處於阻塞狀態,不斷重試直到成功
鎖失效問題,如果資料庫發生宕機,資料庫會將排它鎖釋放
通過 redis 中 setnx 方法實現
setnx 是 redis 提供的原子操作,如果指定 key 存在,那麼 set 失敗,如果不存在 set 成功並返回,利用這個操作便可實現乙個分布式鎖
set 成功便成功獲取鎖,失敗便是獲取鎖失敗,刪除快取則釋放掉鎖
鎖失效時間的問題,可以通過設定快取的過期時間解決
缺點:鎖失效時間,通過快取設定過期時間並不太靠譜,如果設定過長,過大請求量時吞吐量低,如果設定過短,耗時長的方法將出現併發問題
重入問題,和資料庫解決方法相同,獲取鎖時將執行緒資訊儲存,再次獲取時先查詢,查詢不到再嘗試 set 操作
zookeeper 原理還不熟,之後更新...
2019-08-13,終於更新啦 -> 詳解zookeeper原理與應用場景
分布式鎖的幾種實現方式~:
分布式鎖的三種實現的對比:
mysql 共享鎖與排它鎖:
阻塞和非阻塞,同步和非同步:
實現分布式鎖的三種方式
1 資料庫的樂觀鎖 版本號機制 悲觀鎖與樂觀鎖 2 基於redis的分布式鎖 加鎖public class redistool return false 我們加鎖就一行 jedis.set string key,string value,string n string expx,int time 這...
實現分布式鎖的三種方式
類似的文章網上一搜一大把,實現方式也無非這三種,不過自己還是總結一下吧,實際應用中只採用過快取來實現 通過增刪操作,借助資料庫唯一索引的唯一性或主鍵唯一性,來實現 缺點 資料庫單點問題,如果資料庫掛了,會導致業務系統不可用 獲取鎖後,沒有失效時間,如果解鎖失敗,就會導致鎖記錄始終在資料庫中,其他執行...
分布式鎖的三種實現方式
更多請參考 1 基於資料庫的實現方式的核心思想是 在資料庫中建立乙個表,表中包含方法名等字段,並在方法名字段上建立唯一索引,想要執行某個方法,就使用這個方法名向表中插入資料,成功插入則獲取鎖,執行完成後刪除對應的行資料釋放鎖。drop table if exists method lock crea...