redis分布式鎖怎么實(shí)現(xiàn) 基于redis的分布式鎖

大家好,關(guān)于redis分布式鎖怎么實(shí)現(xiàn)很多朋友都還不太明白,不過沒關(guān)系,因?yàn)榻裉煨【幘蛠頌榇蠹曳窒黻P(guān)于基于redis的分布式鎖的知識(shí)點(diǎn),相信應(yīng)該可以解決大家的一些困惑和...
大家好,關(guān)于redis分布式鎖怎么實(shí)現(xiàn)很多朋友都還不太明白,不過沒關(guān)系,因?yàn)榻裉煨【幘蛠頌榇蠹曳窒黻P(guān)于基于redis的分布式鎖的知識(shí)點(diǎn),相信應(yīng)該可以解決大家的一些困惑和問題,如果碰巧可以解決您的問題,還望關(guān)注下本站哦,希望對(duì)各位有所幫助!
redis與zookeeper分布式鎖區(qū)別
您好,Redis與Zookeeper的分布式鎖的區(qū)別如下:
1.實(shí)現(xiàn)方式不同:Redis分布式鎖是基于Redis單機(jī)實(shí)現(xiàn)的,而Zookeeper分布式鎖是基于Zookeeper集群實(shí)現(xiàn)的。
2.鎖的粒度不同:Redis分布式鎖的鎖粒度是基于某個(gè)具體的業(yè)務(wù)邏輯實(shí)現(xiàn)的,而Zookeeper分布式鎖的鎖粒度是基于Zookeeper節(jié)點(diǎn)實(shí)現(xiàn)的。
3.鎖的可靠性不同:Redis分布式鎖在單機(jī)故障或網(wǎng)絡(luò)故障時(shí)可能會(huì)出現(xiàn)鎖失效的情況,而Zookeeper分布式鎖在Zookeeper集群中有多個(gè)節(jié)點(diǎn)存儲(chǔ)鎖信息,所以具有更高的可靠性。
4.性能不同:Redis分布式鎖的性能較高,因?yàn)樗腔趦?nèi)存實(shí)現(xiàn)的,而Zookeeper分布式鎖的性能相對(duì)較低,因?yàn)樗枰M(jìn)行網(wǎng)絡(luò)通信。
5.應(yīng)用場(chǎng)景不同:Redis分布式鎖適用于鎖持有時(shí)間較短,競(jìng)爭(zhēng)鎖的客戶端數(shù)量較少的場(chǎng)景,而Zookeeper分布式鎖適用于鎖持有時(shí)間較長(zhǎng),競(jìng)爭(zhēng)鎖的客戶端數(shù)量較多的場(chǎng)景。
Redis分布式鎖的原理是什么如何續(xù)期
分布式鎖的需求產(chǎn)生
分布式鎖的需求是伴隨著應(yīng)用分布式部署而來的,在單體應(yīng)用,且只部署一臺(tái)服務(wù)器的情況下,通過java的同步鎖即可實(shí)現(xiàn)。同步鎖,即是一個(gè)原子性的操作。
那么當(dāng)應(yīng)用進(jìn)行了分布式部署,應(yīng)用有多個(gè)服務(wù),這個(gè)時(shí)候應(yīng)用服務(wù)端就沒有一個(gè)可提供原子性操作的地方了,Redis性能高,且是單線程,因此可提供一個(gè)原子性操作的地方,利用它,就可以實(shí)現(xiàn)分布式鎖。
用場(chǎng)景說話,使用Redis分布式鎖的場(chǎng)景如下圖所示:如下圖所示,隨后會(huì)根據(jù)場(chǎng)景說明分布式鎖及續(xù)期相關(guān)問題的來龍去脈。
圖中序號(hào)1:進(jìn)來一個(gè)請(qǐng)求,這個(gè)請(qǐng)求要求我們保存一個(gè)“訂單A”;圖中序號(hào)2:2.1步,請(qǐng)求進(jìn)來,首先去嘗試設(shè)置一個(gè)Redis值,他的鍵就是訂單號(hào)“訂單A”,如果嘗試成功,則代表我這個(gè)線程是第一次設(shè)置,相當(dāng)于我拿到了這個(gè)鎖;如果嘗試失敗,那么,可以拋出異?;蛘叩却欢螘r(shí)候后再次重試,這里可以根據(jù)業(yè)務(wù)場(chǎng)景的不同采取不同的策略。這里的關(guān)鍵是在Redis中的操作是單線程的,因此該操作是原子性的。2.2步,為了防止應(yīng)用服務(wù)意外中斷,Redis中的數(shù)據(jù)一直存活,消耗資源,需要設(shè)置一個(gè)超時(shí)時(shí)間。(如果為了嚴(yán)謹(jǐn),可以將2.1,2.2兩步封裝成一個(gè)lua腳本部署在Redis服務(wù)器上)圖中序號(hào)3:情況A,這個(gè)時(shí)候是當(dāng)Redis的key還未失效,程序就已經(jīng)執(zhí)行完成,且刪除了Redis中的數(shù)據(jù),一切正常;情況B:就是需要續(xù)期的場(chǎng)景,如果要避免這個(gè)場(chǎng)景的出現(xiàn),可以將Rediskey的失效時(shí)間設(shè)置長(zhǎng)一點(diǎn),可以應(yīng)對(duì)大多數(shù)業(yè)務(wù)。如果要徹底解決,可以在應(yīng)用端添加一個(gè)Redis鎖的注冊(cè)中心,然后起一個(gè)監(jiān)聽線程去監(jiān)聽這個(gè)注冊(cè)中心,發(fā)現(xiàn)有鎖還在被持有,但是Redis已經(jīng)快過期了,則修改相應(yīng)key的失效時(shí)間,進(jìn)行續(xù)期。Java語言如何正確實(shí)現(xiàn)Redis分布式鎖
和大家分享我的經(jīng)驗(yàn),如何用redis提供的一個(gè)簡(jiǎn)單接口,輕松實(shí)現(xiàn)redis分布式鎖。
在開始之前,我先簡(jiǎn)單介紹下redis的性能。
高效的RedisRedis本身是單線程的,這樣帶來的好處是能夠提高讀寫效率。多線程通常來說會(huì)有上下文切換帶來的時(shí)間損耗,而redis通過綁定單個(gè)CPU到某塊內(nèi)存,實(shí)現(xiàn)了上下文切換的最小開銷,因此這種場(chǎng)景反而比多線程還要高效。
不安全的Redis但是,如果有不同的節(jié)點(diǎn)同時(shí)要對(duì)Redis中的同一個(gè)數(shù)據(jù)進(jìn)行操作,由于是來自不同Redis服務(wù)器,就會(huì)發(fā)生線程不安全的情況。
舉例有兩個(gè)功能函數(shù)X和Y(也可以看做是兩個(gè)服務(wù)器節(jié)點(diǎn)),二者功能相同,都要執(zhí)行讀取Redis中變量P,并且對(duì)其加一的操作。如果是線程安全的,那么X和Y分別執(zhí)行完之后,P的值應(yīng)該比原來增加2,但是由于函數(shù)XY互相獨(dú)立,那就可能發(fā)生下面這種情況:
1X讀取P
2Y讀取P
3X將P+1寫回Redis
4Y將P+1寫回Redis
執(zhí)行結(jié)束后,P的值卻變成了P+1,而不是P+2。
這就是線程不安全導(dǎo)致的結(jié)果。
redis的分布式鎖那么如何用Redis來避免上面的情況呢。
Redis對(duì)外開放了一個(gè)非常厲害的api,目前經(jīng)常被大家用來做分布式鎖,是絕對(duì)的線程安全,這個(gè)函數(shù)就是SETkeyfieldvalue加上NX參數(shù)。這個(gè)NX參數(shù)可是了不得,通常來說,set函數(shù)是不管field字段是否存在,只要寫入成功就會(huì)返回1,但是如果增加了NX參數(shù),那么如果field值在redis中已經(jīng)存在,就會(huì)返回nil,否則才返回1。因此可以通過這個(gè)函數(shù)來執(zhí)行加鎖操作,如果返回值不為nil,則加鎖成功,否則代表有其他線程在操作數(shù)據(jù),當(dāng)前請(qǐng)求需要等待。
不僅如此,為了避免死鎖,SET還有一個(gè)參數(shù)為EX,即EX毫秒后,field會(huì)自動(dòng)清空。
此外,還有PX,XX參數(shù),具體含義見如下文檔。
以上就是我在工作中總結(jié)的防止redis并發(fā)的方式,如果你有其他想法,歡迎在下方評(píng)論區(qū)與我溝通。
我是蘇蘇思量,來自BAT的java開發(fā)工程師,每天分享技術(shù)見聞,歡迎關(guān)注我,與我共同進(jìn)步。
關(guān)于redis分布式鎖怎么實(shí)現(xiàn)的內(nèi)容到此結(jié)束,希望對(duì)大家有所幫助。
本文鏈接:http:///kaifa/2516.html