溫馨提示×

溫馨提示×

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

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

Redis中怎么提高分布式鎖的可用性

發(fā)布時間:2021-08-10 15:29:39 來源:億速云 閱讀:98 作者:Leah 欄目:大數(shù)據(jù)

Redis中怎么提高分布式鎖的可用性,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

Redis分布式鎖簡介

redis給我們提供了分布式鎖,開啟鎖的指令是setnx(set if not exists),釋放鎖指令del,下面我們來嘗試

> setnx lookname mango(integer) 1> get lookname"mango"> del lookname(integer) 1> get mango(nil)
死鎖

這里我們思考一個問題,如果我們在執(zhí)行邏輯的時候出現(xiàn)異常了,那么這個鎖就會一直得不到釋放,導致死鎖,所以我們想辦法讓它自己釋放,添加一個過期時間這個指令是expire key seconds,即使我們不del,他它過了這個時間會自動釋放

> setnx lookname mango(integer) 1> expire lookname 5(integer) 1> get lookname(nil)

還有一個問題,如果我在執(zhí)行setnx和expire的過程中出現(xiàn)了異常怎么辦?我們很快想到了用事務,但是我們這里注意expire依賴setnx,expire這個是當setnx搶到了資源的時候我們的expire才會執(zhí)行,否則是執(zhí)行不成功的,事務里面沒有if else語句。

為了解決這個問題,redis開源社區(qū)開發(fā)出很多分布式鎖的lib庫,也就是說我們每次使用分布式鎖的時候都要引入這個第三方的庫,關于這個問題作者在Redis2.8版本中加入了set擴展,把這兩個命令放在一起執(zhí)行。

> set lookname mango ex 5 nxOK> get lookname"mango"> get lookname    # 5s 后(nil)
超時問題  

如果我們在加鎖后到這個鎖被釋放的時間內(nèi)的業(yè)務邏輯還沒有執(zhí)行完,那么這個時候出現(xiàn)了新的問題就是超時,比如說我只想的邏輯需要30秒,而我的鎖過期時間只有10秒,此時我的邏輯還沒有處理完,問題就來了。

不使用過期時間

解決超時問題的快捷辦法就是不使用過期時間,我們需要在key后面添加一個比較隱私的隨機數(shù),例如name1564835、name6879425,達到減少key的碰撞,我們對這個key做上標記,等執(zhí)行邏輯處理完后程序回收這個內(nèi)存。

延遲回收

如果10秒鐘不夠那么我們可以給這個key延長回收時間,我們在key回收前判斷客戶端是否還在使用這個key,如果沒有使用這個key我們就什么都不做,如果在使用,我們就增加回收時長,如何做?我們可以在調(diào)用端重開一個線程,監(jiān)測快過期的key,客戶端可以給redis服務實例發(fā)送一個Lua腳本檢測這個key的值有沒有改變,如果沒有改變讓redis服務端延長鎖的時間。

RedLock算法

我們在一個集群中,當主節(jié)點掛掉時,從節(jié)點會取而代之,原先第一個客戶端在主節(jié)點中申請成功了一把鎖,但是這把鎖還沒有來得及同步到從節(jié)點,主節(jié)點突然掛掉了,然后從節(jié)點變成了主節(jié)點這個新的節(jié)點內(nèi)部沒有這個鎖,所以當另一個客戶端過來請求加鎖時,此時兩個客戶端都持有這個資源,問題又出現(xiàn)了。

但是這個問題是極小概率事件并且是非常短時間造成的,從分布式系統(tǒng)角度上我們是可以容忍這個問題的。但是我們希望redis完全不受影響,可以考慮 redlock。Redlock算法是由Antirez發(fā)明的,它的流程比較復雜,不過已經(jīng)有了很多開源的 library 做了良好的封裝,用戶可以拿來即用,比如 redlock-py。

redlock.Redlock()

RedLock算法原理:

1.獲取當前時間(單位是毫秒)。

2.輪流用相同的key和隨機值在N個節(jié)點上請求鎖,在這一步里,客戶端在每個master上請求鎖時,會有一個和總的鎖釋放時間相比小的多的超時時間。比如如果鎖自動釋放時間是10秒鐘,那每個節(jié)點鎖請求的超時時間可能是5-50毫秒的范圍,這個可以防止一個客戶端在某個宕掉的master節(jié)點上阻塞過長時間,如果一個master節(jié)點不可用了,我們應該盡快嘗試下一個master節(jié)點。

3.客戶端計算第二步中獲取鎖所花的時間,只有當客戶端在大多數(shù)master節(jié)點上成功獲取了鎖((N/2) +1),而且總共消耗的時間不超過鎖釋放時間,這個鎖就認為是獲取成功了。

4.如果鎖獲取成功了,那現(xiàn)在鎖自動釋放時間就是最初的鎖釋放時間減去之前獲取鎖所消耗的時間。

5.如果鎖獲取失敗了,不管是因為獲取成功的鎖不超過一半(N/2+1)還是因為總消耗時間超過了鎖釋放時間,客戶端都會到每個master節(jié)點上釋放鎖,即便是那些他認為沒有獲取成功的鎖。

注意:加鎖時,它會向過半節(jié)點發(fā)送 set(key, value, nx=True, ex=xxx) 指令,只要過半節(jié)點 set 成功,那就認為加鎖成功。釋放鎖時,需要向所有節(jié)點發(fā)送 del 指令。不過 Redlock 算法還需要考慮出錯重試、時鐘漂移等很多細節(jié)問題,同時因為 Redlock 需要向多個節(jié)點進行讀寫,意味著相比單實例 Redis性能會下降一些,代碼額外引入第三方lib。

關于Redis中怎么提高分布式鎖的可用性問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業(yè)資訊頻道了解更多相關知識。

向AI問一下細節(jié)

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

AI