關于分布式鎖原理的一些學習與思考-redis分布式鎖贱田,zookeeper分布式鎖

首先分布式鎖和我們平常講到的鎖原理基本一樣缅茉,目的就是確保,在多個線程并發(fā)時男摧,只有一個線程在同一刻操作這個業(yè)務或者說方法蔬墩、變量。

在一個進程中耗拓,也就是一個jvm 或者說應用中拇颅,我們很容易去處理控制,在jdk java.util 并發(fā)包中已經(jīng)為我們提供了這些方法去加鎖乔询, 比如synchronized 關鍵字 或者Lock 鎖樟插,都可以處理。

但是我們現(xiàn)在的應用程序如果只部署一臺服務器竿刁,那并發(fā)量是很差的黄锤,如果同時有上萬的請求那么很有可能造成服務器壓力過大,而癱瘓食拜。

想想雙十一 和 三十晚上十點分支付寶紅包等業(yè)務場景鸵熟,自然需要用到多臺服務器去同時處理這些業(yè)務,那么這些服務可能會有上百臺同時處理负甸,

但是請我們大家想一想流强,如果有100臺服務器 要處理分紅包的業(yè)務,現(xiàn)在假設有1億的紅包惑惶,1千萬個人分煮盼,金額隨機,那么這個業(yè)務場景下是不是必須確保這1千萬個人最后分的紅包金額總和等于1億带污。

如果處理不好~~每人分到100萬,那馬云爸爸估計大年初一香到,就得宣布破產(chǎn)了

1鱼冀,常規(guī)鎖會造成什么情況报破?

首先說一下我們?yōu)槭裁匆慵海唵卫斫饩褪乔鳎枨罅浚ㄕ埱蟛l(fā)量)變大了充易,一個工人處理能力有限,那就多招一些工人來一起處理荸型。

假設1千萬個請求平均分配到100臺服務器上盹靴,每個服務器 接收10w的請求(這10w個請求并不是在同一秒中來的,可能是在1,2個小時內(nèi)瑞妇,可以聯(lián)想下我們?nèi)砩祥_紅包稿静,等到10.20開始,有的人立馬開了辕狰,有的人是不是等到12點了才想起來~)

那這樣的話改备,平均到每一秒上的請求也就不到1千個,這種壓力一般的服務器還是可以承受的蔓倍。

第一個請求到來后悬钳,是不是需要在1億里面給他分一部分錢,金額隨機偶翅,假設第一個人分到了100默勾,那是不是要在這1億中減去100塊,剩下99999900 塊~

第二個用戶再來分聚谁,金額隨機母剥,這次分200塊,那是不是就需要在剩下的99999900塊中再減去200塊垦巴,剩下99999700 塊媳搪。

等到第10w個用戶來,一看還有1000w骤宣,那這1000w全成他的了秦爆。

等于是在每個服務器中去分1億,也就是10w個用戶分了一個億憔披,最后總計有100個服務器等限,要分100億。

如果真這樣了芬膝,雖說馬云爸爸不會破產(chǎn)(據(jù)最新統(tǒng)計馬云有2300億人民幣)望门,那分紅包的開發(fā)項目組,以及產(chǎn)品經(jīng)理锰霜,可以GG了~

簡化結構圖如下:

image

2筹误,分布式鎖怎么去處理?

那么為了解決這個問題癣缅,讓1000萬用戶只分1億厨剪,而不是100億哄酝,這個時候分布式鎖就派上用處了。

分布式鎖可以把整個集群就當作是一個應用一樣去處理祷膳,那么也就需要這個鎖陶衅,要獨立于每一個服務之外,而不是在服務里面直晨。

假設第一個服務器接收到用戶1的請求后搀军,那么這個時候,他就不能只在自己的應用中去判斷還有多少錢可以分了勇皇,而需要去外部請求專門負責管理這1億紅包的人(服務)罩句,問他:哎,我這里要分100塊儒士,給我100的止。

管理紅包的妹子(服務)一看,還有1個億着撩,那好诅福,給你100塊,然后剩下99999900塊拖叙。

第二個請求到來后氓润,被服務器2獲取,繼續(xù)去詢問薯鳍,管理紅包的妹子咖气,我這邊要分10塊,管理紅包的妹子先查了下還有99999900挖滤,那就說:好崩溪,給你10塊。那就剩下99999890塊

等到第1000w個請求到來后斩松,服務器100拿到請求伶唯,繼續(xù)去詢問,管理紅包的妹子惧盹,你要100乳幸,妹子翻了翻白眼,對你說钧椰,就剩1塊了粹断,愛要不要,那這個時候就只能給你1塊了(1塊也是錢啊嫡霞,買根辣條還是可以的)瓶埋。

這些請求編號1,2不代表執(zhí)行的先后順序,正式的場景下,應該是 100臺服務器每個服務器持有一個請求去訪問負責管理紅包的妹子(服務)悬赏,那在管紅包的妹子那里同時會接收到100個請求狡汉,這個時候就需要在負責紅包的妹子那里加個鎖就可以了(拋繡球)娄徊,你們100個服務器誰拿到鎖(搶到繡球)闽颇,誰就進來和我談,我給你分寄锐,其他人就等著去吧

經(jīng)過上面的分布式鎖的處理后兵多,馬云爸爸終于放心了,決定給紅包團隊每人加一個雞腿橄仆。

簡化的結構圖如下:

image

3剩膘,分布式鎖的實現(xiàn)有哪些?

說到分布式鎖的實現(xiàn)盆顾,還是有很多的怠褐,有數(shù)據(jù)庫方式的,有redis分布式鎖您宪,有zookeeper分布式鎖等等

我們?nèi)绻捎胷edis作為分布式鎖奈懒,那么上圖中負“責紅包的妹子(服務)”,就可以替換成redis宪巨,請自行腦補磷杏。

3.1,為什么redis可以實現(xiàn)分布式鎖捏卓?

首先redis是單線程的极祸,這里的單線程指的是網(wǎng)絡請求模塊使用了一個線程(所以不需考慮并發(fā)安全性),即一個線程處理所有網(wǎng)絡請求怠晴,其他模塊仍用了多個線程遥金。

在實際的操作中過程大致是這樣子的:

服務器1要去訪問發(fā)紅包的妹子,也就是redis蒜田,那么他會在redis中通過"setnx key value" 操作設置一個key 進去稿械,value是啥不重要,重要的是要有一個key物邑,也就是一個標記溜哮,而且這個key你愛叫啥叫啥,只要所有的服務器設置的key相同就可以色解。

假設我們設置一個茂嗓,如下圖

image

那么我們可以看到會返回一個1,那就代表了成功科阎。

如果再來一個請求去設置同樣的key述吸,如下圖:

image

這個時候會返回0,那就代表失敗了。

那么我們就可以通過這個操作去判斷是不是當前可以拿到鎖蝌矛,或者說可以去訪問“負責發(fā)紅包的妹子”道批,如果返回1,那我就開始去執(zhí)行后面的邏輯入撒,如果返回0隆豹,那就說明已經(jīng)被人占用了,我就要繼續(xù)等待茅逮。

當服務器1拿到鎖之后璃赡,進行了業(yè)務處理,完成后献雅,還需要釋放鎖碉考,如下圖所示:

image

刪除成功返回1,那么其他的服務器就可以繼續(xù)重復上面的步驟去設置這個key挺身,以達到獲取鎖的目的侯谁。

當然以上的操作是在redis客戶端直接進行的,通過程序調(diào)用的話章钾,肯定就不能這么寫墙贱,比如java 就需要通過jedis 去調(diào)用,但是整個處理邏輯基本都是一樣的

通過上面的方式伍玖,我們好像是解決了分布式鎖的問題嫩痰,但是想想還有沒有什么問題呢?窍箍?

對串纺,問題還是有的,可能會有死鎖的問題發(fā)生椰棘,比如服務器1設置完之后纺棺,獲取了鎖之后,忽然發(fā)生了宕機邪狞。

那后續(xù)的刪除key操作就沒法執(zhí)行祷蝌,這個key會一直在redis中存在,其他服務器每次去檢查帆卓,都會返回0巨朦,他們都會認為有人在使用鎖,我需要等剑令。

為了解決這個死鎖的問題糊啡,我們就就需要給key 設置有效期了。

設置的方式有2種

1吁津,第一種就是在set完key之后棚蓄,直接設置key的有效期 "expire key timeout" ,為key設置一個超時時間,單位為second梭依,超過這個時間鎖會自動釋放稍算,避免死鎖。

這種方式相當于役拴,把鎖持有的有效期糊探,交給了redis去控制。如果時間到了扎狱,你還沒有給我刪除key侧到,那redis就直接給你刪了,其他服務器就可以繼續(xù)去setnx獲取鎖淤击。

2,第二種方式故源,就是把刪除key權利交給其他的服務器污抬,那這個時候就需要用到value值了,

比如服務器1绳军,設置了value 也就是 timeout 為 當前時間+1 秒 印机,這個時候服務器2 通過get 發(fā)現(xiàn)時間已經(jīng)超過系統(tǒng)當前時間了,那就說明服務器1沒有釋放鎖门驾,服務器1可能出問題了射赛,

服務器2就開始執(zhí)行刪除key操作,并且繼續(xù)執(zhí)行setnx 操作奶是。

但是這塊有一個問題楣责,也就是,不光你服務器2可能會發(fā)現(xiàn)服務器1超時了聂沙,服務器3也可能會發(fā)現(xiàn)秆麸,如果剛好,服務器2及汉,setnx操作完成沮趣,服務器3就接著刪除,是不是服務器3也可以setnx成功了坷随?

那就等于是服務器2和服務器3都拿到鎖了房铭,那就問題大了。這個時候怎么辦呢温眉?

這個時候需要用到 “GETSET key value” 命令了缸匪。這個命令的意思就是獲取當前key的值,并且設置新的值芍殖。

假設服務器2發(fā)現(xiàn)key過期了豪嗽,開始調(diào)用 getset 命令,然后用獲取的時間判斷是否過期,如果獲取的時間仍然是過期的龟梦,那就說明拿到鎖了隐锭。

如果沒有,則說明在服務2執(zhí)行getset之前计贰,服務器3可能也發(fā)現(xiàn)鎖過期了钦睡,并且在服務器2之前執(zhí)行了getset操作,重新設置了過期時間躁倒。

那么服務器2就需要放棄后續(xù)的操作荞怒,繼續(xù)等待服務器3釋放鎖或者去監(jiān)測key的有效期是否過期。

這塊其實有一個小問題是秧秉,服務器3已經(jīng)修改了有效期褐桌,拿到鎖之后,服務器2象迎,也修改了有效期荧嵌,但是沒能拿到鎖,但是這個有效期的時間已經(jīng)被在服務器3的基礎上有增加一些砾淌,但是這種影響其實還是很小的啦撮,幾乎可以忽略不計。

3.2汪厨,為什么zookeeper可以實現(xiàn)分布式鎖赃春?

百度百科是這么介紹的:ZooKeeper是一個分布式的,開放源碼的分布式應用程序協(xié)調(diào)服務劫乱,是Google的Chubby一個開源的實現(xiàn)织中,是Hadoop和Hbase的重要組件糯耍。

那對于我們初次認識的人析显,可以理解成ZooKeeper就像是我們的電腦文件系統(tǒng)钳枕,我們可以在d盤中創(chuàng)建文件夾a脱盲,并且可以繼續(xù)在文件夾a中創(chuàng)建 文件夾a1适肠,a2双絮。

那我們的文件系統(tǒng)有什么特點蛀柴?佣耐?那就是同一個目錄下文件名稱不能重復拉一,同樣ZooKeeper也是這樣的采盒。

在ZooKeeper所有的節(jié)點,也就是文件夾稱作 Znode蔚润,而且這個Znode節(jié)點是可以存儲數(shù)據(jù)的磅氨。

我們可以通過“ create /zkjjj nice” 來創(chuàng)建一個節(jié)點,這個命令就表示嫡纠,在跟目錄下創(chuàng)建一個zkjjj的節(jié)點烦租,值是nice延赌。同樣這里的值,和我在前面說的redis中的一樣叉橱,沒什么意義挫以,你隨便給。

另外ZooKeeper可以創(chuàng)建4種類型的節(jié)點窃祝,分別是:

1掐松,持久性節(jié)點

2,持久性順序節(jié)點

3粪小,臨時性節(jié)點

4大磺,臨時性順序節(jié)點

首先說下持久性節(jié)點和臨時性節(jié)點的區(qū)別,持久性節(jié)點表示只要你創(chuàng)建了這個節(jié)點探膊,那不管你ZooKeeper的客戶端是否斷開連接杠愧,ZooKeeper的服務端都會記錄這個節(jié)點。

臨時性節(jié)點剛好相反突想,一旦你ZooKeeper客戶端斷開了連接殴蹄,那ZooKeeper服務端就不再保存這個節(jié)點。

再說下順序性節(jié)點猾担,順序性節(jié)點是指,在創(chuàng)建節(jié)點的時候刺下,ZooKeeper會自動給節(jié)點編號比如0000001 绑嘹,0000002 這種的。

最后說下橘茉,zookeeper有一個監(jiān)聽機制工腋,客戶端注冊監(jiān)聽它關心的目錄節(jié)點,當目錄節(jié)點發(fā)生變化(數(shù)據(jù)改變畅卓、被刪除擅腰、子目錄節(jié)點增加刪除)等,zookeeper會通知客戶端翁潘。

下面我們繼續(xù)結合我們上面的分紅包場景趁冈,描述下在zookeeper中如何加鎖。

假設服務器1拜马,創(chuàng)建了一個節(jié)點 /zkjjj ,成功了渗勘,那服務器1就獲取了鎖,服務器2再去創(chuàng)建相同的鎖俩莽,那么他就會失敗旺坠,這個時候他就就只能監(jiān)聽這個節(jié)點的變化。

等到服務器1扮超,處理完業(yè)務取刃,刪除了節(jié)點后蹋肮,他就會得到通知,然后去創(chuàng)建同樣的節(jié)點璧疗,獲取鎖處理業(yè)務坯辩,再刪除節(jié)點,后續(xù)的100臺服務器與之類似

注意這里的100臺服務器并不是挨個去執(zhí)行上面的創(chuàng)建節(jié)點的操作病毡,而是并發(fā)的濒翻,當服務器1創(chuàng)建成功,那么剩下的99個就都會注冊監(jiān)聽這個節(jié)點啦膜,等通知有送,以此類推。

但是大家有沒有注意到僧家,這里還是有問題的雀摘,還是會有死鎖的情況存在,對不對八拱?

當服務器1創(chuàng)建了節(jié)點后掛了阵赠,沒能刪除,那其他99臺服務器就會一直等通知肌稻,那就完蛋了清蚀。。爹谭。

這個時候呢枷邪,就需要用到臨時性節(jié)點了,我們前面說過了诺凡,臨時性節(jié)點的特點是客戶端一旦斷開东揣,就會丟失,也就是當服務器1創(chuàng)建了節(jié)點后腹泌,如果掛了嘶卧。

那這個節(jié)點會自動被刪除,這樣后續(xù)的其他服務器凉袱,就可以繼續(xù)去創(chuàng)建節(jié)點芥吟,獲取鎖了。

但是我們可能還需要注意到一點绑蔫,就是驚群效應:舉一個很簡單的例子,當你往一群鴿子中間扔一塊食物,雖然最終只有一個鴿子搶到食物,但所有鴿子都會被驚動來爭奪,沒有搶到..

就是當服務器1節(jié)點有變化运沦,會通知其余的99個服務器,但是最終只有1個服務器會創(chuàng)建成功配深,這樣98還是需要等待監(jiān)聽携添,那么為了處理這種情況,就需要用到臨時順序性節(jié)點

大致意思就是篓叶,之前是所有99個服務器都監(jiān)聽一個節(jié)點烈掠,現(xiàn)在就是每一個服務器監(jiān)聽自己前面的一個節(jié)點羞秤。

假設100個服務器同時發(fā)來請求,這個時候會在 /zkjjj 節(jié)點下創(chuàng)建 100 個臨時順序性節(jié)點 /zkjjj/000000001, /zkjjj/000000002,一直到 /zkjjj/000000100,這個編號就等于是已經(jīng)給他們設置了獲取鎖的先后順序了左敌。

當001節(jié)點處理完畢瘾蛋,刪除節(jié)點后,002收到通知矫限,去獲取鎖哺哼,開始執(zhí)行,執(zhí)行完畢叼风,刪除節(jié)點取董,通知003~以此類推。

歡迎工作一到五年的Java工程師朋友們加入Java架構開發(fā): 957734884无宿,群內(nèi)提供免費的Java架構學習資料(里面有高可用茵汰、高并發(fā)、高性能及分布式孽鸡、Jvm性能調(diào)優(yōu)蹂午、Spring源碼,MyBatis彬碱,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己豆胸,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕巷疼,使勁拼配乱,給未來的自己一個交代!

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末皮迟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子桑寨,更是在濱河造成了極大的恐慌伏尼,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尉尾,死亡現(xiàn)場離奇詭異爆阶,居然都是意外死亡,警方通過查閱死者的電腦和手機沙咏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門辨图,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肢藐,你說我怎么就攤上這事故河。” “怎么了吆豹?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵鱼的,是天一觀的道長。 經(jīng)常有香客問我猿规,道長,這世上最難降的妖魔是什么环葵? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任猬仁,我火速辦了婚禮的烁,結果婚禮上渴庆,老公的妹妹穿的比我還像新娘襟雷。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般击罪。 火紅的嫁衣襯著肌膚如雪眠副。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天岛宦,我揣著相機與錄音挽霉,去河邊找鬼。 笑死实胸,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼慕匠,長吁一口氣:“原來是場噩夢啊……” “哼譬挚!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤女坑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡具被,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年玻募,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片一姿。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡七咧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出叮叹,到底是詐尸還是另有隱情艾栋,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布蛉顽,位于F島的核電站蝗砾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜悼粮,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一闲勺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧扣猫,春花似錦菜循、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瀑凝,卻和暖如春序芦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背粤咪。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工谚中, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人寥枝。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓宪塔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親囊拜。 傳聞我的和親對象是個殘疾皇子某筐,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 2018.2.26 星期日農(nóng)歷正月十一 晴 讀經(jīng)時間:第41周,第1天 總計281天 讀經(jīng)人員:媽媽和景琪 讀經(jīng)內(nèi)...
    張鳳茹閱讀 222評論 0 0
  • 人與人會逐漸疏遠冠跷,而這疏遠主要是我造成的南誊。 一個朋友,旅游認識的蜜托,難得遇到我感興趣的人抄囚,幾乎一年的時間里,每天都要...
    朝飲木蘭之墜露兮Y閱讀 331評論 0 3
  • 思念成災橄务, 每天想你千遍萬遍幔托, 愛在心頭啞口無言, 我借夏雨蜂挪, 偷偷看你一重挑, 我借夏風, 吻你千遍萬遍棠涮。 回憶里的...
    冰糖檸檬閱讀 230評論 0 2
  • 人被三個圈包圍:信息攒驰、知識、能力故爵。 把信息篩選出來內(nèi)化為知識用起來就是能力。 這也是“越努力越幸運”的理論基礎,廣...
    依盈閱讀 644評論 0 0