分布式鎖

一 鎖的理解

作為一個(gè)編程人員,一般對(duì)鎖都比較熟悉。鎖车份,在生活中就是控制對(duì)一個(gè)資源的獨(dú)特占有權(quán),比如我用一把鎖鎖上自行車牡彻,這輛自行車在鎖上期間是完全屬于我的扫沼,因?yàn)橹挥形矣羞@個(gè)鎖的鑰匙;當(dāng)然如果我鎖上自行車庄吼,我也沒辦法騎車了:)缎除,也就是說現(xiàn)實(shí)中的鎖只是自己不使用的時(shí)候,一種獨(dú)特的防止別人來用的手段总寻,是一種防止共享的手段器罐。

計(jì)算機(jī)中鎖只是借助這種獨(dú)特的占有權(quán)的思想(算是臨時(shí)占有權(quán)),和現(xiàn)實(shí)中相反的是渐行,鎖是為了共享轰坊,是為了更好地共享,解決共享沖突而采用的手段祟印;在現(xiàn)實(shí)生活中肴沫,上鎖了,任何人無法使用了旁理;計(jì)算中上了鎖樊零,只能自己使用了,用完之后孽文,釋放了鎖驻襟,其他使用者才可以訪問。

由于計(jì)算機(jī)發(fā)展中多核芋哭,多cpu的出現(xiàn)沉衣,或者因?yàn)橐恍㊣O密集型程序,需要等待IO操作减牺,如果需要提高應(yīng)用的整體性能豌习,只能提高并發(fā)性,比如增加線程拔疚,增加進(jìn)程等肥隆。但是有些資源確實(shí)需要共享的,比如售票系統(tǒng)或電子商務(wù)系統(tǒng)稚失,票數(shù)或待售物品栋艳。這樣就帶來了,如何控制多個(gè)執(zhí)行體同一時(shí)刻訪問資源的問題句各,以免發(fā)生沖突吸占。

二 鎖的分類

鎖有很多種分類方法晴叨,有悲觀鎖,樂觀鎖矾屯;數(shù)據(jù)庫中的鎖有行級(jí)鎖兼蕊,表級(jí)鎖;悲觀鎖件蚕,就是認(rèn)為任務(wù)資源大部分時(shí)間是被別人占用的孙技,所以每次訪問均需要加鎖,如果加鎖不成功要么等待骤坐,要么報(bào)錯(cuò)绪杏,使用完成后,釋放鎖別人才可以使用纽绍;樂觀鎖就是樂觀地認(rèn)為需要訪問的資源是自己獨(dú)占的蕾久,每次直接操作,但是訪問控制還是要做的拌夏,如何做那僧著,這里面一般通過版本號(hào)來控制,比如數(shù)據(jù)庫中的多版本障簿,solr查詢中的多版本盹愚。

舉個(gè)樂觀鎖的例子,比如我們?cè)诟聅olr的索引中的字段的時(shí)候站故,可以帶上:version字段信息:

1. 如果_version_<0  如果文檔存在皆怕,則拒絕更新,不存在就添加西篓。
2.如果_version_= 0 如果文檔存在愈腾,則更新,不存在則添加岂津。
3.如果_version_ =1 如果文檔存在虱黄,則更新;不存在則拒絕更新吮成。
4.如果_version_ > 1 如果文檔的版本號(hào)和verison一致橱乱,則更新,不一致則拒絕粱甫。[這里面就用樂觀鎖的機(jī)制泳叠,通過版本號(hào)來解決并發(fā)沖突問題]

在Java中synchronized就是重量級(jí)鎖,是悲觀鎖茶宵;Java中通過CAS思想實(shí)現(xiàn)的類都是采用樂觀鎖的機(jī)制析二,比如java.util.concurrent.atomaic類。

三 分布式鎖

在編程中,Java中最常用的鎖比如synchronized等叶摄,ReentrantLock 等鎖,只適合單JVM環(huán)境安拟,沒辦法跨JVM共享的蛤吓,所以在剛才提到的大型的售票系統(tǒng),或電子商務(wù)中等高并發(fā)系統(tǒng)中糠赦,需要分布式鎖來控制共享資源的訪問会傲。

3.1 數(shù)據(jù)庫實(shí)現(xiàn)的分布式鎖

最簡(jiǎn)單的實(shí)現(xiàn),是通過select for update拙泽,這種方法鎖住了當(dāng)前數(shù)據(jù)淌山,防止其他并發(fā)進(jìn)程來操作。
好處:解決了分布式鎖的問題顾瞻;
壞處:
1)這種鎖會(huì)一直鎖住數(shù)據(jù)泼疑,直到事務(wù)提交時(shí)候才會(huì)釋放鎖。
2)需要設(shè)置事務(wù)的隔離級(jí)別為read commited荷荤,如果設(shè)置到其他高并發(fā)的級(jí)別退渗,仍然會(huì)其他線程讀到未提交數(shù)據(jù),從而導(dǎo)致超賣的可能蕴纳。
3)如果事務(wù)的操作時(shí)間太長(zhǎng)会油,長(zhǎng)時(shí)間不釋放,則容易打滿數(shù)據(jù)庫連接古毛;特別是事務(wù)操作中翻翩,還有第三方接口調(diào)用的時(shí)候。
4)容易產(chǎn)生交叉死鎖稻薇,在業(yè)務(wù)加鎖的時(shí)候要控制下加表的順序嫂冻,如果控制不好就會(huì)產(chǎn)生交叉死鎖的問題。

3.2 使用zooKeeper實(shí)現(xiàn)分布式鎖

作為分布式協(xié)調(diào)系統(tǒng)颖低,zooKeeper支持四種節(jié)點(diǎn)類型:
1.持久性節(jié)點(diǎn)絮吵。
2.持久性順序節(jié)點(diǎn)。
3.臨時(shí)節(jié)點(diǎn)忱屑。
4.臨時(shí)性順序節(jié)點(diǎn)蹬敲。
所謂臨時(shí)節(jié)點(diǎn),是通過客戶端心跳來控制的莺戒,如果客戶端掛了伴嗡,則超過一定時(shí)間沒有心跳連接,zookeeper就會(huì)把這個(gè)臨時(shí)節(jié)點(diǎn)刪除掉从铲,防止客戶端突然掛掉而導(dǎo)致鎖一直無法釋放的問題瘪校。

我曾經(jīng)利用zk來實(shí)現(xiàn)一個(gè)鎖,來解決多個(gè)程序同時(shí)創(chuàng)建solr的collection問題,利用的是臨時(shí)節(jié)點(diǎn)阱扬,實(shí)現(xiàn)原理很簡(jiǎn)單:
1)每個(gè)入solr索引的進(jìn)程再查詢到solr的collection不存在的時(shí)候泣懊,會(huì)再特定的目錄下創(chuàng)建臨時(shí)節(jié)點(diǎn)。
2)如果多個(gè)進(jìn)程同時(shí)創(chuàng)建麻惶,肯定存在創(chuàng)建成功和失敗的情況馍刮,創(chuàng)建成功的就稱為leader,負(fù)責(zé)collection的新建窃蹋。
3)創(chuàng)建節(jié)點(diǎn)失敗的則進(jìn)行循環(huán)等待solr的collection的結(jié)果創(chuàng)建成功卡啰。

但是一般情況是比我這種復(fù)雜,比如電子商務(wù)中扣庫存的例子警没,多個(gè)客戶端同時(shí)發(fā)起扣庫存請(qǐng)求匈辱。不光需要控制只能有一個(gè)進(jìn)行資源操作,還需要控制訪問的順序杀迹,這時(shí)候就不能用這種簡(jiǎn)單的臨時(shí)節(jié)點(diǎn)亡脸,可以用臨時(shí)順序節(jié)點(diǎn)。
步驟如下:

  1. 每個(gè)應(yīng)用同時(shí)在一個(gè)特定的節(jié)點(diǎn)比如/app下去創(chuàng)建臨時(shí)順序節(jié)點(diǎn)佛南。
  2. 每個(gè)應(yīng)用對(duì)自己的前一個(gè)節(jié)點(diǎn)建立監(jiān)聽(如果有前一個(gè)節(jié)點(diǎn)的話)梗掰。
  3. 如果沒有比自己小的,則自己獲取鎖嗅回,可以進(jìn)行資源操作及穗。
  4. 有比他小序號(hào)的應(yīng)用,則這個(gè)應(yīng)用進(jìn)入等待绵载。
  5. 一個(gè)應(yīng)用刪除臨時(shí)順序節(jié)點(diǎn)后埂陆,監(jiān)聽它的節(jié)點(diǎn),則自動(dòng)獲取鎖娃豹,操作資源焚虱。
  6. 特殊情況:假如A節(jié)點(diǎn)順序號(hào)最小,B其次懂版,C最大鹃栽,這時(shí)候B監(jiān)聽A節(jié)點(diǎn),如果B突然掛掉了躯畴,C發(fā)現(xiàn)B掛掉了就會(huì)對(duì)上監(jiān)聽A節(jié)點(diǎn)民鼓,如果AB都同時(shí)掛掉了,由于是臨時(shí)節(jié)點(diǎn)蓬抄,所以它們都會(huì)被ZK清理丰嘉,所以也沒關(guān)系。

用這種方式進(jìn)行集群的leader選舉也是極好的嚷缭,只是ZK在存在大量節(jié)點(diǎn)監(jiān)聽的時(shí)候饮亏,會(huì)存在不穩(wěn)定的問題耍贾。
zk方式實(shí)現(xiàn)的分布式鎖,具有很好的性能路幸,而且zk一般是集群部署荐开,可靠性還是不錯(cuò)。

3.3 Redis實(shí)現(xiàn)的分布式鎖

redis 也是實(shí)現(xiàn)分布式鎖的常用手段劝赔,redis通常利用setnx來實(shí)現(xiàn)分布式鎖誓焦,key設(shè)置為鎖的id,value設(shè)置為當(dāng)前時(shí)間+超時(shí)時(shí)間着帽,或者value為線程id,同時(shí)設(shè)置超時(shí)時(shí)間移层;進(jìn)程獲取鎖后仍翰,如果在超時(shí)時(shí)間內(nèi)沒有釋放鎖,鎖會(huì)自動(dòng)釋放观话,這樣可以避免鎖一直無法釋放的問題予借。
setnx 有0或1兩個(gè)返回值。
返回1: 說明該進(jìn)程獲取了鎖频蛔,該進(jìn)程的設(shè)置成功灵迫。
返回0: 說明其他進(jìn)程已經(jīng)獲取到了鎖,進(jìn)程不能訪問共享資源晦溪,只能等待瀑粥。
這里面有個(gè)問題,就是如果在超時(shí)的時(shí)間范圍內(nèi)三圆,線程還沒有使用完共享資源狞换,比如線程A沒有完成業(yè)務(wù)操作,由于超時(shí)時(shí)間已到舟肉,鎖被釋放了修噪,這時(shí)候另外一個(gè)線程B意外的獲取到了鎖。然后A線程執(zhí)行完業(yè)務(wù)的時(shí)候路媚,就用del命令刪除了B線程創(chuàng)建的鎖黄琼,然后線程C再次獲取鎖成功,從而造成業(yè)務(wù)的錯(cuò)亂的問題整慎。
鎖的超時(shí)時(shí)間脏款,如果設(shè)置過長(zhǎng)了,如果一個(gè)擁有鎖的應(yīng)用掛了院领,則其他應(yīng)用很長(zhǎng)時(shí)間都獲取不了這個(gè)線程弛矛。對(duì)于這種情況,有個(gè)解決辦法是在加鎖的應(yīng)用中比然,增加個(gè)守護(hù)線程丈氓,守護(hù)線程定時(shí)判斷主業(yè)務(wù)操作資源是否結(jié)束,如果沒有結(jié)束,而超時(shí)時(shí)間就要結(jié)束了万俗,則增加這個(gè)key的超時(shí)時(shí)間湾笛,從而達(dá)到對(duì)鎖的續(xù)命的目的。

redis實(shí)現(xiàn)分布式鎖闰歪,因?yàn)閿?shù)據(jù)是放在內(nèi)存中的嚎研,性能也不錯(cuò);但是如果是單機(jī)的redis則存在著不可靠的問題库倘。

redis鎖我只是有所了解临扮,自己沒有親自嘗試過,需要使用這種分布式鎖的朋友教翩,還要多加驗(yàn)證杆勇。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市饱亿,隨后出現(xiàn)的幾起案子蚜退,更是在濱河造成了極大的恐慌,老刑警劉巖彪笼,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钻注,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡配猫,警方通過查閱死者的電腦和手機(jī)幅恋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來章姓,“玉大人佳遣,你說我怎么就攤上這事》惨粒” “怎么了零渐?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)系忙。 經(jīng)常有香客問我诵盼,道長(zhǎng),這世上最難降的妖魔是什么银还? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任风宁,我火速辦了婚禮,結(jié)果婚禮上蛹疯,老公的妹妹穿的比我還像新娘戒财。我一直安慰自己,他們只是感情好捺弦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布饮寞。 她就那樣靜靜地躺著孝扛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪幽崩。 梳的紋絲不亂的頭發(fā)上苦始,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音慌申,去河邊找鬼陌选。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蹄溉,可吹牛的內(nèi)容都是我干的咨油。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼柒爵,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼臼勉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起餐弱,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎囱晴,沒想到半個(gè)月后膏蚓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡畸写,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年驮瞧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枯芬。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡论笔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出千所,到底是詐尸還是另有隱情狂魔,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布淫痰,位于F島的核電站最楷,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏待错。R本人自食惡果不足惜籽孙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望火俄。 院中可真熱鬧犯建,春花似錦、人聲如沸瓜客。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至犹菇,卻和暖如春德迹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背揭芍。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工胳搞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人称杨。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓肌毅,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親姑原。 傳聞我的和親對(duì)象是個(gè)殘疾皇子悬而,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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

  • 分布式鎖定義 分布式鎖在分布式環(huán)境下笨奠,鎖定全局唯一公共資源,表現(xiàn)為: 請(qǐng)求串行化 互斥性 第一步是上鎖的資源目標(biāo)唤殴,...
    ___n閱讀 1,745評(píng)論 0 0
  • 什么是鎖般婆?在單進(jìn)程的系統(tǒng)中,當(dāng)存在多個(gè)線程可以同時(shí)改變某個(gè)變量(可變共享變量)時(shí)朵逝,就需要對(duì)變量或代碼塊做同步蔚袍,使其...
    康康不遛貓閱讀 1,035評(píng)論 0 5
  • 最近碰到幾個(gè)業(yè)務(wù)場(chǎng)景,會(huì)遇到并發(fā)的問題配名。在單實(shí)例情況下啤咽,我們會(huì)通過java.util.concurrent包...
    菜鳥小玄閱讀 2,254評(píng)論 0 5
  • 1、什么是鎖渠脉? 在單進(jìn)程的系統(tǒng)中宇整,當(dāng)存在多個(gè)線程可以同時(shí)改變某個(gè)變量(可變共享變量)時(shí),就需要對(duì)變量或代碼塊做同步...
    夏與清風(fēng)閱讀 156評(píng)論 0 1
  • 2018.5.7 我沒有游戲刺激连舍,沒有電影電視有趣没陡,更沒有手機(jī)那么誘人,我只是一個(gè)不重要的人索赏,只是你無聊時(shí)可以找的...
    煙花肆意O閱讀 202評(píng)論 0 0