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

詳解redis分布式鎖的這些坑

 更新時間:2021年05月19日 11:02:54   作者:華為云開發(fā)者社區(qū)  
在很多互聯(lián)網(wǎng)產(chǎn)品應(yīng)用中,有些場景需要加鎖處理,比如:秒殺,全局遞增ID等等。大部分的解決方案是基于DB實現(xiàn)的,Redis為單進程單線程模式,采用隊列模式將并發(fā)訪問變成串行訪問,且多客戶端對Redis的連接并不存在競爭關(guān)系。

一、白話分布式

什么是分布式,用最簡單的話來說,就是為了較低單個服務(wù)器的壓力,將功能分布在不同的機器上面,本來一個程序員可以完成一個項目:需求->設(shè)計->編碼->測試

但是項目多的時候,一個人也扛不住,這就需要不同的人進行分工合作了

這就是一個簡單的分布式協(xié)同工作了;

二、分布式鎖

首先看一個問題,如果說某個環(huán)節(jié)被終止或者別侵占,就會發(fā)生不可知的事情

這就會出現(xiàn),設(shè)計好的或者設(shè)計的半成品會被破壞,導(dǎo)致后面環(huán)節(jié)出錯;

這時候,我們就需要引入分布式鎖的概念;

何為分布式鎖

當在分布式模型下,數(shù)據(jù)只有一份(或有限制),此時需要利用鎖的技術(shù)控制某一時刻修改數(shù)據(jù)的進程數(shù)。

用一個狀態(tài)值表示鎖,對鎖的占用和釋放通過狀態(tài)值來標識。

分布式鎖的條件

  • 可以保證在分布式部署的應(yīng)用集群中,同一個方法在同一時間只能被一臺機器上的一個線程執(zhí)行。
  • 這把鎖要是一把可重入鎖(避免死鎖)
  • 這把鎖最好是一把阻塞鎖
  • 這把鎖最好是一把公平鎖
  • 有高可用的獲取鎖和釋放鎖功能
  • 獲取鎖和釋放鎖的性能要好

分布式鎖的實現(xiàn)

分布式鎖的實現(xiàn)由很多種,文件鎖、數(shù)據(jù)庫、redis等等,比較多,在實踐中,還是redis做分布式鎖性能會高一些;

三、redis實現(xiàn)分布式鎖

首先看兩個命令:

setnx:將 key 的值設(shè)為 value,當且僅當 key 不存在。 若給定的 key 已經(jīng)存在,則 SETNX 不做任何動作。 SETNX 是SET if Not eXists的簡寫。

127.0.0.1:6379> set lock "unlock"
OK
127.0.0.1:6379> setnx lock "unlock"
(integer) 0
127.0.0.1:6379> setnx lock "lock"
(integer) 0
127.0.0.1:6379>

expire:EXPIRE key seconds

為給定 key 設(shè)置生存時間,當 key 過期時(生存時間為 0 ),它會被自動刪除

127.0.0.1:6379> expire lock 10
(integer) 1
127.0.0.1:6379> ttl lock
8
127.0.0.1:6379> get lock
(nil)

基于分布式鎖的流程:

這就是一個簡單的分布式鎖的實現(xiàn)流程,具體代碼實現(xiàn)也很簡單,就不贅述了;

四、redis實現(xiàn)分布式鎖問題

如果出現(xiàn)了這么一個問題:如果setnx是成功的,但是expire設(shè)置失敗,那么后面如果出現(xiàn)了釋放鎖失敗的問題,那么這個鎖永遠也不會被得到,業(yè)務(wù)將被鎖死?

解決的辦法:使用set的命令,同時設(shè)置鎖和過期時間

set參數(shù):

set key value [EX seconds] [PX milliseconds] [NX|XX]

EX seconds:設(shè)置失效時長,單位秒

PX milliseconds:設(shè)置失效時長,單位毫秒

NX:key不存在時設(shè)置value,成功返回OK,失敗返回(nil)

XX:key存在時設(shè)置value,成功返回OK,失敗返回(nil)

實踐:

127.0.0.1:6379> set unlock "234" EX 100 NX
(nil)
127.0.0.1:6379> 
127.0.0.1:6379> set test "111" EX 100 NX
OK

這樣就完美的解決了分布式鎖的原子性。

五、用鎖遇到過哪些問題?又是如何解決的?未關(guān)閉資源

由于當前線程 獲取到redis 鎖,處理完業(yè)務(wù)后未及時釋放鎖,導(dǎo)致其它線程會一直嘗試獲取鎖阻塞,例如:用Jedis客戶端會報如下的錯誤信息

1redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

redis線程池已經(jīng)沒有空閑線程來處理客戶端命令。使用原生方法記得關(guān)閉!

解決的方法也很簡單,只要我們細心一點,拿到鎖的線程處理完業(yè)務(wù)及時釋放鎖

B的鎖被A給釋放了

我們知道Redis實現(xiàn)鎖的原理在于 SETNX命令。當 key不存在時將 key的值設(shè)為 value ,返回值為 1;若給定的 key已經(jīng)存在,則 SETNX不做任何動作,返回值為 0 。

SETNX key value

我們來設(shè)想一下這個場景:A、B兩個線程來嘗試給key myLock加鎖,A線程先拿到鎖(假如鎖3秒后過期),B線程就在等待嘗試獲取鎖,到這一點毛病沒有。

那如果此時業(yè)務(wù)邏輯比較耗時,執(zhí)行時間已經(jīng)超過redis鎖過期時間,這時A線程的鎖自動釋放(刪除key),B線程檢測到myLock這個key不存在,執(zhí)行 SETNX命令也拿到了鎖。

但是,此時A線程執(zhí)行完業(yè)務(wù)邏輯之后,還是會去釋放鎖(刪除key),這就導(dǎo)致B線程的鎖被A線程給釋放了。

為避免上邊的情況,一般我們在每個線程加鎖時要帶上自己獨有的value值來標識,只釋放指定value的key,否則就會出現(xiàn)釋放鎖混亂的場景

一般我們可以設(shè)置value為業(yè)務(wù)前綴_當前線程ID或者uuid,只有當前value相同的才可以釋放鎖

鎖過期了,業(yè)務(wù)還沒執(zhí)行完

redis分布式鎖過期,而業(yè)務(wù)邏輯沒執(zhí)行完的場景,不過,這里換一種思路想問題,把redis鎖的過期時間再弄長點不就解決了嗎?

那還是有問題,我們可以在加鎖的時候,手動調(diào)長redis鎖的過期時間,可這個時間多長合適?業(yè)務(wù)邏輯的執(zhí)行時間是不可控的,調(diào)的過長又會影響操作性能。

要是redis鎖的過期時間能夠自動續(xù)期就好了。

為了解決這個問題我們使用redis客戶端redisson,redisson很好的解決了redis在分布式環(huán)境下的一些棘手問題,它的宗旨就是讓使用者減少對Redis的關(guān)注,將更多精力用在處理業(yè)務(wù)邏輯上。

redisson對分布式鎖做了很好封裝,只需調(diào)用API即可。

RLock lock = redissonClient.getLock("stockLock");

redisson在加鎖成功后,會注冊一個定時任務(wù)監(jiān)聽這個鎖,每隔10秒就去查看這個鎖,如果還持有鎖,就對過期時間進行續(xù)期。默認過期時間30秒。這個機制也被叫做:“看門狗”

redis主從復(fù)制的坑

redis高可用最常見的方案就是主從復(fù)制(master-slave),這種模式也給redis分布式鎖挖了一坑。

redis cluster集群環(huán)境下,假如現(xiàn)在A客戶端想要加鎖,它會根據(jù)路由規(guī)則選擇一臺master節(jié)點寫入key mylock,在加鎖成功后,master節(jié)點會把key異步復(fù)制給對應(yīng)的slave節(jié)點。

如果此時redis master節(jié)點宕機從節(jié)點復(fù)制失敗,為保證集群可用性,會進行主備切換,slave變?yōu)榱藃edis master。B客戶端在新的master節(jié)點上加鎖成功,而A客戶端也以為自己還是成功加了鎖的。另外如果主從復(fù)制延遲同樣也會造成加鎖和解鎖延遲的問題。

此時就會導(dǎo)致同一時間內(nèi)多個客戶端對一個分布式鎖完成了加鎖,導(dǎo)致各種臟數(shù)據(jù)的產(chǎn)生。

畢竟redis是保持的AP而非CP,如果要追求強一致性可以使用zookeeper分布式鎖。

以上就是詳解redis分布式鎖的這些坑的詳細內(nèi)容,更多關(guān)于redis分布式鎖的這些坑的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Linux環(huán)境下升級redis的詳細步驟記錄

    Linux環(huán)境下升級redis的詳細步驟記錄

    這篇文章主要給大家介紹了關(guān)于Linux環(huán)境下升級redis的詳細步驟,描述了如何從舊版本升級到新版本Redis,包括備份舊數(shù)據(jù)、下載和安裝新版本、復(fù)制配置文件和數(shù)據(jù)、停止舊版本并啟動新版本的過程,需要的朋友可以參考下
    2024-12-12
  • NestJS+Redis實現(xiàn)手寫一個限流器

    NestJS+Redis實現(xiàn)手寫一個限流器

    限流是大型系統(tǒng)必備的保護措施,本文將結(jié)合redis , lua 腳本 以及 Nestjs Guard 來實現(xiàn) 限流的效果,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-11-11
  • Redis分布式鎖之紅鎖的實現(xiàn)

    Redis分布式鎖之紅鎖的實現(xiàn)

    本文主要介紹了Redis分布式鎖之紅鎖的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • easyswoole3.5 redis使用詳細解析

    easyswoole3.5 redis使用詳細解析

    這篇文章主要介紹了easyswoole3.5 redis使用的相關(guān)知識,本文通過示例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • 基于Redis實現(xiàn)搶紅包和發(fā)紅包功能

    基于Redis實現(xiàn)搶紅包和發(fā)紅包功能

    搶紅包是我們生活常用的社交功能, 這個功能最主要的特點就是用戶的并發(fā)請求高, 在系統(tǒng)設(shè)計上, 可以使用非常多的辦法來扛住用戶的高并發(fā)請求, 在本文中簡要介紹使用Redis緩存中間件來實現(xiàn)搶紅包算法,需要的朋友可以參考下
    2024-04-04
  • redis?sentinel監(jiān)控高可用集群實現(xiàn)的配置步驟

    redis?sentinel監(jiān)控高可用集群實現(xiàn)的配置步驟

    這篇文章主要介紹了redis?sentinel監(jiān)控高可用集群實現(xiàn)的配置步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪
    2022-04-04
  • Redis鎖的過期時間小于業(yè)務(wù)的執(zhí)行時間如何續(xù)期

    Redis鎖的過期時間小于業(yè)務(wù)的執(zhí)行時間如何續(xù)期

    本文主要介紹了Redis鎖的過期時間小于業(yè)務(wù)的執(zhí)行時間如何續(xù)期,Redisson它能給Redis分布式鎖實現(xiàn)過期時間自動續(xù)期,具有一定的參考價值,感興趣的可以了解一下
    2024-05-05
  • Redis高并發(fā)問題的解決方法

    Redis高并發(fā)問題的解決方法

    這篇文章主要介紹了Redis高并發(fā)問題的解決辦法,具有很好的參考價值,感興趣的小伙伴們可以參考一下,具體如下:
    2018-05-05
  • Redis實現(xiàn)信息已讀未讀狀態(tài)提示

    Redis實現(xiàn)信息已讀未讀狀態(tài)提示

    這篇文章主要介紹了Redis實現(xiàn)信息已讀未讀狀態(tài)提示的相關(guān)資料,需要的朋友可以參考下
    2016-04-04
  • redis限流的實際應(yīng)用

    redis限流的實際應(yīng)用

    這篇文章主要介紹了redis限流的實際應(yīng)用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04

最新評論

金平| 浦江县| 望城县| 舟山市| 嘉鱼县| 凭祥市| 德昌县| 会理县| 敦煌市| 沙坪坝区| 萨迦县| 龙里县| 县级市| 长宁县| 洛浦县| 泸水县| 沙洋县| 将乐县| 东丽区| 融水| 德昌县| 绩溪县| 锡林郭勒盟| 荥经县| 正镶白旗| 临夏县| 宁安市| 米脂县| 濮阳县| 迁西县| 孝感市| 张掖市| 齐齐哈尔市| 修文县| 基隆市| 卓尼县| 普洱| 汕头市| 巴彦淖尔市| 通化县| 荆门市|