從構建分布式秒殺系統聊聊分布式鎖

2021-09-13 11:31:36 字數 3122 閱讀 6094

摘要:前言 最近懶成一坨屎,學不動系列一波接一波,大多還都是底層原理相關的。上周末抽時間重讀了周志明大濕的 jvm 高效併發部分,每讀一遍都有不同的感悟。路漫漫,藉此,把前段時間搞著玩的秒殺案例中的分布式鎖深入了解一下。

最近懶成一坨屎,學不動系列一波接一波,大多還都是底層原理相關的。上周末抽時間重讀了周志明大濕的 jvm 高效併發部分,每讀一遍都有不同的感悟。路漫漫,藉此,把前段時間搞著玩的秒殺案例中的分布式鎖深入了解一下。

在嘗試了解分布式鎖之前,大家可以想象一下,什麼場景下會使用分布式鎖?

單機應用架構中,秒殺案例使用reentrantlcok或者synchronized來達到秒殺商品互斥的目的。然而在分布式系統中,會存在多台機器並行去實現同乙個功能。也就是說,在多程序中,如果還使用以上jdk提供的程序鎖,來併發訪問資料庫資源就可能會出現商品超賣的情況。因此,需要我們來實現自己的分布式鎖。

實現乙個分布式鎖應該具備的特性:

▪ 高可用、高效能的獲取鎖與釋放鎖

▪ 在分布式系統環境下,乙個方法或者變數同一時間只能被乙個執行緒操作

▪ 具備鎖失效機制,網路中斷或宕機無法釋放鎖時,鎖必須被刪除,防止死鎖

▪ 具備阻塞鎖特性,即沒有獲取到鎖,則繼續等待獲取鎖

▪ 具備非阻塞鎖特性,即沒有獲取到鎖,則直接返回獲取鎖失敗

▪ 具備可重入特性,乙個執行緒中可以多次獲取同一把鎖,比如乙個執行緒在執行乙個帶鎖的方法,該方法中又呼叫了另乙個需要相同鎖的方法,則該執行緒可以直接執行呼叫的方法,而無需重新獲得鎖

在之前的秒殺案例中,我們曾介紹過關於分布式鎖幾種實現方式:

▪ 基於資料庫實現分布式鎖

▪ 基於 redis 實現分布式鎖

▪ 基於 zookeeper 實現分布式鎖

前兩種對於分布式生產環境來說並不是特別推薦,高併發下資料庫鎖效能太差,redis在鎖時間限制和快取一致性存在一定問題。這裡我們重點介紹一下 zookeeper 如何實現分布式鎖。

實現原理

zookeeper是乙個分布式的,開放原始碼的分布式應用程式協調服務,它內部是乙個分層的檔案系統目錄樹結構,規定同乙個目錄下只能存在唯一檔名。

資料模型

▪ persistent 持久化節點,節點建立後,不會因為會話失效而消失

▪ ephemeral 臨時節點, 客戶端session超時此類節點就會被自動刪除

▪ ephemeral_sequential 臨時自動編號節點

▪ persistent_sequential 順序自動編號持久化節點,這種節點會根據當前已存在的節點數自動加 1

監視器(watcher)

當建立乙個節點時,可以註冊乙個該節點的監視器,當節點狀態發生改變時,watch被觸發時,zookeeper將會向客戶端傳送且僅傳送一條通知,因為watch只能被觸發一次。

根據zookeeper的這些特性,我們來看看如何利用這些特性來實現分布式鎖:

▪ 建立乙個鎖目錄lock

▪ 執行緒a獲取鎖會在lock目錄下,建立臨時順序節點

▪ 獲取鎖目錄下所有的子節點,然後獲取比自己小的兄弟節點,如果不存在,則說明當前執行緒順序號最小,獲得鎖

▪ 執行緒b建立臨時節點並獲取所有兄弟節點,判斷自己不是最小節點,設定監聽(watcher)比自己次小的節點(只關注比自己次小的節點是為了防止發生「羊群效應」)

▪ 執行緒a處理完,刪除自己的節點,執行緒b監聽到變更事件,判斷自己是最小的節點,獲得鎖

**分析

儘管zookeeper已經封裝好複雜易出錯的關鍵服務,將簡單易用的介面和效能高效、功能穩定的系統提供給使用者。但是如果讓乙個普通開發者去手擼乙個分布式鎖還是比較困難的,在秒殺案例中我們直接使用 apache 開源的curator 開實現 zookeeper 分布式鎖。

這裡我們使用以下版本,截止目前最新版4.0.1:

首先,我們看下interprocesslock介面中的幾個方法:

獲取鎖:

zookeeper獲取鎖實現:

釋放鎖:

為了更好的理解其原理和**分析中獲取鎖的過程,這裡我們實現乙個簡單的demo:

這裡我們開啟5個執行緒,每個執行緒獲取鎖的最大等待時間為5秒,為了模擬具體業務場景,方法中設定4秒等待時間。開始執行main方法,通過zooinspector監控/curator/lock下的節點如下圖:

對,沒錯,設定4秒的業務處理時長就是為了觀察生成了幾個順序節點。果然如案例中所述,每個執行緒都會生成乙個節點並且還是有序的。

觀察控制台,我們會發現只有兩個執行緒獲取鎖成功,另外三個執行緒超時獲取鎖失敗會自動刪除節點。執行緒執行完畢我們重新整理一下/curator/lock節點,發現剛才建立的五個子節點已經不存在了。

通過分析第三方開源工具實現的分布式鎖方式,收穫還是滿滿的。學習本身就是乙個由淺入深的過程,從如何呼叫api,到理解其**邏輯實現,想要更深入可以去挖掘zookeeper的核心演算法zab協議。

閱讀原文

聊聊分布式系統

一提起 分布式系統 大家的第一感覺就是好高大上啊,深不可測,看各類大牛關於分布式系統的演講或者書籍,也大多是一臉懵逼。本文期望用淺顯易懂的大白話來就什麼是分布式系統 分布式系統有哪些優勢 分布式系統會面臨 挑戰 如何來設計分布式等方面的話題來展開討論。關於這個定義,我們直觀的感受就是 從程序角度看,...

簡單聊聊分布式鎖 zookeeper分布式鎖

zookeeper分布式鎖 zookeeper分布式鎖 舉個栗子。對某乙個資料連續發出兩個修改操作,兩台機器同時收到了請求,但是只能一台機器先執行完另外乙個機器再執行。那麼此時就可以使用 zookeeper 分布式鎖,乙個機器接收到了請求之後先獲取 zookeeper 上的一把分布式鎖,就是可以去建...

聊聊分布式事務

事務就是乙個會話過程中,對上下文的影響是一致的,要麼所有的更改都做了,要麼所有的更變都撤銷掉。就要麼生,要麼死。沒有半死不死的中間不可預期狀態。參考下薛丁格的貓。事務是為了保障業務資料的完整性和準確性的。分布式事務,常見的兩個處理辦法就是兩段式提交和補償。兩段式提交典型的就是xa,有個事務協調器,告...