您好,登錄后才能下訂單哦!
Redis中怎么提高分布式鎖的可用性,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
redis給我們提供了分布式鎖,開啟鎖的指令是setnx(set if not exists),釋放鎖指令del,下面我們來嘗試
> setnx lookname mango(integer) 1> get lookname"mango"> del lookname(integer) 1> get mango(nil)
這里我們思考一個問題,如果我們在執行邏輯的時候出現異常了,那么這個鎖就會一直得不到釋放,導致死鎖,所以我們想辦法讓它自己釋放,添加一個過期時間這個指令是expire key seconds,即使我們不del,他它過了這個時間會自動釋放
> setnx lookname mango(integer) 1> expire lookname 5(integer) 1> get lookname(nil)
還有一個問題,如果我在執行setnx和expire的過程中出現了異常怎么辦?我們很快想到了用事務,但是我們這里注意expire依賴setnx,expire這個是當setnx搶到了資源的時候我們的expire才會執行,否則是執行不成功的,事務里面沒有if else語句。
為了解決這個問題,redis開源社區開發出很多分布式鎖的lib庫,也就是說我們每次使用分布式鎖的時候都要引入這個第三方的庫,關于這個問題作者在Redis2.8版本中加入了set擴展,把這兩個命令放在一起執行。
> set lookname mango ex 5 nxOK> get lookname"mango"> get lookname # 5s 后(nil)
如果我們在加鎖后到這個鎖被釋放的時間內的業務邏輯還沒有執行完,那么這個時候出現了新的問題就是超時,比如說我只想的邏輯需要30秒,而我的鎖過期時間只有10秒,此時我的邏輯還沒有處理完,問題就來了。
不使用過期時間
解決超時問題的快捷辦法就是不使用過期時間,我們需要在key后面添加一個比較隱私的隨機數,例如name1564835、name6879425,達到減少key的碰撞,我們對這個key做上標記,等執行邏輯處理完后程序回收這個內存。
延遲回收
如果10秒鐘不夠那么我們可以給這個key延長回收時間,我們在key回收前判斷客戶端是否還在使用這個key,如果沒有使用這個key我們就什么都不做,如果在使用,我們就增加回收時長,如何做?我們可以在調用端重開一個線程,監測快過期的key,客戶端可以給redis服務實例發送一個Lua腳本檢測這個key的值有沒有改變,如果沒有改變讓redis服務端延長鎖的時間。
RedLock算法
我們在一個集群中,當主節點掛掉時,從節點會取而代之,原先第一個客戶端在主節點中申請成功了一把鎖,但是這把鎖還沒有來得及同步到從節點,主節點突然掛掉了,然后從節點變成了主節點這個新的節點內部沒有這個鎖,所以當另一個客戶端過來請求加鎖時,此時兩個客戶端都持有這個資源,問題又出現了。
但是這個問題是極小概率事件并且是非常短時間造成的,從分布式系統角度上我們是可以容忍這個問題的。但是我們希望redis完全不受影響,可以考慮 redlock。Redlock算法是由Antirez發明的,它的流程比較復雜,不過已經有了很多開源的 library 做了良好的封裝,用戶可以拿來即用,比如 redlock-py。
redlock.Redlock()
RedLock算法原理:
1.獲取當前時間(單位是毫秒)。
2.輪流用相同的key和隨機值在N個節點上請求鎖,在這一步里,客戶端在每個master上請求鎖時,會有一個和總的鎖釋放時間相比小的多的超時時間。比如如果鎖自動釋放時間是10秒鐘,那每個節點鎖請求的超時時間可能是5-50毫秒的范圍,這個可以防止一個客戶端在某個宕掉的master節點上阻塞過長時間,如果一個master節點不可用了,我們應該盡快嘗試下一個master節點。
3.客戶端計算第二步中獲取鎖所花的時間,只有當客戶端在大多數master節點上成功獲取了鎖((N/2) +1),而且總共消耗的時間不超過鎖釋放時間,這個鎖就認為是獲取成功了。
4.如果鎖獲取成功了,那現在鎖自動釋放時間就是最初的鎖釋放時間減去之前獲取鎖所消耗的時間。
5.如果鎖獲取失敗了,不管是因為獲取成功的鎖不超過一半(N/2+1)還是因為總消耗時間超過了鎖釋放時間,客戶端都會到每個master節點上釋放鎖,即便是那些他認為沒有獲取成功的鎖。
注意:加鎖時,它會向過半節點發送 set(key, value, nx=True, ex=xxx) 指令,只要過半節點 set 成功,那就認為加鎖成功。釋放鎖時,需要向所有節點發送 del 指令。不過 Redlock 算法還需要考慮出錯重試、時鐘漂移等很多細節問題,同時因為 Redlock 需要向多個節點進行讀寫,意味著相比單實例 Redis性能會下降一些,代碼額外引入第三方lib。
關于Redis中怎么提高分布式鎖的可用性問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。