亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

前言

提到數(shù)據(jù)一致性、操作原子性,諸如此類的一些與并發(fā)有關(guān)的詞匯時(shí)不知道你第一時(shí)間會(huì)聯(lián)想到什么呢?我相信大多數(shù)人可能會(huì)想到“鎖”,為什么是鎖呢,這個(gè)我不多說,大家心里應(yīng)該都明白。在單體應(yīng)用時(shí)代,我們使用jvm提供的鎖就可以很好的工作,但是到了分布式應(yīng)用時(shí)代,jvm提供的鎖就行不通了,那么勢(shì)必要借助一些跨jvm的臨界資源來支持鎖的相關(guān)語義,比如redis,zookeeper等。

步入正題

我今天就來分享下我司基于redis來實(shí)現(xiàn)的分布式鎖,2013年投入使用,也算是久經(jīng)沙場。但是也存在一些設(shè)計(jì)上的缺陷,這個(gè)我后面也會(huì)提到,希望大家秉著互相學(xué)習(xí)的態(tài)度文明交流,別一上來就說這不行那不行,還是那句話“適合自己的才是最好的”。

加鎖過程分析

我們公司使用了 6 年的分布式鎖,很是牛逼啊

 

我第一次讀代碼的時(shí)候,有這么幾個(gè)疑惑:

Q1:為什么不使用 SET key value [expiration EX seconds|PX milliseconds] [NX|XX] 這個(gè)指令來實(shí)現(xiàn)key的自動(dòng)過期呢,反而放到應(yīng)用代碼判斷key是否過期?

A1:我們的分布式鎖開發(fā)的時(shí)候SET命令還不支持NX、PX,所以才想出這種辦法來實(shí)現(xiàn)key過期,NX、PX在2.6.12以后開始支持;

Q2:已經(jīng)判斷了當(dāng)前key對(duì)應(yīng)的時(shí)間戳已經(jīng)過期了,為什么還要使用getset再獲取一次呢,直接使用set指令覆蓋不可以嗎?

A2:這里其實(shí)牽扯到并發(fā)的一些事情,如果直接使用set,那有可能多個(gè)客戶端會(huì)同時(shí)獲取到鎖,如果使用getset然后判斷舊值是否過期就不會(huì)有這個(gè)問題,設(shè)想一下如下場景:

1.C1加鎖成功,不巧的是,這時(shí)C1意外的奔潰了,自然就不會(huì)釋放鎖;

2.C2,C3嘗試加鎖,這時(shí)key已存在,所以C2,C3去判斷key是否已過期,這里假設(shè)key已經(jīng)過期了,所以C2,C3使用set指令去設(shè)置值,那兩個(gè)都會(huì)加鎖成功,這就闖大禍了;如果使用getset指令,然后判斷下返回值是否過期就可以避免這種問題,假如C2跑的快,那C3判斷返回的時(shí)間戳已經(jīng)過期,自然就加鎖失??;

釋放鎖過程分析

我們公司使用了 6 年的分布式鎖,很是牛逼啊

 

Q1:為什么釋放鎖時(shí)還需要判斷key是否過期呢,直接del不是性能更高嗎?

A1:考慮這樣一種場景:

1. C1獲取鎖成功,開始執(zhí)行自己的操作,不幸的是C1這時(shí)被阻塞了;

2. C2這時(shí)來獲取鎖,由于C1被阻塞了很長時(shí)間,所以key對(duì)應(yīng)的value已經(jīng)過期了,這時(shí)C2通過getset加鎖成功;

3. C1塵封了太久終于被再次喚醒,對(duì)于釋放鎖這件事它可是認(rèn)真的,伴隨著一波del操作,悲劇即將發(fā)生;

4. C3來獲取鎖,好家伙,居然一下就成功了,接著就是一波操作猛如虎,接著就是一堆的客訴過來了;

為什么會(huì)這樣呢?回想C1被喚醒以后的事情,居然敢直接del,C2活都沒干完呢,鎖就被C1給釋放了,這時(shí)C3來直接就加鎖成功,所以為了安全起見C3釋放鎖時(shí)得分成兩步:1.判斷value是否已經(jīng)過期 2.如果已過期直接忽略,如果沒過期就執(zhí)行del。這樣就真的安全了嗎?安全了嗎?安全了嗎?假如第一步和第二步之間相隔了很久是不是也會(huì)出現(xiàn)鎖被其他人釋放的問題呢?是吧?是的!有沒有別的解決辦法呢?聽說借助lua就可以解決這個(gè)問題了。

正視自己的缺點(diǎn)

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

A1:這個(gè)暫時(shí)沒有實(shí)現(xiàn),據(jù)說有一個(gè)叫Redisson的家伙解決了這個(gè)問題,我們也有部分業(yè)務(wù)在使用,未來有可能會(huì)切換到Redisson。

Q2:怎么實(shí)現(xiàn)的高可用?

A2:我們采用Failover機(jī)制,初始化redis鎖的時(shí)候會(huì)維護(hù)一個(gè)redis連接池,加鎖或者釋放鎖的時(shí)候采用多寫的方式來保障一致性,如果某個(gè)節(jié)點(diǎn)不可用的時(shí)候會(huì)自動(dòng)切換到其他節(jié)點(diǎn),但是這種機(jī)制可能會(huì)導(dǎo)致多個(gè)客戶端同時(shí)獲取到鎖的情況,考慮這種情況:

1. C1去redis1加鎖,加鎖成功后會(huì)寫到redis2,redis3;

2. C2也去redis1加鎖,但是此時(shí)C2到redis1的網(wǎng)絡(luò)出現(xiàn)問題,這時(shí)C2切換到redis2去加鎖,由于第一步中的redis多寫并不是原子的,所有就有可能導(dǎo)致C2也獲取鎖成功;

針對(duì)這種情況,目前有些業(yè)務(wù)方是通過數(shù)據(jù)庫唯一索引的方式來規(guī)避的,未來會(huì)修復(fù)這個(gè)bug,具體方案目前還沒有。

總結(jié)

希望對(duì)有些同學(xué)能起到幫助,不喜勿噴。

來源:https://biiy.cn/000PZC

分享到:
標(biāo)簽:分布式 redis
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績?cè)u(píng)定