亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Redis中Redlock的示例分析

發布時間:2022-01-20 11:00:10 來源:億速云 閱讀:276 作者:小新 欄目:關系型數據庫

這篇文章主要介紹了Redis中Redlock的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

為什么要用鎖

我待過的一家k12教育公司,我們當時有個業務場景是這樣的。業務這邊要給學生排課,偶爾會反饋學生的課時明明充足的但是卻提示課時不足,等再刷新一遍頁面卻發現學生的課時已經不夠了。更可怕的是,偶爾會有學生的課時被扣成負數(公司被白嫖課時)。

再比如下面這個例子

Redis中Redlock的示例分析

上面的這倆個問題都是并發給我們的業務帶來的問題。解決這個問題的核心就是,同一時間只能允許有一個請求來對這些敏感(重要)的數據進行讀寫操作。所以這個時候就要使用到分布式鎖來限制程序的并發執行。

setnx有哪些問題

我們先來看看用Redis如何實現分布式鎖,想必大家都很熟悉。比如針對我文章開頭講的學生排課的問題我們就可以這樣加鎖

Redis中Redlock的示例分析

這就是我們常規使用setnx來實現鎖的方式。

現在我們假設有這樣一個場景。A請求拿到鎖到了第2步給學生排課的時候程序掛了,沒有釋放鎖。那么這個鎖就成了死鎖,下一個操作同一個學生的請求永遠就拿不到鎖,那么這個學生就沒法被排課了。這個時候都需要手動去把鎖釋放掉。

為了解決死鎖的問題,我們給鎖加一個過期時間。

Redis中Redlock的示例分析

加上過期時間之后,如果A請求沒有主動釋放鎖,在鎖過期之后也會主動釋放,這樣B請求一樣可以獲取鎖處理業務邏輯。但是如果在加過期時間的時候也就是在第1步和第2步之間程序崩潰。那還是會出現死鎖的問題。這個問題的根源就在于setnx和expire這兩條指令不是原子指令。所以如果setnx和expire能夠要么全部執行要么一個都不執行那該多好。

為此在Redis2.8之前社區涌現了一大批擴展包來解決該問題。官方為了治理該亂象,在2.8版本中加入了set指令的擴展參數使得setnx和expire指令可以一起執行,所以現在我們使用分布式鎖應該是這樣了

Redis中Redlock的示例分析

這樣看起來已經很完美了,已經達成了我們的期望“setnx和expire能夠要么全部執行要么一個都不執行那該多好”。我們再假設現在有如下場景:

A請求現在獲取到了鎖,鎖的超時時間設置的是5秒。到了第2步執行業務邏輯,結果因為某些原因5秒之后業務邏輯還沒有執行完,此時鎖由于超時自動釋放了。這個時候B請求也來了,拿到鎖之后開始執行業務邏輯。A請求這個時候業務邏輯執行完了,開始執行第三步,釋放了鎖。而這個時候鎖是B請求拿到的,結果被A請求釋放了。那么C請求就可以拿到鎖了。這個時候B請求和C請求就會導致并發問題了。所以可以從這個例子看出來,在分布式鎖中過期時間的設置非常重要,如果設置的時間小于這個接口的響應時間那么仍然會產生并發問題。所以我們可以參考接口響應時長的監控來設置鎖的過期時間。

Redlock

我們上述的方案都是基于單點的Redis的實現方式。單點的Redis實現分布式鎖基本上可以滿足95%的業務場景。剩下的5%就是對數據一致性要求極其嚴苛并且對于鎖丟失的0容忍的業務場景。這個時候就得考慮Redlock了。至于單點的Redis即使通過sentinel保證高可用,如果這個master節點由于某些原因發生了主從切換,如果數據主從數據同步不及時那么勢必會有數據丟失,那么就會出現鎖丟失的情況。

假設存在多個Redis實例,這些節點是完全獨立的,不需要使用復制或者任何協調數據的系統,我們假設有5個Redis master節點,客戶端為了取到鎖,步驟將會變成這樣:

  • 以毫秒為單位獲取當前的服務器時間

  • 嘗試使用相同的key和隨機值來獲取鎖,客戶端對每一個機器獲取鎖時都應該有一個超時時間,比如鎖的過期時間為10s,那么獲取單個節點鎖的超時時間就應該為5到50毫秒左右,他這樣做的目的是為了保證客戶端與故障的機器連接不耗費多余的時間!超時間時間內未獲取數據就放棄該節點,從而去下一個Redis節點獲取。

  • 獲取完成后,獲取當前時間減去步驟一獲取的時間,當且僅當客戶端從半數以上(這里是3個節點)的Redis節點獲取到鎖且獲取鎖的時間小于鎖額超時時間,則證明該鎖生效!

  • 如果取到了鎖,key的真正有效時間等于有效時間減去獲取鎖所使用的時間(步驟3計算的結果)。

  • 如果獲取鎖的機器不滿足半數以上,或者鎖的超時時間計算完畢后為負數等異常操作,則系統會嘗試解鎖所有實例,即便某些Redis實例根本就沒有加鎖成功,防止某些節點獲取到鎖但是客戶端沒有得到響應而導致接下來的一段時間不能被重新獲取鎖

所以我們看出,redlock其實是比單點Redis看起來更加可靠的鎖。

如果你跟我一樣是Node.js程序員那么正好有第三方庫redlock直接使用。

我們真的需要redlock嗎

關于redlock其實也有另外一種聲音,Martin Kleppmann(劍橋大學的研究員,從事數據庫、分布式系統和信息安全交叉領域的TRVE DATA項目)寫過一篇blog發表了關于對redlock的一些看法,感興趣的可以看看。Redis作者Salvatore也對這篇文章的疑問做出了一些回應,還挺有意思的。作者的blog主要的觀點如下:

分布式鎖的用途無非兩種:

  • 效率:使用鎖可以避免不必要地做同樣的工作兩次(例如一些昂貴的計算)。如果鎖定失敗并且兩個節點最終完成相同的工作,結果是成本略有增加(您最終向 AWS 支付的費用比其他情況多 5 美分)或帶來輕微的不便(例如,用戶最終兩次收到相同的電子郵件通知)。

  • 正確性:使用鎖可以防止并發進程相互干擾并破壞系統狀態。如果鎖定失敗并且兩個節點同時處理同一條數據,則結果是文件損壞、數據丟失、永久性不一致、給患者服用的藥物劑量錯誤或其他一些非常嚴重的問題。

如果是為了效率,則根本沒有必要承擔 Redlock 的成本和復雜性,鎖丟失導致多發幾次郵件和運行 5 個 Redis 服務器的成本相比,最好只使用單個 Redis 實例。如果你使用的是單個 Redis 實例,Redis 節點突然斷電或者崩潰,或者出現其他問題,這個時候當然會丟失鎖。但是如果你只是將鎖用作效率優化,而且這種崩潰不會經常發生,那沒什么大不了的。這種“沒什么大不了”的場景是 也恰好是Redis優秀的地方。至少如果依賴單個 Redis 實例,那么查看系統的每個人都能夠更方便的定位問題。

如果是為了正確性,那么嚴格來講,redlock根本不具有強一致的嚴格性。舉了一些例子

  • 時序和系統時鐘做出了危險的假設,對每臺服務器的時鐘強依賴。因為有系統有GC的存在,做GC的時整個服務器是夯住的,時間也就停滯了,所以我們不能夠對時鐘有強依賴。

  • 沒有令牌。客戶端每次獲取鎖的時候服務端沒有下發令牌,服務端應該校驗每次操作的時候客戶端的令牌要與服務端當前的令牌一致才難操作鎖。

感謝你能夠認真閱讀完這篇文章,希望小編分享的“Redis中Redlock的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

东辽县| 蒙阴县| 西林县| 邹城市| 甘南县| 吴江市| 建阳市| 永济市| 清河县| 灵武市| 大厂| 松潘县| 明光市| 安多县| 郎溪县| 云南省| 铁岭县| 吉安市| 来安县| 沈丘县| 樟树市| 北票市| 平和县| 抚顺市| 额尔古纳市| 图们市| 鸡东县| 于田县| 洛扎县| 南靖县| 临潭县| 文昌市| 鄂尔多斯市| 宣武区| 中方县| 安远县| 府谷县| 卢湾区| 敦煌市| 阜城县| 扶沟县|