阿里面試官:Redis的分布式鎖和Zookeeper的有啥區(qū)別?為啥要用它?
在分布式鎖的實(shí)現(xiàn)方案中,通常就是數(shù)據(jù)庫(kù)、Redis 以及 Zookeeper 這三種,關(guān)于分布式鎖的多種實(shí)現(xiàn)方式及原理我們這里不展開(kāi)了。
圖片
本文主要聚焦 Redis 的分布式鎖和Zookeeper 的分布式鎖之間的區(qū)別,以及如何選擇。
其實(shí)在功能上,Redis 的分布式鎖和 ZK 的分布式鎖都能實(shí)現(xiàn)我們想要的功能,鎖的互斥、重入等等。他們主要有以下幾個(gè)區(qū)別:
性能區(qū)別
在性能方面,Redis 是基于內(nèi)存存儲(chǔ)的,而 ZK 是基于磁盤(pán)存儲(chǔ)的,所以,在性能上,Redis 要比 ZK 更好一些。
自動(dòng)釋放
ZK 的鎖的實(shí)現(xiàn)原理是基于客戶(hù)端和服務(wù)端的連接來(lái)保證的,一旦連接斷了,鎖就會(huì)被自動(dòng)釋放。而 Redis 的鎖是需要自己主動(dòng)加鎖和解鎖的,除非達(dá)到了超時(shí)時(shí)間,否則不會(huì)自動(dòng)釋放。
所以,ZK 的分布式鎖可以更好的應(yīng)對(duì)客戶(hù)端崩潰的情況,一旦客戶(hù)端崩潰,鎖就會(huì)釋放,而 Redis 實(shí)現(xiàn)的分布式鎖,一旦客戶(hù)端崩潰了,就沒(méi)有人去進(jìn)行釋放了,只能等超時(shí)。
鎖能自動(dòng)釋放有啥好處?除了提升并發(fā)度以外,還有個(gè)好處就是可以減少死鎖發(fā)生的概率。因?yàn)殒i釋放了,所以就不會(huì)出現(xiàn)死鎖了。
一致性&可用性要求(CAP)
我們分別介紹過(guò)關(guān)于 Redis和 Zookeeper 的 CAP 的實(shí)現(xiàn)情況,我們知道ZK 是一個(gè) CP 的系統(tǒng),也就是他是保證強(qiáng)一致性的,而 Redis 是一個(gè) AP 的系統(tǒng),它是保證可用性的。
ZK 會(huì)犧牲可用性來(lái)保證數(shù)據(jù)的一致性,即出現(xiàn)部分節(jié)點(diǎn)宕機(jī)后,集群中少于一半的節(jié)點(diǎn)后,或者集群正在進(jìn)行 master 選舉時(shí),都會(huì)拒絕新的寫(xiě)請(qǐng)求,導(dǎo)致無(wú)法加鎖。
而Redis 會(huì)犧牲一致性性來(lái)保證可用性,即 Redis 的集群中在做數(shù)據(jù)同步時(shí),如果出現(xiàn)網(wǎng)絡(luò)延遲,那么即使多個(gè)節(jié)點(diǎn)上面的數(shù)據(jù)不一樣,客戶(hù)端也可以正常的進(jìn)行寫(xiě)入和讀取。
那么,在使用 ZK 的分布式鎖的時(shí)候,不會(huì)存在鎖丟失的情況,也就是說(shuō)不太會(huì)出現(xiàn)因?yàn)殒i丟失而導(dǎo)致并發(fā)的情況。但是,可能會(huì)出現(xiàn)短暫的無(wú)法加鎖的情況。
而在使用 Redis 的分布式鎖的時(shí)候,除非集群都掛了,要不然不太會(huì)出現(xiàn)無(wú)法加鎖的情況。但是可能會(huì)出現(xiàn)鎖丟失的情況,或者說(shuō)是重復(fù)加鎖的情況,我們介紹 RedLock 的時(shí)候提到的單點(diǎn)故障的問(wèn)題。(詳見(jiàn)我八股文中關(guān)于《什么是RedLock,他解決了什么問(wèn)題》)
做個(gè)總結(jié)
Redis 實(shí)現(xiàn)的分布式鎖、性能更好,可用性更高。ZK 實(shí)現(xiàn)的分布式鎖可以自動(dòng)釋放,減少死鎖出現(xiàn)的概率,并且他的一致性更有保障。
所以,如果你的分布式鎖使用場(chǎng)景,對(duì)性能要求更高,可以犧牲一點(diǎn)一致性,那么就選擇 Redis的分布式鎖。而如果你的場(chǎng)景對(duì)性能要求沒(méi)那么高,但是對(duì)一致性要求非常高,那么則可以選擇 Zookeeper
But
凡事都有個(gè) but,下面就是一些經(jīng)驗(yàn)之談了。
其實(shí),如果你對(duì)可用性的要求高的話(huà),用 Redis 也行,因?yàn)橛袀€(gè) RedLock,他的機(jī)制和 zk 很像,都是通過(guò)半數(shù)以上提交這種方式來(lái)避免因?yàn)閱吸c(diǎn)問(wèn)題而導(dǎo)致鎖重復(fù)的。
但是,RedLock 其實(shí)我也不建議大家用,并且 ZK的分布式鎖我其實(shí)也不建議大家用。就直接用 Redis 就好了。(詳見(jiàn)我的八股文中《Redisson 中為什么要廢棄 RedLock,該用啥?》)
為啥呢?因?yàn)橐话銇?lái)說(shuō),我們?cè)谟梅植际芥i的時(shí)候,對(duì)性能要求肯定很高的,如果不高的話(huà),你直接用數(shù)據(jù)庫(kù)的悲觀鎖就好了。沒(méi)必要用分布式鎖。
而且,往往我們?cè)谟梅植际芥i的時(shí)候,同時(shí)會(huì)伴隨著冪等性判斷、以及數(shù)據(jù)庫(kù)兜底的唯一性約束的校驗(yàn)。所以,即使出現(xiàn)了極端情況,因?yàn)?Redis 的一致性沒(méi)保證好,導(dǎo)致重復(fù)加鎖了,我們也能在后續(xù)的環(huán)節(jié)中識(shí)別并防止并發(fā)。
而 Redis 的不可用的問(wèn)題其實(shí)可以通過(guò)哨兵、集群等運(yùn)維手段來(lái)解決的,所以,發(fā)生的概率本來(lái)就極低。所以說(shuō),日常開(kāi)發(fā)的時(shí)候,只要我們把冪等判斷、唯一性約束做好,對(duì)賬最好,用 Redis 是最簡(jiǎn)單,高效的辦法。
而且,Redis 作為一個(gè)緩存框架,很多應(yīng)用都會(huì)直接依賴(lài),直接用SETNX 或者 Redisson 加鎖不要太方便。而 Zookeeper,很多都是中間件在使用他, 真正的業(yè)務(wù)應(yīng)用依賴(lài)的很少的,多引入一個(gè)底層中間件,對(duì)系統(tǒng)來(lái)說(shuō)也會(huì)提升復(fù)雜度,減少整體的穩(wěn)定性的。
除非你真的完全接受不了不一致性,完全不能接受重復(fù)加鎖,有很愿意依賴(lài) zookeeper,那當(dāng)我沒(méi)說(shuō),我認(rèn)為這種情況少之又少。