redis做分布式鎖實戰案例詳解

2021-10-12 16:16:53 字數 2275 閱讀 4327

好久沒更新文章了,近幾天在研究分布式鎖,今天就更新下redis分布式鎖的內容;

環境:nginx+redis+idea+jmeter(壓力測試),思路:nginx將請求**到兩台伺服器(我本地啟動兩台),兩台伺服器進行搶奪資源

注意:由於資源有限,這裡nginx和redis我都以windows版本為例進行試驗

好,接下來進入切入正題,我們模擬買東西案例,商品數量儲存在redis中,然後啟動兩台idea通過nginx**進行消費,如下圖:

看**邏輯是很簡單的,從redis中取商品數量,商品數量大於0就減一然後寫回redis,這個時候我們是沒有使用分布式鎖的,我們只加了synchonized單機鎖,那麼有沒有問題呢,我用jmeter瞬間打過去200個請求,執行效果如圖所示:

大家看到了吧,嚴重的超賣現象,如果生產出現這種問題那肯定被封為t0及bug超級會員,可能要被祭天,原因就是我們現在是兩台伺服器而synchonized鎖的只是jvm層面,是一把單機鎖,在單機情況下

我們通過setifabsent來設定鎖,搶到鎖了就繼續執行,沒搶到就給你乙個友好提示,最後finally**塊釋放鎖

那麼上面加上分布式鎖之後的**有沒有問題呢鐵子,想想有沒有問題,其實是有問題的,問題就是:執行到一半出問題了,導致就沒執行finally**塊,那鎖一直存在沒有釋放,其他執行緒就獲取不到鎖,那不就game over了鐵子,所以我們要加個過期時間對不對,給它10s,10s後自動釋放鎖讓其他執行緒來使用,修改一下如圖所示:

那我加上過期時間其實還存在問題,就是「張冠李戴」,比如我a執行緒搶到了鎖,可能處理了12秒還沒處理完業務邏輯,但是10秒的時候a執行緒的鎖就過期了被自動刪除了,這個時候b帶著自己的鎖進來了,15秒的時候a處理完自己的那些事情了然後走finally**塊刪除鎖,這個時候a就把b的鎖給刪除了,以此類推是不是就出大問題了,所以我們要解決每個執行緒只能刪除自己的鎖,修改**如下:

我判斷一下是自己的鎖再進行刪除,然後老鐵你思考下是不是還存在乙個恐怖的問題,就是finally**塊中刪除所的**不具備原子性,那多執行緒肯定有問題對不對,解決原子性問題redis官方給出建議使用lua

此時我們就通過lua指令碼解決了原子性問題,到此為止如果你的公司併發量不是特別特別大使用目前**基本上可以解決問題了,但是當併發特別大的時候還是有問題的

問題一:設定過期時間10s合理嗎?我處理業務時間可能10s可能20s或者30s不一定是吧,所以要解決分布式鎖如何續期的問題(就像你開車從河南開封到鄭州,路上沒油了要加油保證到達鄭州)

問題而:我剛把資料set到redis,redis主機收到之後還沒來得及把資料同步給備機就掛了,那是不是就出現資料丟失問題

針對上面兩個問題我們手寫解決很難,就算寫出來了你能保證不出問題?傻子才手寫解決上面兩個問題呢

既然不手寫解決,那肯定有可以解決的方法,接下來有請redlock出場,記住這不是紅樓夢鎖,也不是紅燒牛肉鎖,它就是redlock,能夠幫助我們解決上面兩個問題,俗話說的好天上飛的理念必定有落地的實現,redlock的落地實現redisson,我們就用redisson來解決,redisson主要通過乙個watchdog(看門狗)來解決續期的問題,感興趣的可以看下原始碼,下面直接上**,如下圖:

執行效果如圖所示:

Redis做分布式鎖

在分布式系統中,在介面沒 冪等性或者在某些場景下相同的服務需要有且僅有乙個服務執行的情況下,需要使用分布式鎖來保證系統的安全執行。分布式鎖的執行順序,有服務a,分別部署了三個節點為a1 a2 a3,為滿足我們上述需求,我們需要在共享的資料載體中做標記,即,a1開始執行的話,a2 a3不能在執行,直到...

Redis做分布式鎖

在分布式系統中,在介面沒 冪等性或者在某些場景下相同的服務需要有且僅有乙個服務執行的情況下,需要使用分布式鎖來保證系統的安全執行。分布式鎖的執行順序,有服務a,分別部署了三個節點為a1 a2 a3,為滿足我們上述需求,我們需要在共享的資料載體中做標記,即,a1開始執行的話,a2 a3不能在執行,直到...

Redis分布式鎖,開發實戰

背景 專案的定時任務,出現重複執行的情況。由於解決時間非常緊急。打算用redis自帶的分布式鎖 setnx key value設定鍵的值,僅當鍵不存在時 redis官方文件setnx key value 將 key 的值設為 value 當且僅當 key 不存在。若給定的 key 已經存在,則set...