溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Redis分布式鎖的原理是什么

發(fā)布時(shí)間:2021-12-03 15:21:46 來(lái)源:億速云 閱讀:148 作者:柒染 欄目:大數(shù)據(jù)

今天就跟大家聊聊有關(guān)Redis分布式鎖的原理是什么,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

前言

以前在學(xué)校做小項(xiàng)目的時(shí)候,用到Redis,基本也只是用來(lái)當(dāng)作緩存??砂⒎墼诠ぷ髦邪l(fā)現(xiàn),Redis在生產(chǎn)中并不只是當(dāng)作緩存這么簡(jiǎn)單。在阿粉接觸到的項(xiàng)目中,Redis起到了一個(gè)分布式鎖的作用,具體情況是這樣的:

該項(xiàng)目在某金融平臺(tái)中負(fù)責(zé)某塊業(yè)務(wù),是一個(gè)分布式系統(tǒng),線上大概跑著10個(gè)左右的實(shí)例。其中有一個(gè)步驟需要用戶支付一定的費(fèi)用,Redis分布式鎖在其中大概處于這么一個(gè)位置:

Redis分布式鎖的原理是什么  

可以看到在上分布式鎖之后,系統(tǒng)做了兩個(gè)查詢(xún)校驗(yàn),然后向數(shù)據(jù)庫(kù)中插入了一條訂單記錄,接著才解鎖進(jìn)入支付流程。

從業(yè)務(wù)的角度考慮分布式鎖是好理解的,它保證了查詢(xún)及插入數(shù)據(jù)整個(gè)流程的原子性,防止查詢(xún)校驗(yàn)的時(shí)候查到臟數(shù)據(jù),使得支付前訂單信息落表的操作串行化執(zhí)行。

盡管從業(yè)務(wù)上來(lái)說(shuō)很好理解,但使用Redis作為分布式鎖對(duì)我來(lái)說(shuō)是個(gè)新知識(shí),阿粉打算結(jié)合項(xiàng)目中的代碼,深挖一下這個(gè)知識(shí)點(diǎn)。

Redis分布式鎖的原理是什么  
 

正文

 
1. 為什么要使用分布式鎖

在實(shí)際項(xiàng)目中見(jiàn)過(guò)分布式鎖后,就不難理解為什么要使用分布式鎖了:總結(jié)來(lái)說(shuō)就是分布式系統(tǒng)要訪問(wèn)共享資源,為了避免并發(fā)訪問(wèn)資源帶來(lái)錯(cuò)誤,我們?yōu)楣蚕碣Y源添加一把鎖,讓各個(gè)訪問(wèn)互斥,保證并發(fā)訪問(wèn)的安全性,這就是使用分布式鎖的原因。

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

redis中使用分布式鎖很簡(jiǎn)單,只要使用setnx指令對(duì)某個(gè)key上鎖就行:

setnx lock test //上鎖
del lock test   //解鎖
 

當(dāng)某個(gè)key沒(méi)有被占用的時(shí)候,setnx指令會(huì)返回1,否則返回0,這就是Redis中分布式鎖的使用原理。

當(dāng)然我們還可以在上鎖之后使用expire指令給鎖設(shè)置過(guò)期時(shí)間。

看到這里你可能會(huì)有疑問(wèn),如果我們的程序流程不使用指令解鎖,靠redis設(shè)置時(shí)間過(guò)期來(lái)解鎖,貌似會(huì)出問(wèn)題。假如我們的服務(wù)進(jìn)程在執(zhí)行setnx之后和執(zhí)行expire指令之前掛掉了,那這個(gè)鎖豈不是永遠(yuǎn)都不能被釋放?

Redis分布式鎖的原理是什么  

沒(méi)錯(cuò),這確實(shí)是個(gè)問(wèn)題,當(dāng)時(shí)人們?cè)赗edis的開(kāi)源社區(qū)提出了一堆解決方案專(zhuān)門(mén)來(lái)解決這個(gè)問(wèn)題,可實(shí)現(xiàn)方式都極為復(fù)雜。后來(lái)Redis的作者在Redis 2.8版本中加入了set指令的擴(kuò)展參數(shù),使得setnx指令和expire指令能夠同時(shí)執(zhí)行,具體使用像下面這個(gè)樣子:

set lock test ex 5 nx
ex:設(shè)置鍵的過(guò)期時(shí)間
nx:只在鍵不存在時(shí),才對(duì)鍵進(jìn)行設(shè)置操作
 

從此以后,Redis成為了分布式鎖的寵兒。

 
3. 分布式鎖在Redis集群中遇到的麻煩

在學(xué)習(xí)了Redis中分布式鎖的使用后,很快我們便發(fā)現(xiàn)了新的問(wèn)題。在企業(yè)中,Redis基本上都是集群部署的,集群部署避免不了要面對(duì)某個(gè)節(jié)點(diǎn)宕機(jī)的問(wèn)題。

我們考慮這么一種情況:假設(shè)我們?cè)趓edis的主節(jié)點(diǎn)上添加了一把分布式鎖,不幸的是主節(jié)點(diǎn)掛掉了,而且主節(jié)點(diǎn)上的鎖還沒(méi)有同步到從節(jié)點(diǎn)上,如果此時(shí)有客戶端來(lái)請(qǐng)求獲得同一把鎖,那么它將順利地獲得鎖,之前那把鎖會(huì)被無(wú)情地忽視掉,這就是分布式鎖在Redis集群中遇到的麻煩。

Redis分布式鎖的原理是什么  

Redis的作者為了解決這個(gè)問(wèn)題提出了一個(gè)叫Redlock的算法,它的原理是這樣的:當(dāng)上鎖的時(shí)候,把set指令發(fā)送給過(guò)半的節(jié)點(diǎn),只要過(guò)半的鎖set成功,就認(rèn)為這次加鎖成功;當(dāng)解鎖的時(shí)候,會(huì)向所有的節(jié)點(diǎn)發(fā)送del指令。

從這個(gè)算法的原理可以看出,由于Redlock需要同時(shí)對(duì)多個(gè)節(jié)點(diǎn)進(jìn)行讀寫(xiě),因此使用Redlock加分布式鎖的性能要比單機(jī)Redis低很多。因?yàn)橹鲝膹?fù)制出紕漏的概率極低,所以如果對(duì)分布式加鎖過(guò)程有一定的容錯(cuò)率的話,可以考慮直接使用set指令;如果追求高可用性,可以考慮使用Redlock算法。

當(dāng)然,高可用性的分布式鎖不只有Redis的Redlock,我們還可以用zookeeper或者支持事務(wù)的數(shù)據(jù)庫(kù)做分布式鎖。

?

簡(jiǎn)述zookeeper的分布式鎖原理:假設(shè)zk用某個(gè)節(jié)點(diǎn)作為分布式鎖,當(dāng)不同的客戶端到zk競(jìng)爭(zhēng)這把鎖的時(shí)候,zk會(huì)按順序給不同的客戶端創(chuàng)建一個(gè)子節(jié)點(diǎn),掛在作為分布式鎖的節(jié)點(diǎn)下面。假設(shè)第一個(gè)來(lái)到的客戶端為A,第二個(gè)來(lái)到的是B,分布式節(jié)點(diǎn)下掛的第一個(gè)節(jié)點(diǎn)就是A,B緊跟著A,且B會(huì)監(jiān)聽(tīng)著A的生命狀態(tài),當(dāng)A釋放鎖后A會(huì)被刪除,這時(shí)B監(jiān)聽(tīng)到A被刪除,B接能上位獲得分布式鎖了。

?  

在公司的項(xiàng)目中,雖然Redis是以集群的方式部署的,但還是使用最基本的set指令獲取分布式鎖,因?yàn)檫@種方式的性能遠(yuǎn)遠(yuǎn)高于Redlock算法,也高于zk,數(shù)據(jù)庫(kù)等分布式鎖實(shí)現(xiàn)方式。

雖然在高性能與低概率的錯(cuò)誤中選擇了高性能,但項(xiàng)目中還是做了其他工作對(duì)錯(cuò)誤情況進(jìn)行兜底的,比如在公司的項(xiàng)目中對(duì)主從復(fù)制時(shí)的錯(cuò)誤情況會(huì)拋出異常,然后根據(jù)異常會(huì)進(jìn)行一些重試的操作。

看完上述內(nèi)容,你們對(duì)Redis分布式鎖的原理是什么有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI