pg_durable:把持久化工作流搬进 PostgreSQL,不再依赖外部编排引擎

2026-06-11 29 预计阅读时间: 1 分钟
来源: infoq.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:9 分钟

微软最近开源了一个 PostgreSQL 扩展——pg_durable,它的核心主张很简单:持久化工作流不需要再跑到外面去。工作流的状态、步骤、恢复逻辑全部在数据库内部完成,省掉 Temporal、Camunda 这类外部编排系统的一整套部署和维护成本。

为什么要把编排拉回数据库

传统做法里,一个业务流程(订单审批、退款处理、数据迁移)要跨多个服务调用,中间状态丢给外部编排引擎保管。这带来几个实际问题:

  • 多了一层基础设施——编排引擎本身要集群、要存储、要监控,运维成本不低。
  • 状态分散——业务数据在 PostgreSQL,流程状态在编排引擎的存储里,调试时要在两个系统之间来回跳。
  • 网络开销——每一步都要从编排引擎发请求到业务服务,再写回状态,延迟和故障点都多了。

pg_durable 的思路是:既然业务数据已经在 PostgreSQL 里了,把流程状态也放进来,用数据库的事务和持久性保证工作流不会丢步、不会重复执行。

pg_durable 的核心机制

根据项目描述,pg_durable 在 PostgreSQL 内部实现了 durable execution——即工作流的每一步执行都是持久化的,遇到崩溃、重启后可以从断点恢复继续。关键设计点包括:

  • 步骤级持久化:每个步骤完成后状态立即写入数据库,不依赖外部存储。
  • 崩溃恢复:数据库重启后,未完成的工作流自动从上一个已完成步骤继续。
  • SQL 可编程:工作流逻辑用 SQL 函数定义,不需要单独的 DSL 或 YAML 配置文件。

这意味着你不再需要为编排引擎单独搭建一套高可用集群——PostgreSQL 本身就是那个可靠的状态后端。

实际上手:定义并运行一个持久化工作流

下面演示如何安装扩展并创建一个简单的多步骤审批工作流。注意:部分 API 细节基于项目公开描述和合理推断,实际使用时请对照官方仓库确认。

安装扩展

# 从 GitHub 克隆并编译
git clone https://github.com/microsoft/pg_durable.git
cd pg_durable

# 编译安装(需要 pg_config 在 PATH 中)
make
make install

# 在目标数据库中启用扩展
psql -d your_db -c "CREATE EXTENSION pg_durable;"

定义一个退款审批工作流

假设业务场景:用户申请退款 → 自动风控检查 → 人工审批 → 执行退款。每一步都可能失败或超时,需要持久化保证。

-- 注册一个持久化工作流
SELECT pg_durable.register_workflow(
  'refund_approval',
  'process_refund_step'
);

-- 定义工作流的步骤函数
-- 每次被调用时根据当前步骤执行对应逻辑
CREATE OR REPLACE FUNCTION process_refund_step(
  workflow_id  UUID,
  step_name    TEXT,
  input_data   JSONB
) RETURNS JSONB AS $$
DECLARE
  result JSONB;
BEGIN
  CASE step_name
    -- 第一步:风控自动检查
    WHEN 'risk_check' THEN
      -- 模拟风控逻辑:金额超过 5000 标记为需人工审核
      IF (input_data->>'amount')::DECIMAL > 5000 THEN
        result := jsonb_build_object(
          'status', 'need_manual_review',
          'next_step', 'manual_review'
        );
      ELSE
        result := jsonb_build_object(
          'status', 'auto_approved',
          'next_step', 'execute_refund'
        );
      END IF;

    -- 第二步:人工审批(此处仅标记等待状态,实际可对接审批系统回调)
    WHEN 'manual_review' THEN
      result := jsonb_build_object(
        'status', 'pending_approval',
        'next_step', 'execute_refund',
        'note', '等待审批人操作'
      );

    -- 第三步:执行退款
    WHEN 'execute_refund' THEN
      -- 在事务中完成退款并更新订单状态
      UPDATE orders
        SET refund_status = 'completed',
            refunded_at   = now()
        WHERE order_id = (input_data->>'order_id')::INT;
      result := jsonb_build_object(
        'status', 'done',
        'next_step', NULL  -- NULL 表示工作流结束
      );

    ELSE
      RAISE EXCEPTION '未知步骤: %', step_name;
  END CASE;

  RETURN result;
END;
$$ LANGUAGE plpgsql;

启动一个工作流实例

-- 发起一笔退款审批
SELECT pg_durable.start_workflow(
  'refund_approval',
  jsonb_build_object(
    'order_id', 1024,
    'amount',   3200,
    'user_id',  887
  )
);

查询工作流状态

-- 查看所有进行中的退款工作流
SELECT workflow_id, current_step, status, created_at
  FROM pg_durable.workflow_instances
  WHERE workflow_name = 'refund_approval'
    AND status != 'done'
  ORDER BY created_at;

如果 PostgreSQL 在风控检查完成后崩溃重启,pg_durable 会从已持久化的 risk_check 结果恢复,直接进入下一步,不会重复执行风控逻辑——这正是 durable execution 的核心价值。

什么时候该用,什么时候不该用

适合的场景:

  • 工作流步骤本身就是数据库操作(状态更新、数据迁移、批量计算),编排和数据在同一个地方最自然。
  • 团队已经深度使用 PostgreSQL,不想再引入一套独立的编排基础设施。
  • 流程步骤数量有限(几十步以内),不需要跨数十个微服务的复杂拓扑。

需要谨慎的场景:

  • 工作流需要调用大量外部 HTTP 服务——把所有外部调用塞进 PostgreSQL 函数会让数据库承担不该承担的网络职责,此时外部编排引擎更合适。
  • 流程涉及长时间等待(数天、数周的人工审批),数据库连接和事务不宜长期持有,需要确认 pg_durable 的等待机制是否适合你的场景。
  • 已有成熟的 Temporal / Camunda 部署和运维体系,迁移成本需要认真评估。

上手建议

  1. 先在非生产环境试跑——克隆仓库、编译安装、跑通上面的退款示例,感受步骤恢复的实际行为。
  2. 对照现有编排方案做成本估算——如果你目前用 Temporal,算一算去掉那套集群后省了多少机器和运维时间;如果流程复杂度不高,收益可能很直接。
  3. 关注扩展的成熟度——这是微软刚开源的项目,API 和稳定性还在演进中,生产使用前务必跟踪 issue 和版本更新。
  4. 从简单流程开始替换——挑一个三五步的内部流程(比如数据清洗、状态机流转)先用 pg_durable 实现,验证崩溃恢复和监控是否满足要求,再考虑更大范围采用。

持久化工作流进数据库,本质上是在用 PostgreSQL 已经很成熟的事务和恢复能力,替代编排引擎专门建的那一层。对很多中等复杂度的业务流程来说,这可能是更务实的选择。


相关推荐