利用中秋節時間補一下redis分散式鎖的知識,在B站上看到程式設計師諸葛老師講的《Redisson實現Redis分散式鎖以及Redlock分散式鎖》課程感覺不錯。
超賣問題,應該是97 但是三個執行緒執行完之後依舊是99
問題:公司一般兩臺機器或者多臺機器,多點
模擬場景
Jmeter使用 springBoot啟動兩個機器,改一下埠
併發量越高,出現“超賣”的機率越大。在分散式環境下,產生的鎖是鎖不住的,不同的請求發到nginx上,幫忙做負載均衡,如果兩個請求均勻地分發到不同的Tomcat去,生出來的鎖只在JVM程序內有效, 在同一個Tomcat內有效,沒辦法跨tomcat控制的。
入門級分散式鎖的實現
注:redis單執行緒
拋異常導致請求死鎖
宕機
宕機,redis鎖還存在,其他機器請求時候
原子執行,不可分割,
請求執行時間很長,
假設請求時間比較長,執行15s,假設請求質控relStock時,過去了10s,這把鎖被redis 清理掉了,
意味這什麼呢?高併發場景,外面不斷有請求過來訪問介面
第2個請求就可以加鎖成功,因為第一個請求的鎖被redis清除掉了,假設新來的請求執行時間為8s
第1個請求此時執行了10s,再執行5s,刪除之前的key,會刪除第二個執行緒的key,刪鎖操作
超高併發過程中,之前加的鎖可能永久失效,只要高併發存在,鎖會永久失效,問題會被放大,秒殺場景,商家會虧死
問題本質
自己加的鎖,被其他執行緒刪除
開源框架解決
redis原始碼分析
lua具有原子性,當做一條命令執行
從cap角度剖析redis&zookeeper鎖架構
redis很少單機版,至少主從 哨兵 叢集如果redis是多節點情況下,會不會出現什麼問題?若redis是主從、哨兵模式還是會有問題的。
加鎖之後,redis底層設定key,redis預設情況下是非同步同步,主節點寫之後,非同步同步從節點,主要如果主節點key寫成功之後,馬上返回客戶端,鎖加成功了,redis主節點開始同步從節點,假設剛開始同步從節點,主節點掛掉了怎麼辦?
CAP原則:redis叢集滿足AP架構
zk滿足CP架構(ZAB協議):加鎖向主節點寫,不會立刻向客戶端返回加鎖成功的結果,而是先向從節點同步,同步成功之後,才告訴客戶端加鎖成功了,有延遲,犧牲了一點可用性,達到一致性。即使叢集掛掉,對外也是不可用,也要達到資料一致性。
萬一主節點掛掉,從從節點選舉出新的主節點
對併發要求比較高,建議選擇redis,即使出現redis主從架構失效問題,出現機率不大,可以人工補償措施,寫指令碼補償。
Redlock 不推薦使用,使用zk
需要很多機器加鎖成功,才能算成功,效能會受影響,也存在鎖回滾情況。