Redis分布式鎖學習記錄

2021-10-22 06:25:09 字數 1900 閱讀 6605

首先我們要明確乙個定義,分布式鎖是為了保證統一時間只有乙個客戶端能對共享資源進行操作(update、delete、insert)。

在涉及到一些訂單、庫存、金額時,為了避免出現超賣、重複扣款等情況發生,我們必須要保證從下單到扣款一系列的操作都只能成功執行一次,而在一般的正式生產環境中為了保證服務的高可用性我們會採用服務集群的模式,這也就直接宣布@synchronized、lock這些方法沒辦法有效地保證集群服務之間的資料一致性,分布式事務鎖也就由此誕生。

分布式鎖可以有多種實現方式,比如通過mysql資料庫、redies等就能有多種實現方式。

1.通過唯一索引或主鍵索引,達到互斥鎖的效果

把一把鎖的id作為主鍵插入到資料庫,如果鎖已存在,其他人就會插入失敗,也就搶不到鎖,在業務邏輯完成或者超時後再把這條資料刪掉。

2.通過mysql的樂觀鎖,實現資料一致性的效果

當完成乙個update或者delete命令時,再重新查一遍資料看看是否與預期資料一樣,如果和預期資料一樣這輪操作就算成功完成,如果不一樣就要進行事務回滾,但是這種方法顯然難以避免在高併發情況下產生髒讀的情況。

3.通過redis實現

用mysql固然可以實現分布式鎖,但是在高併發的場景下效率顯然是比較容易出現效能瓶頸的,因此我們最好的選擇還是通過redis來實現。

1)搶鎖

用redis的setnx命令去搶鎖,當乙個請求成功搶到鎖後,其他請求就只能進入等待或者直接返回失敗

2)死鎖

當乙個請求搶到鎖後還會存在乙個問題也就是如果業務邏輯由於資料庫、第三方介面等種種原因導致無限超時,那這把鎖就會變成死鎖,因此我們要用expire命令給這把鎖加乙個過期時間,過期時間比必須大於業務正常執行所需要的時間,保證即使鎖擁有者不主動釋放鎖也不會產生死鎖的結果。

3)看門狗

當乙個請求搶到鎖後由於種種原因導致業務執行時間超出正常預期(只超出幾秒或者其他可控範圍內)時,如果鎖由於自動過期時間直接被釋放,這時第二個請求搶到這把鎖開始執行業務,執行業務期間上乙個得到鎖的執行緒執行釋放鎖的動作,把第二個請求得到的鎖釋放了,這就產生鎖錯亂的結果。這時候我們要引入乙個看門狗的概念,其作用就是對請求一這樣小超時但是不至於到死鎖的級別時進行乙個鎖續時的操作,看門狗預設有效時間是30s,也就是說30s就不會再進行續時操作了,同時在finally**塊中寫上釋放鎖的動作,進一步保證鎖的安全和有效性。

4)分布式redis節點

經過以上幾個步驟的逐步完善,在大部分情況下我們已經能在分布式鎖的作用下保證資料的安全性和一致性,但是在極端情況下譬如redis節點崩了,那就直接造成快取穿透、快取血崩等等情況,分布式鎖自然也就失效了。這時候我們就可以考慮用多台(單數)redis單節點來保證redis的高可用,譬如用3台單節點redis服務,每個請求要在這3個節點中搶到至少2把鎖才算是搶鎖成功,這樣即使暫時一台redis節點宕機了也不會直接造成資料錯亂等後果。

5)延遲啟動redis節點

假設現在有3臺redis單機節點,當其中一台redis節點宕機後,已經搶到鎖的請求在業務執行完畢後會釋放掉已經搶到的2個鎖,其中乙個鎖的redis節點已宕機,也就是釋放另乙個鎖,此時第二個請求只搶到一把鎖,在這之後拿到第二把鎖,搶鎖成功,業務繼續執行。如果在第乙個請求釋放鎖之前直接把宕機的redis節點重啟,那第二個請求就會直接拿到重啟的redis節點的鎖,開始執行業務,就會出現兩個請求同時執行業務的情況,也就是鎖失效了。因此我們要至少確保一輪業務跑完,釋放掉鎖之後再重啟宕機的redis節點。

阿里開源元件seata在進行配置後可以用乙個@globatranscational註解保證這個業務類下所有方法都能具有資料強一致性,也就是所有步驟都結束後和預期結果對比沒有報錯,再統一對資料庫進行操作。相比於前面用redis就算弱一致性,報錯後回滾是分開回滾的。由此不難判斷seata雖然能保證資料的強一致性,但是效率也是比較低的,在對於金融操作如轉賬等我們可以用seata來處理,對於一些庫存的加減我們可以用效率更高的redis分布式鎖來處理。

redis分布式鎖

redis分布式鎖 直接上 我寫了四個redis分布式鎖的方法,大家可以提個意見 第一種方法 redis分布式鎖 param timeout public void lock long timeout thread.sleep 100 catch exception e override publi...

Redis分布式鎖

分布式鎖一般有三種實現方式 1.資料庫樂觀鎖 2.基於redis的分布式鎖 3.基於zookeeper的分布式鎖.首先,為了確保分布式鎖可用,我們至少要確保鎖的實現同時滿足以下四個條件 互斥性。在任意時刻,只有乙個客戶端能持有鎖。不會發生死鎖。即使有乙個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保...

redis分布式鎖

使用redis的setnx命令實現分布式鎖 redis為單程序單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多個客戶端對redis的連線並不存在競爭關係。redis的setnx命令可以方便的實現分布式鎖。setnx key value 將key的值設為value,當且僅當key不存在。如給定的...