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

一文詳解如何使用Redis實(shí)現(xiàn)分布式鎖

 更新時(shí)間:2022年09月06日 08:50:10   作者:程序員讀書???????  
這篇文章主要介紹了一文詳解如何使用Redis實(shí)現(xiàn)分布式鎖,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下

1. 什么是分布式鎖

當(dāng)我們在編寫多線程代碼的時(shí)候,不同的線程可能會(huì)發(fā)生資源的爭奪,為了避免資源爭奪造成的錯(cuò)誤,我們會(huì)對資源上鎖,只有獲得鎖的線程才能繼續(xù)往下執(zhí)行。

進(jìn)程中的鎖,本質(zhì)就是內(nèi)存中一個(gè)變量,當(dāng)一個(gè)線程執(zhí)行某個(gè)操作申請加鎖時(shí),如果能成功把代表鎖的變量值設(shè)置為1,則表示獲得了鎖,其他線程想要獲得鎖時(shí)會(huì)阻塞,而擁有鎖的線程執(zhí)行完操作后,再把鎖的值設(shè)置為0,則表示釋放了鎖。

上面我們說的是在一臺(tái)服務(wù)器的進(jìn)程內(nèi)不同線程之間的鎖,這個(gè)鎖是放在內(nèi)存中的,而對于分布式應(yīng)用程序來說,不同的應(yīng)用(進(jìn)程或線程)部署在不同的服務(wù)器上,這樣就不能通過內(nèi)存中的變量來表示鎖。

即然在一臺(tái)服務(wù)器上可以通過內(nèi)存這塊共享的空間來表示鎖,那么對于分布式應(yīng)用程序來說,可以共享存儲(chǔ)系統(tǒng)來存儲(chǔ)一個(gè)共享鎖,這就是分布式鎖,而Redis作為內(nèi)存數(shù)據(jù)庫,執(zhí)行非常快,很適合作為實(shí)現(xiàn)分布式鎖的共享存儲(chǔ)系統(tǒng)。

2. 使用Redis實(shí)現(xiàn)分布式鎖

對于一個(gè)鎖來說,其實(shí)只有兩個(gè)操作,加鎖和釋放鎖,下面我們看來看通過Redis要怎么實(shí)現(xiàn)?

2.1 加鎖

Redissetnx命令會(huì)判斷鍵值是否存在,如果存在則不做任何操作,并返回0,如果不存在,則創(chuàng)建并賦值,并返回1,因此我們可以執(zhí)行setnx為一個(gè)代表鎖鍵設(shè)置值,如果能設(shè)置成功,則表示獲得鎖,失敗則無法獲得鎖。

# 使用key為lock來表示一個(gè)鎖
setnx lock 1 

2.2 釋放鎖

當(dāng)執(zhí)行好操作之后,要釋放鎖的時(shí)候直接把Redis里的鍵值lock刪除就可以了,這樣其他進(jìn)程才能通過setnx命令重新設(shè)置并獲得該鎖。

# 釋放鎖
del lock

通過上面兩個(gè)命令,我們實(shí)現(xiàn)了一個(gè)簡單的分布式鎖,但這里就出現(xiàn)了一個(gè)問題:如果一個(gè)進(jìn)程通過setnx命令加鎖之后,在執(zhí)行具體操作出錯(cuò)了,沒有辦法及時(shí)釋放鎖,那么其他進(jìn)程就無法獲得該鎖,系統(tǒng)便無法繼續(xù)往下執(zhí)行,解決這個(gè)問題的辦法就是為鎖設(shè)置一個(gè)有效期,在這個(gè)有效期之后,自動(dòng)釋放鎖。

2.3 給鎖設(shè)置有效期

給鎖設(shè)置有效期非常簡單,直接使用Redisexpire命令就可以了,如:

# 加鎖
setnx lock 1 
# 給鎖設(shè)置10s有效期
expire lock 10 

但是,現(xiàn)在又出現(xiàn)另一個(gè)問題了,如果我們在設(shè)置了鎖之后,執(zhí)行expire命令之前該進(jìn)程掛掉了,那么expire就沒有執(zhí)行成功,鎖一樣是沒有被釋放掉的,所以一定要保證上面兩個(gè)命令要一起執(zhí)行,怎么保證呢?

有兩個(gè)方法,一個(gè)是使用LUA語言編寫的腳本,另一個(gè)是使用Redisset命令,set命令后面跟nx參數(shù)后,執(zhí)行的效果與setnx一致,且set命令可以跟ex參數(shù)來設(shè)置過期時(shí)間,所以我們可以使用set命令把setnxexpire兩個(gè)合并在一起,這樣就可以保證執(zhí)行的原子性了。

# 判斷是否鍵值是否存在,ex后面跟著的是鍵值的有效期,10s
set lock 1 nx ex 10 

解決了鎖的有效問題,現(xiàn)在我們再來看另外一個(gè)問題。

如上圖所示,現(xiàn)在有AB,C三個(gè)不同服務(wù)器上的進(jìn)程在執(zhí)行某個(gè)操作都需要獲得鎖,執(zhí)行后要釋放鎖。

現(xiàn)在的情況是進(jìn)程A執(zhí)行第2步時(shí)卡頓了(上面綠色區(qū)域所示),且時(shí)間超出了鎖有效期,所以進(jìn)程A設(shè)置的鎖自動(dòng)釋放了,這時(shí)候進(jìn)程B獲得了鎖,并開始執(zhí)行操作,但由于進(jìn)程A只是卡頓了而已,所以會(huì)繼續(xù)執(zhí)行的時(shí)候,在第3步的時(shí)候會(huì)手動(dòng)釋放鎖,但是這個(gè)時(shí)候,鎖由線程B所擁有,也就是說進(jìn)程A刪除的不是自己的鎖,而進(jìn)程B的鎖,這時(shí)候進(jìn)程B還沒執(zhí)行完,但鎖被釋放后,進(jìn)程C可以加鎖,也就是說由于進(jìn)程A卡頓釋放錯(cuò)了鎖,導(dǎo)致進(jìn)程B和進(jìn)程C可以同時(shí)獲得鎖。

怎么避免這種情況呢?如何區(qū)分其他進(jìn)程的鎖,避免刪除其他進(jìn)程的鎖呢?答案就是每個(gè)進(jìn)程在加鎖的時(shí)候,給鎖設(shè)置一個(gè)唯一值,并在釋放鎖的時(shí)候,判斷是不是自己設(shè)置的鎖。

2.4 給鎖設(shè)置唯一值

給鎖設(shè)置唯一值的時(shí)候,一樣是使用set命令,唯一的不同是將鍵值1改為一個(gè)隨機(jī)生成的唯一值,比如uuid。

 # rand_uid表示唯一id
set lock rand_id nx ex 10

當(dāng)鎖里的值由進(jìn)程設(shè)置后,釋放鎖的時(shí)候,就需要判斷鎖是不是自己的,步驟如下:

  • 通過Redisget命令獲得鎖的值
  • 根據(jù)獲得的值,判斷鎖是不是自己設(shè)置的
  • 如果是,通過del命令釋放鎖。

此時(shí)我們看到,釋放鎖需要執(zhí)行三個(gè)操作,如果三個(gè)操作依次執(zhí)行的話,是沒有辦法保證原子性的,比如進(jìn)程A在執(zhí)行到第2步后,準(zhǔn)備開始執(zhí)行del命令時(shí),而鎖由時(shí)有效期到了,被自動(dòng)釋放了,并被其他服務(wù)器上的進(jìn)程B獲得鎖,但這時(shí)候線程A執(zhí)行del還是把線程B的鎖給刪掉了。

解決這個(gè)問題的辦法就是保證上述三個(gè)操作執(zhí)行的原子性,即在執(zhí)行釋放鎖的三個(gè)操作中,其他進(jìn)程不可以獲得鎖,想要做到這一點(diǎn),需要使用到LUA腳本。

2.5 通過LUA腳本實(shí)現(xiàn)釋放鎖的原子性

Redis支持LUA腳本,LUA腳里的代碼執(zhí)行的時(shí)候,其他客戶端的請求不會(huì)被執(zhí)行,這樣可以保證原子性操作,所以我們可以使用下面腳本進(jìn)行鎖的釋放:

if redis.call("get",KEYS[1]) == ARGV[1] then 
  return redis.call("del",KEYS[1])
else 
  return 0
end

將上述腳本保存為腳本后,可以調(diào)用Redis客戶端命令redis-cli來執(zhí)行,如下:

# lock為key,rand_id表示key里保存的值
redis-cli --eval unlock.lua lock , rand_id 

3. 小結(jié)

無論是本地鎖還是分布式鎖,鎖的本質(zhì)就是一個(gè)共享的變量,只是在實(shí)現(xiàn)分布式鎖時(shí)候,把這個(gè)變量移到了Redis服務(wù)器所在的內(nèi)存中。

在上面實(shí)現(xiàn)分布式鎖的過程中我們碰到了以下幾個(gè)問題:

  • 如何保證加鎖操作的原子性?
  • 如何保證進(jìn)程崩潰自動(dòng)釋放鎖?
  • 如何避免刪錯(cuò)其他進(jìn)程的鎖?
  • 如何保證釋放鎖操作的原子性?

在解決上述問題的時(shí)候,我們也一步步完善一個(gè)可以在實(shí)際開發(fā)中應(yīng)用的Redis分布式鎖。

到此這篇關(guān)于一文詳解如何使用Redis實(shí)現(xiàn)分布式鎖的文章就介紹到這了,更多相關(guān)Redis實(shí)現(xiàn)分布式鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis SETNX命令在Spring Cloud中的分布式鎖用法詳解

    Redis SETNX命令在Spring Cloud中的分布式鎖用法詳解

    在Spring Cloud項(xiàng)目中,使用Java和Redis結(jié)合實(shí)現(xiàn)的分布式鎖可以確保訂單的一致性和并發(fā)控制,通過合理使用鎖的粒度以及注意事項(xiàng),可以減少死鎖問題并提高系統(tǒng)的并發(fā)性能,這篇文章主要介紹了Redis SETNX命令在Spring Cloud中的分布式鎖用法詳解,需要的朋友可以參考下
    2023-10-10
  • Redis哨兵模式實(shí)現(xiàn)一主二從三哨兵

    Redis哨兵模式實(shí)現(xiàn)一主二從三哨兵

    本文主要介紹了Redis哨兵模式實(shí)現(xiàn)一主二從三哨兵,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • SpringBoot整合Redis入門之緩存數(shù)據(jù)的方法

    SpringBoot整合Redis入門之緩存數(shù)據(jù)的方法

    Redis是一個(gè)開源的使用ANSI C語言編寫、支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型、Key-Value數(shù)據(jù)庫,并提供多種語言的API,下面通過本文給大家介紹下SpringBoot整合Redis入門之緩存數(shù)據(jù)的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2021-11-11
  • Redis中的數(shù)據(jù)過期策略詳解

    Redis中的數(shù)據(jù)過期策略詳解

    這篇文章主要介紹了Redis中的數(shù)據(jù)過期策略,文中通過示例代碼介紹的很詳細(xì),相信對大家的理解和學(xué)習(xí)具有一定的參考借鑒價(jià)值,有需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-01-01
  • Redis的4種緩存模式分享

    Redis的4種緩存模式分享

    這篇文章主要介紹了Redis的4種緩存模式分享,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下
    2022-07-07
  • redis鎖機(jī)制介紹與實(shí)例

    redis鎖機(jī)制介紹與實(shí)例

    今天小編就為大家分享一篇關(guān)于redis鎖機(jī)制介紹與實(shí)例,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Reactor?WebFlux集成Redis處理緩存操作

    Reactor?WebFlux集成Redis處理緩存操作

    這篇文章主要為大家介紹了Reactor?WebFlux集成Redis處理緩存操作示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Redis的過期鍵刪除策略原理說明

    Redis的過期鍵刪除策略原理說明

    這篇文章主要介紹了Redis的過期鍵刪除策略原理說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • Redisson分布式鎖解鎖異常問題

    Redisson分布式鎖解鎖異常問題

    文章主要描述了在使用Redisson進(jìn)行分布式鎖操作時(shí),遇到的`IllegalMonitorStateException`異常,通過分析報(bào)錯(cuò)信息,作者發(fā)現(xiàn)了問題的根源在于線程嘗試解鎖但未按順序執(zhí)行,作者提出了兩種解決方案:在解鎖前增加判斷,確保線程已獲得鎖
    2024-12-12
  • 手動(dòng)實(shí)現(xiàn)Redis的LRU緩存機(jī)制示例詳解

    手動(dòng)實(shí)現(xiàn)Redis的LRU緩存機(jī)制示例詳解

    這篇文章主要介紹了手動(dòng)實(shí)現(xiàn)Redis的LRU緩存機(jī)制示例詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03

最新評(píng)論

中西区| 商河县| 凤阳县| 探索| 宁陵县| 星子县| 桓台县| 教育| 新余市| 工布江达县| 佳木斯市| 开远市| 桑日县| 韩城市| 杭州市| 淅川县| 安乡县| 昌江| 嵊州市| 扶风县| 昭觉县| 慈利县| 岱山县| 宁蒗| 广汉市| 长汀县| 万全县| 泸西县| 榆树市| 博白县| 清河县| 三台县| 来安县| 大姚县| 西青区| 南昌市| 叶城县| 临汾市| 寿光市| 永丰县| 财经|