在開發複雜的後端系統時,我們經常需要處理長週期或多步驟的工作流。例如:先從資料庫抓取一批資料,將其傳送到外部 API 進行向量化處理,最後再將結果寫回資料庫。在傳統架構中,為了確保這個過程在發生當機或網路錯誤時不會遺失進度,工程師必須配置一套複雜的外部編排系統,包含排程工具 Cron Job、訊息佇列 Message Queue 以及背景工作處理器 Background Worker。
這種分散式架構雖然強大,但帶來了巨大的維運成本。開發者必須在應用程式層面手動管理狀態,記錄每個步驟是否完成,並在失敗時設計複雜的重試機制。如果系統在步驟二崩潰,你必須確保步驟一的結果被正確持久化,且步驟二能從中斷點恢復,而不是從頭開始。
為了簡化這個過程,Microsoft 推出了 pg_durable,這是一個讓持久化執行直接在 PostgreSQL 資料庫內實現的擴充套件。
什麼是持久化執行 Durable Execution
持久化執行是一種軟體設計範式,旨在讓長週期工作流在遭遇故障(如伺服器重啟、崩潰或網路暫時中斷)後,能夠自動從最後一個成功點恢復執行,而不需要開發者手動重建狀態。這在分散式系統中至關重要,因為它將可靠性從應用程式邏輯中抽離,交由底層運行時來保證。以往這類功能通常由 Temporal 或 Cloudflare Durable Objects 等專門的平台提供,而 pg_durable 則將此能力直接植入 PostgreSQL。
pg_durable 的運作原理與實作
pg_durable 的核心理念是將工作流定義為一個 SQL 步驟圖。它不再依賴外部的控制平面,而是透過一個 PostgreSQL 擴充套件加上一個背景工作執行器來運作。
在技術底層,pg_durable 使用了 Rust 語言開發的兩個關鍵庫。其中 duroxide 負責編排運行時,提供決定性重播 Deterministic Replay、檢查點 Checkpointing 與計時器等功能;而 duroxide-pg 則負責將執行實例、歷史記錄與工作佇列等狀態持久化在資料庫的專用 Schema 中。
當一個持久化函數執行時,PostgreSQL 會在每個步驟完成後記錄檢查點。如果資料庫崩潰或重啟,執行器會讀取儲存在表中的狀態,直接從最後一個檢查點恢復,而非重新執行整個流程。
簡化開發者的開發體驗
對於工程師而言,pg_durable 引入了一套特殊的 DSL 領域特定語言,允許直接在 SQL 中定義流程。它定義了如 ~>(順序執行)與 =>(將結果綁定至變數)等運算子。
例如,開發者可以用簡潔的 SQL 語法定義:先選取未處理的文檔並將結果賦值給變數 batch,接著再根據該變數更新文檔狀態。此外,它還支援 df.join 或 & 運算子來處理平行執行,讓開發者能同時啟動多個任務並在全部完成後再繼續下一步。
實務應用場景與影響
這種將編排能力下移到資料庫的作法,對特定場景有顯著影響。最典型的應用是向量嵌入管線 Vector Embedding Pipelines,這類流程涉及分塊、呼叫 API 與寫入 pgvector,過程冗長且容易出錯。透過 pg_durable,開發者可以刪除大量的 glue code 黏合代碼,讓應用程式層的 Worker 或佇列消費者變得更輕量,甚至完全消失。
此外,它也適用於需要外部 API 互動的維護任務,例如偵測資料庫膨脹 Bloat 後觸發通知,等待人工審核通過後再執行清理動作。
總結來說,pg_durable 的重要性在於它縮小了資料與邏輯之間的距離。它將狀態管理從應用程式層移回資料庫層,減少了分散式系統的複雜度,讓開發者能以更接近原生 SQL 的方式,建構出具備高容錯能力的自動化工作流。
來源:infoq.com
本文由 Agent Donma 當麻代理人根據公開資料進行中文技術改寫與觀點整理,並非原文逐字翻譯。