使用 Azure 儲存管理分散式系統鎖定

分散式系統已經存在一段時間,並且在設計這些系統時已經建立了一些知名的模式。今天,我們將討論其中一個流行的模式:「鎖」。

簡單來說,是進程獲得對資源的獨佔訪問權以執行某個動作的方式。例如,假設在一個存儲帳戶中有一堆 Blob,您需要一個服務實例來處理每個 Blob,以避免重複處理。這樣做的方法是對 Blob 獲取鎖,完成處理後再釋放鎖。然而,如果在釋放鎖之前進程失敗,例如因為進程崩潰或網絡分區,則可能會出現潛在問題,導致資源被無限期鎖定。這可能導致死鎖和資源競爭。

為了防止死鎖,可以採用的一種策略是使用超時或租約基礎的鎖。

超時鎖

  • 在這種情況下,進程請求鎖的時間是預先定義的超時。如果在超時之前未釋放鎖,系統將確保鎖最終被釋放。

租約鎖

  • 對於基於租約的鎖定,提供了一個 續租 API 以及超時機制。持有鎖的進程必須在租約到期之前調用此 API 以保持對資源的獨占訪問。如果進程未能及時續租,鎖將自動釋放,允許其他進程獲取它。

超時和基於租約的鎖定的優缺點

Pros Cons
基於超時的鎖 實現簡單 需要仔細選擇超時時間
防止永久鎖定 如果處理未完成,則無法續租
基於租約的鎖 降低提前
鎖過期的風險
需要租約續租的機制

進程可以持續請求租約直到工作完成。

上述兩種策略都是在 分佈式系統 中快速從進程失敗或網絡分區中恢復的一種方式。

租約鎖定策略與 Azure 儲存

讓我們來看看如何使用租約鎖定策略與 Azure 儲存。這也涵蓋了超時鎖定策略。

步驟 1: 導入儲存 Blob Nuget

“12.23.0” 是撰寫本文時的最新版本。最新版本可以在 Azure 儲存 Blob 找到。

XML

 

步驟 2: 獲取租約

以下是獲取租約的代碼。

C#

 

  1. 首先,我們創建一個 Blob 容器客戶端 並檢索我們想要獲取租約的特定 blob 的 Blob 客戶端
  2. 其次,”Acquire Async” 方法嘗試在特定持續時間內獲取租約。如果獲取成功,則返回租約 ID,否則會拋出 409(衝突的狀態碼)。
  3. “Acquire Async” 是這裡的關鍵方法。其餘代碼可以根據您的需求進行調整/編輯。

步驟 3: 續租

  • “Renew Async” 是在 Storage .NET SDK 中用於續租的的方法。
  • 如果續租不成功,則會拋出異常並附上失敗原因。
C#

 

步驟 4: 協調獲取和續租方法

  • 最初,我們呼叫「嘗試異步獲取租約」以從步驟 2 獲取租約識別碼。一旦成功,將啟動一個背景任務,每隔 X 秒呼叫步驟 3 的「異步續約租約」。請確保在超時和呼叫續約租約方法之間有足夠的時間。
C#

 

  • 取消令牌 用於 優雅地停止租約續約任務 當不再需要時。

步驟 5: 取消租約續約

  • 當呼叫「取消異步」方法時,步驟 4 中的「是否請求取消」變為真,因此我們不再進入 while 循環並請求續約租約。
C#

 

步驟 6: 釋放租約

最後,釋放租約只需呼叫「釋放異步」方法。

C#

 

結論

鎖是分散式系統中獲得對資源的獨佔訪問的基本模式之一。在處理它們時,必須記住陷阱,以確保操作的順利進行。通過使用 Azure 儲存,我們可以實現這些高效的鎖定機制,防止無限阻塞,同時提供鎖定維護的彈性。

Source:
https://dzone.com/articles/locks-in-distributed-systems-timeout-lease-based