溫馨提示×

溫馨提示×

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

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

怎么使用Redis鎖定資源

發(fā)布時間:2022-01-15 15:41:10 來源:億速云 閱讀:125 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹了怎么使用Redis鎖定資源的相關(guān)知識,內(nèi)容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇怎么使用Redis鎖定資源文章都會有所收獲,下面我們一起來看看吧。

一、概述

在這個技術(shù)不斷更新迭代的情況下,分布式這個概念,在企業(yè)中的權(quán)重越來越高!談及分布式時,不可避免一定會提到分布式鎖,現(xiàn)階段分布式鎖的實現(xiàn)方式主流的有三種實現(xiàn)方式, ZookeeperDB、Redis,我們本篇文章以Redis為例!

從我們的角度來看,這三個屬性是有效使用分布式鎖所需的最低保證。

  1. 安全特性:互斥。在任何給定時刻,只有一個客戶端可以持有鎖。
  2. 活力屬性:無死鎖。最終,即使鎖定資源的客戶端崩潰或分區(qū),也始終可以獲得鎖。
  3. 活動性:容錯能力。只要大多數(shù)Redis節(jié)點都處于運行狀態(tài),客戶端就可以獲取和釋放鎖。

二、redis多節(jié)點實現(xiàn)分布式鎖帶來的挑戰(zhàn)

我們使用Redis鎖定資源的最簡單方法是:

  1. 在實例中創(chuàng)建鎖。
  2. 鎖通常使用Redis過期功能在有限時間存在,因此最終將被釋放,最終超過給定期限會被刪除。
  3. 當客戶端需要釋放資源時,它將刪除鎖。

乍一看,似乎并沒有什么問題。但是不妨我們深究一下,這種實現(xiàn)方案在redis單機環(huán)境下似乎并沒有什么問題!但是如果節(jié)點宕了呢?好吧,那么讓我們添加一個slave節(jié)點!如果主服務器宕機了,就使用這個節(jié)點!但是我們不妨來看看她真的能保證可用嗎?

在談論這個的致命缺陷時,我們需要了解一個知識點,Redis復制是異步的。

  1. 客戶端A獲取主服務器中的鎖。
  2. 在將鎖復制傳輸?shù)綇臋C之前,主機崩潰。
  3. slave晉升為      master。
  4. 客戶端B獲取鎖,因為從機并沒有該鎖的對象,獲取成功!

顯然,這樣是不對的,主節(jié)點因為沒來得及同步數(shù)據(jù)就宕機了,所以從節(jié)點沒有該數(shù)據(jù),從而造成分布式鎖的失效,那么作者antirez的觀點是如何解決這個呢?

三、Redlock算法

作者認為,我們應該使用多個Redis,這些節(jié)點是完全獨立的,不需要使用復制或者任何協(xié)調(diào)數(shù)據(jù)的系統(tǒng),多個redis系統(tǒng)獲取鎖的過程就變成了如下步驟:

  1. 以毫秒為單位獲取當前的服務器時間
  2. 嘗試使用相同的key和隨機值來獲取鎖,對每一個機器獲取鎖時都應該有一個超時時間,比如鎖的過期時間為10s那么獲取單個節(jié)點鎖的超時時間就應該為5到50毫秒左右,他這樣做的目的是為了保證客戶端與故障的機器連接,耗費多余的時間!超時間時間內(nèi)未獲取數(shù)據(jù)就放棄該節(jié)點,從而去下一個節(jié)點獲取,直至將所有節(jié)點全部獲取一遍!
  3. 獲取完成后,獲取當前時間減去步驟一獲取的時間,當且僅當客戶端半數(shù)以上獲取成功且獲取鎖的時間小于鎖額超時時間,則證明該鎖生效!
  4. 獲取鎖之后,鎖的超時時間等于      設置的有效時間-獲取鎖花費的時間
  5. 如果 獲取鎖的機器不滿足半數(shù)以上,或者鎖的超時時間計算完畢后為負數(shù) 等異常操作,則系統(tǒng)會嘗試解鎖所有實例,即使有些實例沒有獲取鎖成功,依舊會被嘗試解鎖!
  6. 釋放鎖,只需在所有實例中釋放鎖,無論客戶端是否認為它能夠成功鎖定給定的實例。

四、但是Redlock真能夠解決問題嗎?

Martin Kleppmann發(fā)表文章任務,Redlock并不能保證該鎖的安全性!

他認為鎖的用途無非兩種

  1. 提升效率,用鎖來保證一個任務沒有必要被執(zhí)行兩次。比如(很昂貴的計算)
  2. 保證正確,使用鎖來保證任務按照正常的步驟執(zhí)行,防止兩個節(jié)點同時操作一份數(shù)據(jù),造成文件沖突,數(shù)據(jù)丟失。

對于第一種原因,我們對鎖是有一定寬容度的,就算發(fā)生了兩個節(jié)點同時工作,對系統(tǒng)的影響也僅僅是多付出了一些計算的成本,沒什么額外的影響。這個時候 使用單點的 Redis 就能很好的解決問題,沒有必要使用RedLock,維護那么多的Redis實例,提升系統(tǒng)的維護成本。

1.分布式鎖的超時性,所帶來的缺點

但是對于第二種場景來說,就比較慎重了,因為很可能涉及到一些金錢交易,如果鎖定失敗,并且兩個節(jié)點同時處理同一數(shù)據(jù),則結(jié)果將導致文件損壞,數(shù)據(jù)丟失,永久性不一致,或者金錢方面的損失!

我們假設一種場景,我們有兩個客戶端,每一個客戶端必須拿到鎖之后才能去保存數(shù)據(jù)到數(shù)據(jù)庫,我們使用RedLock算法實現(xiàn)會出現(xiàn)什么問題呢?RedLock中,為了防止死鎖,鎖是具有過期時間的,但是Martin 認為這是不安全的!該流程圖類似于這樣!

怎么使用Redis鎖定資源  

客戶端1獲取到鎖成功后,開始執(zhí)行,執(zhí)行到一半系統(tǒng)發(fā)生Full GC ,系統(tǒng)服務被掛起,過段時間鎖超時了。

客戶端2等待客戶端1的鎖超時后,成功的獲取到鎖,開始執(zhí)行入庫操作,完成后,客戶端1完成了Full GC,又做了一次入庫操作!這是不安全的!如何解決呢?

Martin 提出來一種類似樂觀鎖的實現(xiàn)機制,示例圖如下:

怎么使用Redis鎖定資源  

客戶端1長時間被掛起后,客戶端2獲取到鎖,開始寫庫操作,同時攜帶令牌 34,寫庫完成后,客戶端1蘇醒,開始進行入庫操作,但是因為攜帶的令牌為33 小于最新令牌,該次提交就被拒絕!

這個想法聽起來似乎時很完備的思路,這樣即使系統(tǒng)因為某些原因被掛起,數(shù)據(jù)也能夠被正確的處理。但是仔細想一下:

  • 如果僅當您的令牌大于所有過去的令牌時,數(shù)據(jù)存儲區(qū)才能始終接受寫入,則它是可線性化的存儲區(qū),相當與使用數(shù)據(jù)庫來實現(xiàn)一個 分布式鎖系統(tǒng),那么RedLock的作用就變的微乎其微!甚至不在需要使用redis保證分布式鎖! 

2.RedLock對于系統(tǒng)時鐘強依賴

回想一下Redlock算法獲取鎖的幾個步驟,你會發(fā)現(xiàn)鎖的有效性是與當前的系統(tǒng)時鐘強依賴,我們假設:

我們有,A B C D E 五個redis節(jié)點:

  1. 客戶端1獲取節(jié)點A,B,C的鎖定。由于網(wǎng)絡問題,無法訪問D和E。
  2. 節(jié)點C上的時鐘向前跳,導致鎖過期。
  3. 客戶端2獲取節(jié)點C,D,E的鎖定。由于網(wǎng)絡問題,無法訪問A和B。
  4. 現(xiàn)在,客戶1和2都認為他們持有該鎖。

如果C在將鎖持久保存到磁盤之前崩潰并立即重新啟動,則可能會發(fā)生類似的問題。

Martin認為系統(tǒng)時間的階躍主要來自兩個方面(以及作者給出的解決方案):

  1. 人為修改。
    • 對于人為修改,能說啥呢?人要搞破壞沒辦法避免。
  2. 從NTP服務收到了一個跳躍時時鐘更新。
    • NTP受到一個階躍時鐘更新,對于這個問題,需要通過運維來保證。需要將階躍的時間更新到服務器的時候,應當采取小步快跑的方式。多次修改,每次更新時間盡量小。

3.基于程序語言彌補分布式鎖的超時性所帶來的缺點

我們回顧 1 觀點,深究抽象出現(xiàn)這個缺陷的根本原因,就是為了解決由于系統(tǒng)宕機帶來的鎖失效而給鎖強加了一個失效時間,異常情況下,程序(業(yè)務)執(zhí)行的時間大于鎖失效時間從而造成的一系列的問題,我們能否從這方面去考慮,從而用程序來解決這個樣一個死局 呢?

既然是因為鎖的失效時間小于業(yè)務時間,那么我們想辦法保證業(yè)務程序執(zhí)行時間絕對小于鎖超時時間不久解決了?

java語言中redisson實現(xiàn)了一種保證鎖失效時間絕對大于業(yè)務程序執(zhí)行時間的機制。官方叫做看門狗機制(Watchdog),他的主要原理是,在程序成功獲取鎖之后,會fork一條子線程去不斷的給該鎖續(xù)期,直至該鎖釋放為止!他的原理圖大概如下所示:

怎么使用Redis鎖定資源  

redisson使用守護線程來進行鎖的續(xù)期,(守護線程的作用:當主線程銷毀,會和主線程一起銷毀。)防止程序宕機后,線程依舊不斷續(xù)命,造成死鎖!

另外,Redisson還實現(xiàn)并且優(yōu)化了 RedLock算法、公平鎖、可重入鎖、連鎖等操作,使Redis分布式鎖的實現(xiàn)方式更加簡便高效!

關(guān)于“怎么使用Redis鎖定資源”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“怎么使用Redis鎖定資源”知識都有一定的了解,大家如果還想學習更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

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

AI