摘要:分布式情況下這個(gè)就需要換成分布式鎖以保證數(shù)據(jù)一致性。三分布式鎖實(shí)現(xiàn)原理所需的依賴一個(gè)擁有強(qiáng)一致性的服務(wù)發(fā)現(xiàn)存儲(chǔ)倉庫。保證數(shù)據(jù)一致性一個(gè)具有高可用性的服務(wù)發(fā)現(xiàn)存儲(chǔ)倉庫。
一、基本概念
分布式鎖,是單機(jī)鎖的一種擴(kuò)展,主要是為了鎖住分布式系統(tǒng)中不同機(jī)器代碼的物理塊或邏輯塊。以此保證不同機(jī)器之間的邏輯一致性。二、一個(gè)簡(jiǎn)單的案例 對(duì)DB寫操作的雙檢鎖案例
偽代碼如下
if (可以插入一條數(shù)據(jù)) { lock { if (可以插入一條數(shù)據(jù)) { // 插入一條數(shù)據(jù) } } }
上面代碼中的lock如果是單機(jī)情況下的鎖的話,在一臺(tái)服務(wù)器多線程情況下是沒有問題的。但是如果是分布式的情況下,單機(jī)的鎖只能鎖住一臺(tái)服務(wù)器的物理代碼塊,是無法防住其他機(jī)器產(chǎn)生的臟數(shù)據(jù)的。
分布式情況下這個(gè)lock就需要換成分布式鎖以保證數(shù)據(jù)一致性。
三、分布式鎖實(shí)現(xiàn)原理 所需的依賴一個(gè)擁有強(qiáng)一致性的服務(wù)發(fā)現(xiàn)存儲(chǔ)倉庫。(保證數(shù)據(jù)一致性)
一個(gè)具有高可用性的服務(wù)發(fā)現(xiàn)存儲(chǔ)倉庫。(保證服務(wù)的穩(wěn)定性)
在這里我們使用etcd作為服務(wù)發(fā)現(xiàn)存儲(chǔ)倉庫。
具體實(shí)現(xiàn)原理 我們本次所使用的etcd的能力etcd節(jié)點(diǎn)的保持獨(dú)占能力。(同一時(shí)間只有一臺(tái)服務(wù)器可以擁有節(jié)點(diǎn))
節(jié)點(diǎn)事件監(jiān)聽能力。(可以在節(jié)點(diǎn)被釋放/占有時(shí)通知觀察者-服務(wù)器)
節(jié)點(diǎn)主動(dòng)釋放能力。(服務(wù)器可以主動(dòng)釋放擁有節(jié)點(diǎn))
節(jié)點(diǎn)超時(shí)自動(dòng)釋放能力。(超時(shí)自動(dòng)釋放節(jié)點(diǎn))
在代碼中,需要準(zhǔn)備以下幾個(gè)內(nèi)容etcd長(zhǎng)監(jiān)聽。(監(jiān)聽etcd節(jié)點(diǎn),在節(jié)點(diǎn)變更時(shí)作出響應(yīng))
事件隊(duì)列。(存放爭(zhēng)奪etcd節(jié)點(diǎn)的方法)
爭(zhēng)奪鎖事件。
等待鎖超時(shí)事件。(沒畫在流程圖中,在爭(zhēng)奪鎖事件入隊(duì)列時(shí)注冊(cè),持有鎖時(shí)注銷)
持有鎖超時(shí)事件。(沒畫在流程圖中,在持有鎖時(shí)注冊(cè),在釋放鎖時(shí)注銷)
釋放鎖事件。
基本代碼流程圖
正常代碼流程圖(markdown畫的,有點(diǎn)丑)
st=>start: 項(xiàng)目啟動(dòng) watcher=>operation: 監(jiān)聽etcd ed=>end: 等待請(qǐng)求 st->watcher->ed
st=>start: 開始執(zhí)行l(wèi)ock ed=>end: 結(jié)束 watcher=>operation: 監(jiān)聽etcd hasEvent=>condition: 事件隊(duì)列為空 pushEvent=>operation: 爭(zhēng)奪鎖事件 入等待隊(duì)列 watcherEvent=>operation: etcd節(jié)點(diǎn)超時(shí)事件和釋放事件 popEvent=>operation: 爭(zhēng)奪鎖事件 出事件隊(duì)列 execute=>operation: 執(zhí)行被鎖住的代碼塊 fight=>condition: 爭(zhēng)奪鎖失敗 unlock=>operation: 釋放鎖 st->fight fight(no)->execute->unlock->ed fight(yes)->pushEvent->watcherEvent->popEvent->fight
事件細(xì)節(jié)偽代碼
準(zhǔn)備一個(gè)清空所有相關(guān)事件的萬能方法
假設(shè)eventQueue是這種業(yè)務(wù)對(duì)應(yīng)的事件隊(duì)列 假設(shè)fightEvent是該次執(zhí)行的爭(zhēng)奪鎖事件 假設(shè)clear為清除超時(shí)事件的方法 假設(shè)holdEvent為持有鎖超時(shí)事件 假設(shè)waitEvent為等待鎖超時(shí)事件 假設(shè)unLockEvent為釋放鎖事件 // 清空所有事件 - clearAll eventQueue.remove(fightEvent) clear(waitEvent) clear(holdEvent)
監(jiān)聽etcd的兩個(gè)事件
// 當(dāng)etcd鎖超時(shí)事件或etcd主動(dòng)釋放事件發(fā)生時(shí) // 爭(zhēng)奪鎖事件 出事件隊(duì)列 fightEvent = eventQueue.pop // 執(zhí)行爭(zhēng)奪鎖事件 執(zhí)行 fightEvent
爭(zhēng)奪鎖事件
// 爭(zhēng)奪鎖事件 執(zhí)行 etcd爭(zhēng)奪鎖方法 if (搶到鎖了) { // 清空所有事件 執(zhí)行 clearAll // 設(shè)置持有鎖超時(shí)事件 設(shè)置 holdEvent } else { // 爭(zhēng)奪鎖事件如果是二次入隊(duì)列,建議到隊(duì)列頭,而不是到隊(duì)列尾 eventQueue.push(fightEvent) }
等待鎖超時(shí)事件(用時(shí)間輪延時(shí)執(zhí)行)
// 清空所有事件 執(zhí)行 clearAll // 拋出異常 throw new Exception
持有鎖超時(shí)事件(用時(shí)間輪延時(shí)執(zhí)行)
// 執(zhí)行釋放鎖事件 執(zhí)行 unLockEvent
釋放鎖事件
// 釋放鎖事件 執(zhí)行 etcd釋放鎖方法 // 清空所有事件 執(zhí)行 clearAll
備注
以上代碼可以用有限狀態(tài)機(jī)設(shè)計(jì)模式來設(shè)計(jì)業(yè)務(wù)
圖解分布式服務(wù)器與etcd集群交互
項(xiàng)目啟動(dòng)時(shí)初始化,服務(wù)器A、B、C是一個(gè)分布式系統(tǒng)(不考慮哪臺(tái)為master)
同時(shí)發(fā)來10個(gè)請(qǐng)求,此時(shí)經(jīng)過算法分配假設(shè)變成了這樣
開始爭(zhēng)奪鎖時(shí),10個(gè)線程同時(shí)向etcd爭(zhēng)奪鎖
假設(shè)請(qǐng)求2爭(zhēng)奪成功,那么第一次競(jìng)爭(zhēng)完畢后除了請(qǐng)求2,其他請(qǐng)求都進(jìn)入了各自的事件隊(duì)列等待etcd釋放鎖的通知
當(dāng)請(qǐng)求2執(zhí)行完代碼塊后,向etcd發(fā)送釋放鎖請(qǐng)求
etcd收到釋放鎖請(qǐng)求,將節(jié)點(diǎn)刪除,觸發(fā)compareAndDelete事件(釋放鎖事件)
三臺(tái)服務(wù)器接收到釋放鎖的信息,各自讓事件隊(duì)列頭的請(qǐng)求向etcd發(fā)送爭(zhēng)奪鎖請(qǐng)求
鎖搶完后,重復(fù)4->6的行為
補(bǔ)充說明
etcd還有一個(gè)功能是控制時(shí)序,這樣的話就可以將每個(gè)請(qǐng)求搶鎖的行為控制到只剩一次,業(yè)務(wù)執(zhí)行的順序由etcd控制,不過我沒有試過,有興趣的同學(xué)可以試一試。
之前基于分布式鎖的原理還寫了一個(gè)分布式緩存鎖,是通過鎖緩存來防止緩存擊穿的,有空的時(shí)候補(bǔ)上。感謝各位同學(xué)看我的文章看到此處。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/69030.html
摘要:分布式情況下這個(gè)就需要換成分布式鎖以保證數(shù)據(jù)一致性。三分布式鎖實(shí)現(xiàn)原理所需的依賴一個(gè)擁有強(qiáng)一致性的服務(wù)發(fā)現(xiàn)存儲(chǔ)倉庫。保證數(shù)據(jù)一致性一個(gè)具有高可用性的服務(wù)發(fā)現(xiàn)存儲(chǔ)倉庫。 一、基本概念 分布式鎖,是單機(jī)鎖的一種擴(kuò)展,主要是為了鎖住分布式系統(tǒng)中不同機(jī)器代碼的物理塊或邏輯塊。以此保證不同機(jī)器之間的邏輯一致性。 二、一個(gè)簡(jiǎn)單的案例 對(duì)DB寫操作的雙檢鎖案例 偽代碼如下 if (可以插入一條數(shù)...
摘要:不過比較膚淺,為了進(jìn)一步加深對(duì)的認(rèn)識(shí),我利用空閑時(shí)間編寫了本篇文章對(duì)應(yīng)的基于的分布式鎖實(shí)現(xiàn)。不過我所編寫的分布式鎖還是比較簡(jiǎn)陋的,實(shí)現(xiàn)的也不夠優(yōu)美,僅僅是個(gè)練習(xí),僅供參考使用。好了,題外話就說到這里,接下來我們就來聊聊基于的分布式鎖實(shí)現(xiàn)。 1. 背景 最近在學(xué)習(xí) Zookeeper,在剛開始接觸 Zookeeper 的時(shí)候,完全不知道 Zookeeper 有什么用。且很多資料都是將 Z...
摘要:作為面試官,我是如何甄別應(yīng)聘者的包裝程度語言和等其他語言的對(duì)比分析和主從復(fù)制的原理詳解和持久化的原理是什么面試中經(jīng)常被問到的持久化與恢復(fù)實(shí)現(xiàn)故障恢復(fù)自動(dòng)化詳解哨兵技術(shù)查漏補(bǔ)缺最易錯(cuò)過的技術(shù)要點(diǎn)大掃盲意外宕機(jī)不難解決,但你真的懂?dāng)?shù)據(jù)恢復(fù)嗎每秒 作為面試官,我是如何甄別應(yīng)聘者的包裝程度Go語言和Java、python等其他語言的對(duì)比分析 Redis和MySQL Redis:主從復(fù)制的原理詳...
摘要:作為面試官,我是如何甄別應(yīng)聘者的包裝程度語言和等其他語言的對(duì)比分析和主從復(fù)制的原理詳解和持久化的原理是什么面試中經(jīng)常被問到的持久化與恢復(fù)實(shí)現(xiàn)故障恢復(fù)自動(dòng)化詳解哨兵技術(shù)查漏補(bǔ)缺最易錯(cuò)過的技術(shù)要點(diǎn)大掃盲意外宕機(jī)不難解決,但你真的懂?dāng)?shù)據(jù)恢復(fù)嗎每秒 作為面試官,我是如何甄別應(yīng)聘者的包裝程度Go語言和Java、python等其他語言的對(duì)比分析 Redis和MySQL Redis:主從復(fù)制的原理詳...
閱讀 1326·2021-11-19 09:40
閱讀 3195·2021-11-02 14:47
閱讀 3481·2021-10-11 10:58
閱讀 3279·2019-08-30 15:54
閱讀 2760·2019-08-30 12:50
閱讀 1789·2019-08-29 16:54
閱讀 525·2019-08-29 15:38
閱讀 1288·2019-08-29 15:19