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