最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Redis如何實(shí)現(xiàn)分布式鎖

 更新時間:2023年10月09日 10:11:36   作者:下次一定少寫B(tài)UG  
這篇文章主要介紹了Redis如何實(shí)現(xiàn)分布式鎖問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

Redis實(shí)現(xiàn)分布式鎖

分布式鎖是用于分布式環(huán)境下并發(fā)控制的一種機(jī)制,用于控制某個資源在同一時刻只能被一個應(yīng)用所使用。

如下圖所示:

Redis 本身可以被多個客戶端共享訪問,正好就是一個共享存儲系統(tǒng),可以用來保存分布式鎖,而且 Redis 的讀寫性能高,可以應(yīng)對高并發(fā)的鎖操作場景。

Redis 的 SET 命令有個 NX 參數(shù)可以實(shí)現(xiàn)「key不存在才插入」,所以可以用它來實(shí)現(xiàn)分布式鎖:

  • 如果 key 不存在,則顯示插入成功,可以用來表示加鎖成功;
  • 如果 key 存在,則會顯示插入失敗,可以用來表示加鎖失敗。

基于 Redis 節(jié)點(diǎn)實(shí)現(xiàn)分布式鎖時,對于加鎖操作,我們需要滿足三個條件。

  • 加鎖包括了讀取鎖變量、檢查鎖變量值和設(shè)置鎖變量值三個操作,但需要以原子操作的方式完成,所以,我們使用 SET 命令帶上 NX 選項(xiàng)來實(shí)現(xiàn)加鎖;
  • 鎖變量需要設(shè)置過期時間,以免客戶端拿到鎖后發(fā)生異常,導(dǎo)致鎖一直無法釋放,所以,我們在 SET 命令執(zhí)行時加上 EX/PX 選項(xiàng),設(shè)置其過期時間;
  • 鎖變量的值需要能區(qū)分來自不同客戶端的加鎖操作,以免在釋放鎖時,出現(xiàn)誤釋放操作,所以,我們使用 SET 命令設(shè)置鎖變量值時,每個客戶端設(shè)置的值是一個唯一值,用于標(biāo)識客戶端;

滿足這三個條件的分布式命令

如下:

SET lock_key unique_value NX PX 10000
  • lock_key 就是 key 鍵;
  • unique_value 是客戶端生成的唯一的標(biāo)識,區(qū)分來自不同客戶端的鎖操作;
  • NX 代表只在 lock_key 不存在時,才對 lock_key 進(jìn)行設(shè)置操作;
  • PX 10000 表示設(shè)置 lock_key 的過期時間為 10s,這是為了避免客戶端發(fā)生異常而無法釋放鎖。

而解鎖的過程就是將 lock_key 鍵刪除(del lock_key),但不能亂刪,要保證執(zhí)行操作的客戶端就是加鎖的客戶端。

所以,解鎖的時候,我們要先判斷鎖的 unique_value 是否為加鎖客戶端,是的話,才將 lock_key 鍵刪除。

可以看到,解鎖是有兩個操作,這時就需要 Lua 腳本來保證解鎖的原子性,因?yàn)?Redis 在執(zhí)行 Lua 腳本時,可以以原子性的方式執(zhí)行,保證了鎖釋放操作的原子性。

// 釋放鎖時,先比較 unique_value 是否相等,避免鎖的誤釋放
if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

這樣一來,就通過使用 SET 命令和 Lua 腳本在 Redis 單節(jié)點(diǎn)上完成了分布式鎖的加鎖和解鎖。

基于Redis 實(shí)現(xiàn)分布式鎖有什么優(yōu)缺點(diǎn)?

Redis 實(shí)現(xiàn)分布式鎖的 優(yōu)點(diǎn)

  • 性能高效(這是選擇緩存實(shí)現(xiàn)分布式鎖最核心的出發(fā)點(diǎn))。
  • 實(shí)現(xiàn)方便。很多研發(fā)工程師選擇使用 Redis 來實(shí)現(xiàn)分布式鎖,很大成分上是因?yàn)?Redis 提供了 setnx 方法,實(shí)現(xiàn)分布式鎖很方便。
  • 避免單點(diǎn)故障(因?yàn)?Redis 是跨集群部署的,自然就避免了單點(diǎn)故障)。

Redis 實(shí)現(xiàn)分布式鎖的 缺點(diǎn)

  • 超時時間不好設(shè)置。如果鎖的超時時間設(shè)置過長,會影響性能,如果設(shè)置的超時時間過短會保護(hù)不到共享資源。比如在有些場景中,一個線程 A 獲取到了鎖之后,由于業(yè)務(wù)代碼執(zhí)行時間可能比較長,導(dǎo)致超過了鎖的超時時間,自動失效,注意 A 線程沒執(zhí)行完,后續(xù)線程 B 又意外的持有了鎖,意味著可以操作共享資源,那么兩個線程之間的共享資源就沒辦法進(jìn)行保護(hù)了。
  • 那么如何合理設(shè)置超時時間呢? 我們可以基于續(xù)約的方式設(shè)置超時時間:先給鎖設(shè)置一個超時時間,然后啟動一個守護(hù)線程,讓守護(hù)線程在一段時間后,重新設(shè)置這個鎖的超時時間。實(shí)現(xiàn)方式就是:寫一個守護(hù)線程,然后去判斷鎖的情況,當(dāng)鎖快失效的時候,再次進(jìn)行續(xù)約加鎖,當(dāng)主線程執(zhí)行完成后,銷毀續(xù)約鎖即可,不過這種方式實(shí)現(xiàn)起來相對復(fù)雜。
  • Redis 主從復(fù)制模式中的數(shù)據(jù)是異步復(fù)制的,這樣導(dǎo)致分布式鎖的不可靠性。如果在 Redis 主節(jié)點(diǎn)獲取到鎖后,在沒有同步到其他節(jié)點(diǎn)時,Redis 主節(jié)點(diǎn)宕機(jī)了,此時新的 Redis 主節(jié)點(diǎn)依然可以獲取鎖,所以多個應(yīng)用服務(wù)就可以同時獲取到鎖。

Redis如何解決集群情況下分布式鎖的可靠性?

為了保證集群環(huán)境下分布式鎖的可靠性,Redis 官方已經(jīng)設(shè)計了一個分布式鎖算法 Redlock(紅鎖)。

它是基于多個 Redis 節(jié)點(diǎn)的分布式鎖,即使有節(jié)點(diǎn)發(fā)生了故障,鎖變量仍然是存在的,客戶端還是可以完成鎖操作。

官方推薦是至少部署 5 個 Redis 節(jié)點(diǎn),而且都是主節(jié)點(diǎn),它們之間沒有任何關(guān)系,都是一個個孤立的節(jié)點(diǎn)。

Redlock 算法的基本思路,是讓客戶端和多個獨(dú)立的 Redis 節(jié)點(diǎn)依次請求申請加鎖,如果客戶端能夠和半數(shù)以上的節(jié)點(diǎn)成功地完成加鎖操作,那么我們就認(rèn)為,客戶端成功地獲得分布式鎖,否則加鎖失敗。

這樣一來,即使有某個 Redis 節(jié)點(diǎn)發(fā)生故障,因?yàn)殒i的數(shù)據(jù)在其他節(jié)點(diǎn)上也有保存,所以客戶端仍然可以正常地進(jìn)行鎖操作,鎖的數(shù)據(jù)也不會丟失。

Redlock算法加鎖三個過程

第一步是,客戶端獲取當(dāng)前時間(t1)。

第二步是,客戶端按順序依次向 N 個 Redis 節(jié)點(diǎn)執(zhí)行加鎖操作:

  • 加鎖操作使用 SET 命令,帶上 NX,EX/PX 選項(xiàng),以及帶上客戶端的唯一標(biāo)識。
  • 如果某個 Redis 節(jié)點(diǎn)發(fā)生故障了,為了保證在這種情況下,Redlock 算法能夠繼續(xù)運(yùn)行,我們需要給「加鎖操作」設(shè)置一個超時時間(不是對「鎖」設(shè)置超時時間,而是對「加鎖操作」設(shè)置超時時間),加鎖操作的超時時間需要遠(yuǎn)遠(yuǎn)地小于鎖的過期時間,一般也就是設(shè)置為幾十毫秒。

第三步是,一旦客戶端從超過半數(shù)(大于等于 N/2+1)的 Redis 節(jié)點(diǎn)上成功獲取到了鎖,就再次獲取當(dāng)前時間(t2),然后計算計算整個加鎖過程的總耗時(t2-t1)。如果 t2-t1 < 鎖的過期時間,此時,認(rèn)為客戶端加鎖成功,否則認(rèn)為加鎖失敗。

加鎖成功要同時滿足兩個條件

(簡述:如果有超過半數(shù)的 Redis 節(jié)點(diǎn)成功的獲取到了鎖,并且總耗時沒有超過鎖的有效時間,那么就是加鎖成功):

  • 條件一:客戶端從超過半數(shù)(大于等于 N/2+1)的 Redis 節(jié)點(diǎn)上成功獲取到了鎖;
  • 條件二:客戶端從大多數(shù)節(jié)點(diǎn)獲取鎖的總耗時(t2-t1)小于鎖設(shè)置的過期時間。

加鎖成功后,客戶端需要重新計算這把鎖的有效時間,計算的結(jié)果是「鎖最初設(shè)置的過期時間」減去「客戶端從大多數(shù)節(jié)點(diǎn)獲取鎖的總耗時(t2-t1)」。

如果計算的結(jié)果已經(jīng)來不及完成共享數(shù)據(jù)的操作了,我們可以釋放鎖,以免出現(xiàn)還沒完成數(shù)據(jù)操作,鎖就過期了的情況。

加鎖失敗后,客戶端向所有 Redis 節(jié)點(diǎn)發(fā)起釋放鎖的操作,釋放鎖的操作和在單節(jié)點(diǎn)上釋放鎖的操作一樣,只要執(zhí)行釋放鎖的 Lua 腳本就可以了。

總結(jié)

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 線上Redis一直報連接超時該如何解決

    線上Redis一直報連接超時該如何解決

    這篇文章主要為大家詳細(xì)介紹了項(xiàng)目開發(fā)時如果出現(xiàn)線上Redis一直報連接超時的問題該如何解決,文中的示例代碼簡潔易懂,需要的小伙伴可以借鑒一下
    2023-08-08
  • phpredis提高消息隊列的實(shí)時性方法(推薦)

    phpredis提高消息隊列的實(shí)時性方法(推薦)

    下面小編就為大家?guī)硪黄猵hpredis提高消息隊列的實(shí)時性方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • Redis Lua腳本實(shí)現(xiàn)分布式鎖方式

    Redis Lua腳本實(shí)現(xiàn)分布式鎖方式

    文章主要介紹了在分布式系統(tǒng)中使用Lua腳本實(shí)現(xiàn)Redis分布式鎖的方法,包括可重入鎖的實(shí)現(xiàn)和注意事項(xiàng),以及紅鎖算法在Redis集群狀態(tài)下的潛在問題
    2026-05-05
  • Redis 存取 JSON 數(shù)據(jù)示例操作

    Redis 存取 JSON 數(shù)據(jù)示例操作

    JSON 是我們常用的數(shù)據(jù)類型,當(dāng)我們需要在Redis中保存json數(shù)據(jù)時是怎么存放的呢?一般是用String或者Hash,但還是不太方便,無法靈活的操作json 數(shù)據(jù),下面通過本文給大家介紹Redis存取JSON 數(shù)據(jù)示例操作,感興趣的的朋友一起看看吧
    2024-02-02
  • Redis實(shí)現(xiàn)短信驗(yàn)證碼登錄的示例代碼

    Redis實(shí)現(xiàn)短信驗(yàn)證碼登錄的示例代碼

    本文主要介紹了基于Redis如何實(shí)現(xiàn)短信驗(yàn)證碼登錄功能,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • 緩存替換策略及應(yīng)用(以Redis、InnoDB為例)

    緩存替換策略及應(yīng)用(以Redis、InnoDB為例)

    本文以Redis、InnoDB為例給大家講解緩存替換策略及應(yīng)用,本文給大家提到五種置換策略,通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2021-07-07
  • dubbo服務(wù)使用redis注冊中心的系列異常解決

    dubbo服務(wù)使用redis注冊中心的系列異常解決

    這篇文章主要為大家介紹了dubbo服務(wù)在使用redis注冊中心遇到的一系列異常的解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-03-03
  • Redis哨兵集群模式全方位解讀

    Redis哨兵集群模式全方位解讀

    Redis哨兵集群通過心跳檢測實(shí)現(xiàn)主從自動故障轉(zhuǎn)移,當(dāng)主節(jié)點(diǎn)宕機(jī)時,依據(jù)斷開時間、優(yōu)先級、offset和運(yùn)行ID規(guī)則選舉新主,腦裂問題因網(wǎng)絡(luò)分割導(dǎo)致數(shù)據(jù)沖突,可通過配置參數(shù)限制同步延遲和從節(jié)點(diǎn)數(shù)量來避免數(shù)據(jù)丟失
    2025-09-09
  • redis數(shù)據(jù)結(jié)構(gòu)之intset的實(shí)例詳解

    redis數(shù)據(jù)結(jié)構(gòu)之intset的實(shí)例詳解

    這篇文章主要介紹了redis數(shù)據(jù)結(jié)構(gòu)之intset的實(shí)例詳解的相關(guān)資料, intset也即整數(shù)集合,當(dāng)集合保存的值數(shù)量不多時,redis使用intset作為其底層數(shù)據(jù)保存結(jié)構(gòu),希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • Redis數(shù)據(jù)結(jié)構(gòu)SortedSet的底層原理解析

    Redis數(shù)據(jù)結(jié)構(gòu)SortedSet的底層原理解析

    這篇文章主要介紹了Redis數(shù)據(jù)結(jié)構(gòu)SortedSet的底層原理解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07

最新評論

湖口县| 阿勒泰市| 无锡市| 西吉县| 百色市| 张家港市| 韶山市| 辛集市| 格尔木市| 祁东县| 当雄县| 惠东县| 武川县| 奇台县| 修水县| 万年县| 嘉禾县| 荣昌县| 汶川县| 格尔木市| 阿图什市| 恩平市| 开封县| 天峨县| 乌拉特后旗| 北流市| 云和县| 黄骅市| 周至县| 高邑县| 甘肃省| 合阳县| 商城县| 东安县| 长子县| 思茅市| 普兰店市| 三江| 台州市| 都安| 莱阳市|