閒聊軟體設計:分散式鎖

更新 發佈閱讀 7 分鐘
圖片來源:ChatGPT 生成

圖片來源:ChatGPT 生成

這次開發系統的過程中,大多數都是使用樂觀鎖來避免 race condition 的情況 (參閱 閒談軟體設計:樂觀鎖 ),但樂觀鎖的使用有前提條件:要有資料本身能做為鎖的載體。但不是所有的情境都能滿足這個條件。

這次的情境比較特別,一邊使用者可能在一個範圍內批次新增或修改多筆資源 S,而另一邊背景的 Worker 則會讀取一個範圍內的資源 S 作為運算的輸入,此時會希望當批次寫入仍在進行中時,Worker 要等到批次寫入完成再讀取,不然可能會用到錯的資料進行運算。反之,Worker 在讀取資料時,會希望批次處理等到 Worker 處理完後再寫入。

樂觀鎖和序列交易

在這個情境下,無法找到合適的樂觀鎖載體,因為 Worker 只讀取資料,沒有更新任何資訊,也就無法比較版本是否有更動過,更何況,批次的操作中有新增資源的情況,這讓 Worker 無法提前知道資料的 ID 來鎖定。因此,這個情境下樂觀鎖無法上派上用場。

那 PostgreSQL 的 Serializable Isolation Level 的交易管理有機會解決這問題嗎?有機會,但處理方式需要調整,首先,讀寫兩端都要開啟 Serializable Isolation Level 的交易,接著,讀寫兩端都需要處理重試,因為PostgreSQL 在 Serializable Isolation Level 下並不會強制讓交易排隊,而是允許交易先平行執行,並在 commit 時檢查是否存在 serialization anomaly。如果發現衝突,就會中止其中一個交易並要求重試。

那如果是鎖整張 table 呢?可以,但這會讓系統的效能大幅降低,如果沒有特殊的需求,通常不會使用。

在一般的情況下,直接把錯誤傳回前端,讓使用者重試是可接受的選項,但由於這回批次寫入的資料如果讓使用者重試,體驗恐怕不會太好,若不想重試似乎要請出悲觀鎖。

分散式鎖

在過去學習作業系統或是平行處理時,當要處理 race condition,通常都會用 mutex lock 確保只有一個程序進入 critical section,其他程序要等到先進入 critical section 完成後才能進入。如果是單程序的 Java 應用程式,用語言內建的 synchronized 關鍵字,就能簡單地實現多執行緒的 mutex lock。

但在雲端環境呢?就需要分散式鎖,一般來說,很多人會想到用 Redis,確實在一開始也想過直接用 Redis,畢竟目前的系統裡,也有佈署 Redis,但後來想想,當時佈署 Redis 是為了使用 Redis Pub/Sub,所以用 k8s 簡單地佈署了只有一個 instance 的 Redis,唯一的 instance 如果重啟,那 lock 就失效了,似乎會是個風險。

那有其他選擇嗎?花了一點時間研究後,發現了一個有趣而且不用佈署任何新機器的解:PostgreSQL Advisory Lock。

PostgreSQL Advisory Lock

PostgreSQL Advisory Lock 是 PostgreSQL 內建的一種鎖,使用方式很簡單,只需要在 transaction 內執行 SELECT pg_advisory_xact_lock(key)key 是一個 64 位元整數,由應用層決定 key,只要是相同的 key,PostgreSQL 就會確保未取得鎖的程序等待已取得鎖的程序結束。

必須在 transaction 內使用,而且會隨著 transaction 結束 (commit 或 rollback),自動釋放 lock,很簡單就能避免忘記釋放 lock 的情況,相當方便,之前竟然不知道有這東西,太可惜了。

馬上將這個技術封裝並提供一個類似 Java synchronized 的抽象,在原有的 Sql2oTransactionManager 加入 synchronize 函式,第一個參數是 key,第二個參數便是取得鎖後要執行的內容:

  • runInSession 確保作為參數的 lambda 會在一個 transaction 執行,不管那個 transaction 是既有的或是新建立的
  • obtainLock 則是將 key 透過 hashtextextended 雜湊程 64 位元的整數。
  • 在取得 lock 後才執行 runnable

整個實作相當直覺簡單。

有了這個函式後,在 Worker 就可以將初始化的動作包進第二個參數,在批次更新的部分,也將寫入的部分包進第二個參數,只要 key 相同,就會確保只會有一個程序執行,另一個程序會等待先執行的程序結束後才執行。

到此,批次寫入和 Worker 讀取能按照順序執行了,也替系統添加了一個分散式鎖的實作,之後有需要時,能直接使用。

Advisory Lock 也是有限制的,要進入 critical section 的程式都要先試著取得鎖,這和多數 mutex lock 的使用是一樣的。另外,key 的範圍要小心,如果 key 鎖定的範圍太大,也會讓系統效能大幅下降,要盡量避免。

另外,這邊使用 pg_advisory_xact_lock 而非 pg_advisory_lock 就是讓 lock 的生命週期與 transaction 綁定,並免忘記釋放 lock 的問題,若真的要使用 pg_advisory_lock,請切記做好 lock 的生命週期管理。

最後,如果是不想等待,可以使用 pg_try_advisory_xact_lock,若取得鎖失敗後馬上返回 false,由應用層決定該如何處理。

小結

在需要「一組操作完成後另一組操作才能開始」的情境下,樂觀鎖或 Serializable Isolation Level 交易不一定能滿足這需求,特別是當操作涉及範圍查詢或可能新增未知資料時。若既有系統有 PostgreSQL 的情況下,可以透過 PostgreSQL 提供的Advisory Lock,加上能用 key 決定鎖的顆粒度,在不引入額外基礎設施的情況下,是相當方便的一個悲觀鎖選項。

留言
avatar-img
Spirit 異想世界
58會員
122內容數
這是從 Medium 開始的一個專題,主要是想用輕鬆閒談的方式,分享這幾年軟體開發的心得,原本比較侷限於軟體架構,但這幾年的文章不僅限於架構,也聊不少流程相關的心得,所以趁換平台,順勢換成閒談軟體設計。
Spirit 異想世界的其他內容
2026/03/01
本文探討在軟體開發過程中,將原本並非 Aggregate 的設計,逐步重構成具有 Aggregate 精神的實作。作者分享了一個實際案例,說明如何在一致性問題和更複雜的協同作業需求出現時,透過引入樂觀鎖,並逐步思考 Aggregate 的設計原則,最終找到一個在滿足系統需求下的特殊解決方案。
Thumbnail
2026/03/01
本文探討在軟體開發過程中,將原本並非 Aggregate 的設計,逐步重構成具有 Aggregate 精神的實作。作者分享了一個實際案例,說明如何在一致性問題和更複雜的協同作業需求出現時,透過引入樂觀鎖,並逐步思考 Aggregate 的設計原則,最終找到一個在滿足系統需求下的特殊解決方案。
Thumbnail
2026/02/21
作者分享了 B2B 產品在迭代開發過程中所遇到的挑戰,特別是在追求功能完整性的過程中,如何避免設計變得過於複雜,進而影響使用者體驗。文中探討了從使用者回饋、市場變化到團隊內部認知的變化,並提出了在產品開發中「踩煞車」的重要性,以確保產品能真正符合使用者需求,而非徒增複雜度。
Thumbnail
2026/02/21
作者分享了 B2B 產品在迭代開發過程中所遇到的挑戰,特別是在追求功能完整性的過程中,如何避免設計變得過於複雜,進而影響使用者體驗。文中探討了從使用者回饋、市場變化到團隊內部認知的變化,並提出了在產品開發中「踩煞車」的重要性,以確保產品能真正符合使用者需求,而非徒增複雜度。
Thumbnail
2026/02/14
分享在不同公司期間,與客戶進行實地拜訪的豐富經,這些故事不僅是單純的客戶訪談紀錄,更揭示了產品開發過程中可能遇到的挑戰、客戶的真實痛點,以及從數據以外的角度全面理解市場需求的洞見。文章強調了工程師實地訪談的重要性,並鼓勵讀者若有機會應多加嘗試,從中獲取寶貴的經驗與啟發。
Thumbnail
2026/02/14
分享在不同公司期間,與客戶進行實地拜訪的豐富經,這些故事不僅是單純的客戶訪談紀錄,更揭示了產品開發過程中可能遇到的挑戰、客戶的真實痛點,以及從數據以外的角度全面理解市場需求的洞見。文章強調了工程師實地訪談的重要性,並鼓勵讀者若有機會應多加嘗試,從中獲取寶貴的經驗與啟發。
Thumbnail
看更多
你可能也想看
Thumbnail
當時間變少之後,看戲反而變得更加重要——這是在成為母親之後,我第一次誠實地面對這一件事:我沒有那麼多的晚上,可以任性地留給自己了。看戲不再只是「今天有沒有空」,而是牽動整個週末的結構,誰應該照顧孩子,我該在什麼時間回到家,隔天還有沒有精神帶小孩⋯⋯於是,我不得不學會一件以前並不擅長的事:挑選。
Thumbnail
當時間變少之後,看戲反而變得更加重要——這是在成為母親之後,我第一次誠實地面對這一件事:我沒有那麼多的晚上,可以任性地留給自己了。看戲不再只是「今天有沒有空」,而是牽動整個週末的結構,誰應該照顧孩子,我該在什麼時間回到家,隔天還有沒有精神帶小孩⋯⋯於是,我不得不學會一件以前並不擅長的事:挑選。
Thumbnail
見諸參與鄧伯宸口述,鄧湘庭於〈那個大霧的時代〉記述父親回憶,鄧伯宸因故遭受牽連,而案件核心的三人,在鄧伯宸記憶裡:「成立了成大共產黨,他們製作了五星徽章,印刷共產黨宣言——刻鋼板的——他們收集中共空飄的傳單,以及中國共產黨中央委員會有關文化大革命決議文的英文打字稿,另外還有手槍子彈十發。」
Thumbnail
見諸參與鄧伯宸口述,鄧湘庭於〈那個大霧的時代〉記述父親回憶,鄧伯宸因故遭受牽連,而案件核心的三人,在鄧伯宸記憶裡:「成立了成大共產黨,他們製作了五星徽章,印刷共產黨宣言——刻鋼板的——他們收集中共空飄的傳單,以及中國共產黨中央委員會有關文化大革命決議文的英文打字稿,另外還有手槍子彈十發。」
Thumbnail
在紡織業做廠長二十多年,習慣了各種挑戰:產線延誤、設備故障、排程變動、來料不齊……但有一個新挑戰,這兩年變得愈來愈明顯,卻也最難處理:碳排放管理與能源效率透明化。這不是什麼新名詞,大家都聽過。問題是:知道歸知道,要做怎麼做?
Thumbnail
在紡織業做廠長二十多年,習慣了各種挑戰:產線延誤、設備故障、排程變動、來料不齊……但有一個新挑戰,這兩年變得愈來愈明顯,卻也最難處理:碳排放管理與能源效率透明化。這不是什麼新名詞,大家都聽過。問題是:知道歸知道,要做怎麼做?
Thumbnail
在這個數位時代,幾乎人人有手機有電腦,每天都會接觸網站或 APP。你打開手機滑臉書、用foodpanda 網路訂餐、上網查資料,甚至於近兩年快速登上科技時代的最佳主角:AI ,背後都是由一群默默耕耘的軟體工程師在支撐。 今天,就讓我們從基礎的網站架構談起,一步步認識工程師的世界。
Thumbnail
在這個數位時代,幾乎人人有手機有電腦,每天都會接觸網站或 APP。你打開手機滑臉書、用foodpanda 網路訂餐、上網查資料,甚至於近兩年快速登上科技時代的最佳主角:AI ,背後都是由一群默默耕耘的軟體工程師在支撐。 今天,就讓我們從基礎的網站架構談起,一步步認識工程師的世界。
Thumbnail
將兩個JPG文件合併為一個是一項實用的技能,可用於創建拼貼、文件或演示文稿。本文探討了多種有效的方法來達成這一目標,包括使用在線工具、桌面應用程序以及操作系統內建的工具。每種方法都有其優缺點,適用於不同的需求和資源。無論您是尋求快速解決方案,還是需要高級編輯功能,這份指南將幫助您找到適合的選項。
Thumbnail
將兩個JPG文件合併為一個是一項實用的技能,可用於創建拼貼、文件或演示文稿。本文探討了多種有效的方法來達成這一目標,包括使用在線工具、桌面應用程序以及操作系統內建的工具。每種方法都有其優缺點,適用於不同的需求和資源。無論您是尋求快速解決方案,還是需要高級編輯功能,這份指南將幫助您找到適合的選項。
Thumbnail
EP27 精華重點: 1.時間管理的觀念: 將時間視為資產,讓時間發揮最大價值 設定明確的短期和長期目標 2.制定可行計畫: 將大目標分割成可執行的小計畫和里程碑 給自己合理的獎勵作為動力 3.優先排序處理事務: 根據重要性和緊急程度劃分為四個象限 先處理緊急的事物,延後的部分要補
Thumbnail
EP27 精華重點: 1.時間管理的觀念: 將時間視為資產,讓時間發揮最大價值 設定明確的短期和長期目標 2.制定可行計畫: 將大目標分割成可執行的小計畫和里程碑 給自己合理的獎勵作為動力 3.優先排序處理事務: 根據重要性和緊急程度劃分為四個象限 先處理緊急的事物,延後的部分要補
Thumbnail
當代名導基里爾.賽勒布倫尼科夫身兼電影、劇場與歌劇導演,其作品流動著強烈的反叛與詩意。在俄烏戰爭爆發後,他持續以創作回應專制體制的壓迫。《傳奇:帕拉贊諾夫的十段殘篇》致敬蘇聯電影大師帕拉贊諾夫。本文作者透過媒介本質的分析,解構賽勒布倫尼科夫如何利用影劇雙棲的特質,在荒謬世道中尋找藝術的「生存之道」。
Thumbnail
當代名導基里爾.賽勒布倫尼科夫身兼電影、劇場與歌劇導演,其作品流動著強烈的反叛與詩意。在俄烏戰爭爆發後,他持續以創作回應專制體制的壓迫。《傳奇:帕拉贊諾夫的十段殘篇》致敬蘇聯電影大師帕拉贊諾夫。本文作者透過媒介本質的分析,解構賽勒布倫尼科夫如何利用影劇雙棲的特質,在荒謬世道中尋找藝術的「生存之道」。
Thumbnail
5 月,方格創作島正式開島。這是一趟 28 天的創作旅程。活動期間,每週都會有新的任務地圖與陪跑計畫,從最簡單的帳號使用、沙龍建立,到帶著你從一句話、一張照片開始,一步一步找到屬於自己的創作節奏。不需要長篇大論,不需要完美的文筆,只需要帶上你今天的日常,就可以出發。征服創作島,抱回靈感與大獎!
Thumbnail
5 月,方格創作島正式開島。這是一趟 28 天的創作旅程。活動期間,每週都會有新的任務地圖與陪跑計畫,從最簡單的帳號使用、沙龍建立,到帶著你從一句話、一張照片開始,一步一步找到屬於自己的創作節奏。不需要長篇大論,不需要完美的文筆,只需要帶上你今天的日常,就可以出發。征服創作島,抱回靈感與大獎!
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News