10. 分布式鎖有哪些場景

如何理解分布式鎖

為了保證在多線程下處理共享數(shù)據(jù)的安全性扣孟,需要保證同一時刻只有一個線程能處理共享數(shù)據(jù)
Java 語言提供了線程鎖,開放了處理鎖機制的 API荣赶,比如 Synchronized凤价,Lock 等
當一個鎖被某個線程持有時,另一個線程嘗試去獲取這個鎖會失敗或者阻塞
直到持有鎖的線程釋放了該鎖
單臺服務(wù)器內(nèi)存拔创,可以通過線程加鎖的方式來同步利诺,避免并發(fā)問題


20230802102622.jpg

分布式鎖的常用實現(xiàn)

20230802102720.jpg
基于關(guān)系型數(shù)據(jù)庫

基于關(guān)系型數(shù)據(jù)庫實現(xiàn)分布式鎖,是依賴數(shù)據(jù)庫的唯一性來實現(xiàn)資源鎖定剩燥,比如主鍵和唯一索引等
以唯一索引為例慢逾,創(chuàng)建一張鎖表,定義方法或資源名灭红,失效時間等字段
同時針對鎖的信息添加唯一索引侣滩,比如方法名
當要鎖住某個方法或資源時,就在該表中插入對應(yīng)方法的一條記錄
插入成功表示獲取了鎖变擒,想要釋放鎖的時候就刪除這條記錄

  • 創(chuàng)建一張基于數(shù)據(jù)庫的分布式鎖表
CREATE TABLE `methodLock` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `method_name` varchar(64) NOT NULL DEFAULT '' COMMENT '鎖定的方法或資源',
  PRIMARY KEY (`id`),
  UNIQYE KEY `uidx_method_name` (`method_name`) USIGN BTREE
)ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='對方法加鎖';

當希望對某個方法加鎖時君珠,執(zhí)行以下SQL語句

insert into methodLock(method_name) values ('method_name'); 

如果有多個請求同時提交到數(shù)據(jù)庫的話,數(shù)據(jù)庫會保證只有一個操作可以成功
可以認為操作成功的那個線程獲得了該方法的鎖娇斑,可以執(zhí)行后面的業(yè)務(wù)邏輯
當方法執(zhí)行完畢后策添,想要釋放鎖,在數(shù)據(jù)庫中刪除對應(yīng)的記錄即可

優(yōu)化
  • 存在單點故障風險
    數(shù)據(jù)實現(xiàn)方式強依賴數(shù)據(jù)庫的可用性毫缆,一旦數(shù)據(jù)庫掛掉唯竹,則會導(dǎo)致業(yè)務(wù)系統(tǒng)不可用
    解決方法:配置數(shù)據(jù)庫主從機器,防止單點故障
  • 超時無法失效
    一旦解鎖操作失敗苦丁,會導(dǎo)致鎖記錄一直在數(shù)據(jù)庫中浸颓,其他線程無法再獲得鎖
    解決方法:可以添加獨立的定時任務(wù),通過時間戳對比等方式,刪除超時數(shù)據(jù)
  • 不可重入
    以Java語言為例猾愿,常見的Synchronize鹦聪,Lock 等都支持可重入
    在數(shù)據(jù)庫實現(xiàn)方式中,同一個線程在沒有釋放鎖
    實現(xiàn)可重入蒂秘,需要改造加鎖方法泽本,額外存儲在判斷線程信息,不阻塞獲得鎖的線程再次請求加鎖
  • 對阻塞操作不友好
    其他線程在請求對應(yīng)方法時姻僧,插入數(shù)據(jù)失敗會直接返回,不會阻塞線程
    如果需要阻塞其他線程撇贺,需要不斷的重試 insert 操作,直到數(shù)據(jù)插入成功

應(yīng)用 Redis 緩存

緩存的性能更好艘狭,各種緩存組件也提供了多種集群方案翠订,可以解決單點問題
常見的開源緩存組件都支持分布式鎖,包括 Redis尽超,Memcached 即 Tair
應(yīng)用 Redis 實現(xiàn)分布式鎖,最直接的想法是利用 setnx 和 expire 命令實現(xiàn)加鎖
在 Redis 中傲绣,setnx 是【set if not exists】如果不存在巩踏,則 SET 的意思

  • 當一個線程執(zhí)行 setnx 返回 1 ,說明 key 不存在顷链,該線程獲得鎖
  • 當一個線程執(zhí)行 setnx 返回 0 屈梁,說明key 已存在在讶,獲取鎖失敗
if (setnx(key, value) == 1) {
  expire(key, expireTime)
  try {
    // 業(yè)務(wù)處理
  } finally {
    // 釋放鎖
    del(key)
  }
}

在 Redis 版本更新中霜大,添加了 SETEX 命令
SETEX 支持 setnx 和 expire 指令組合的原子操作
解決了加鎖過程中失敗的問題

基于 ZooKeeper 實現(xiàn)

ZooKeeper 有四種節(jié)點類型:

  • 持久節(jié)點
  • 持久順序節(jié)點
  • 臨時節(jié)點
  • 臨時順序節(jié)點
利用 ZooKeeper 支持臨時順序節(jié)點的特性,可以實現(xiàn)分布式鎖
20230802111918.jpg

當客戶端對某個方法加鎖時残拐,在 ZooKeeper中該方法對指定節(jié)點目錄下生成唯一有序節(jié)點碟嘴。
判斷是否獲取鎖,只需要判斷持有的節(jié)點是否是有序節(jié)點中的序號最小的一個
當釋放鎖的時候娜扇,將這個臨時節(jié)點刪除即可
這種方法可以避免服務(wù)宕機導(dǎo)致的鎖無法釋放而產(chǎn)生的死鎖問題

使用 Zookeeper 實現(xiàn)分布式鎖的算法流程,根節(jié)點為 /lock
  • 客戶端連接 ZooKeeper 枢析,并在 /lock 下創(chuàng)建臨時有序子節(jié)點
    第一個客戶端對應(yīng)的子節(jié)點為 /lock/lock01/0000001 ,第二個為 /locl/lock01/00000002
  • 其他客戶端獲取 /lock01 下的子節(jié)點列表刃麸,判斷自己創(chuàng)建的子節(jié)點是否為當前列表中序號最小的子節(jié)點
  • 如果是則任務(wù)獲得鎖,執(zhí)行業(yè)務(wù)代碼把沼,否則通過 watch 事件監(jiān)聽 /lock01 的子節(jié)點變更消息脱吱,獲得變更通知后重復(fù)此步驟直至獲得鎖
  • 完成業(yè)務(wù)流程后,刪除對應(yīng)的子節(jié)點续捂,釋放分布式鎖

在實際開發(fā)中宦搬,可以應(yīng)用 Apache Curator 來快速實現(xiàn)分布式鎖
Curator 是 Netflix 公司開源的一個 ZooKeeper 客戶端
對 ZooKeeper 原生 API 做了抽象和封裝

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末间校,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子憔足,更是在濱河造成了極大的恐慌,老刑警劉巖控妻,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弓候,死亡現(xiàn)場離奇詭異郎哭,居然都是意外死亡夸研,警方通過查閱死者的電腦和手機依鸥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門毕籽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人关筒,你說我怎么就攤上這事∷埽” “怎么了袍榆?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長包雀。 經(jīng)常有香客問我,道長葡兑,這世上最難降的妖魔是什么赞草? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮洲守,結(jié)果婚禮上沾凄,老公的妹妹穿的比我還像新娘。我一直安慰自己叙谨,他們只是感情好,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著配椭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪衡楞。 梳的紋絲不亂的頭發(fā)上敦姻,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機與錄音迷守,去河邊找鬼旺入。 笑死,一個胖子當著我的面吹牛茵瘾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播圣絮,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼雕旨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了餐禁?” 一聲冷哼從身側(cè)響起突照,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎末盔,沒想到半個月后座慰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡游盲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了益缎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡欣范,死狀恐怖令哟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情晴竞,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布颓鲜,位于F島的核電站甜滨,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏衣摩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一艾扮、第九天 我趴在偏房一處隱蔽的房頂上張望泡嘴。 院中可真熱鬧,春花似錦酌予、人聲如沸奖慌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至棉姐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間伞矩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留盲镶,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓枫吧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親九杂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

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