艰难之路:持久执行
速览
持久执行旨在确保任务即使在中断后也能恢复,但传统方法需开发者手动处理状态持久化、重试逻辑及幂等性。本文深入分析了这种“硬”方式带来的工程复杂性与维护成本。尽管缺乏自动化框架支持,理解其底层原理对构建高可靠系统至关重要。
AI 深度解读
深度解读:Durable Execution the Hard Way —— 从零构建持久化执行引擎
背景
受 Kelsey Hightower 著名的《Kubernetes the Hard Way》启发,本文档旨在通过 Go 语言和 Postgres 数据库,从零开始构建一个持久化执行引擎(Durable Execution Engine)。
持久化执行是一种机制,它允许函数在推进过程中对状态进行增量检查点(checkpoint)。当发生非预期故障时,函数可以从断点处恢复执行。这一概念在实现 AI Agent(智能体)的新兴技术栈中尤为重要,因为 AI Agent 通常具有长运行(long-running)和状态保持(stateful)的特征。实现持久化执行系统的通常被称为“工作流引擎”(Workflow Engine)。
本指南的目标读者是那些希望深入理解 Hatchet 和 Temporal 等持久化执行引擎底层原理,或者正在构建自己的工作流引擎并寻求简单架构起点的开发者。
核心内容
本指南采用了一种“硬核”的学习路径,专注于理解基础原理,而非开发者体验(Developer Ergonomics)。最终目标是构建一个最小化但功能完整的工作流引擎。
技术栈与依赖
- 语言:Go 1.25+
- 数据库:Postgres(默认通过 Docker 创建)
- ORM/查询生成:pgx 配合 sqlc 生成的模板化 SQL。
课程结构与执行方式
指南分为多个章节(Lessons),每个章节的目录结构一致:
README.md:导航说明。main.go:运行示例代码,可通过go run .执行。sql/目录:包含schema.sql、queries.sql以及用于通过 sqlc 生成模板化查询的文件。
课程大纲
整个构建过程分为以下七个阶段:
- Prerequisites:前置准备。
- Simple task queue:简单的任务队列。
- Limiting concurrent tasks:限制并发任务。
- Task queue improvements:任务队列改进。
- Durable event log:持久化事件日志。
- Tracking non-determinism:跟踪非确定性行为。
- Durable tasks:持久化任务。
设计理念与特性
本指南提供了一种观点鲜明的持久化执行实现方案,具体特点如下:
- 完全基于 Postgres:所有持久化执行逻辑均在 Postgres 中实现。
- 两种函数类型:
- Durable Tasks(持久化任务):对应 Hatchet 中的 Durable Tasks,或 Temporal 中的 Workflows。
- Regular Tasks(常规任务):对应 Hatchet 中的 Tasks,或 Temporal 中的 Activities。
- 独立调用的常规任务:常规任务可以作为独立任务调用,这意味着在前几课中,指南实际上也实现了一个简单的基于 Postgres 的任务队列。
- 区分重试(Retries)与重放(Replays):
- Retries:重试持久化任务时,不重置事件历史记录,保留函数的执行状态。
- Replays:重置持久化任务的执行历史,从头开始。
- 注:Forking(分叉)将在未来课程中介绍,它允许在历史记录的某一点重置,从而创建任务的“分叉”。
使用与贡献
- 实验性:读者可以修改每个章节中的 Schema、查询和代码进行实验。
- 代码生成:若要重新生成目录中的 SQL 文件,需运行:
go run github.com/sqlc-dev/sqlc/cmd/sqlc generate --file sql/sqlc.yaml - 反馈与奖励:如果发现核心逻辑错误,请提交 GitHub Issue。作者承诺奖励来自附近面包店的烘焙食品,或 Hatchet 的周边(T恤/帽子)。若不需要周边,作者的感激之情同样永恒。
关于 AI 的使用声明
- 人工撰写:本文档的所有文字内容均由人工撰写,未使用 AI 生成。
- AI 辅助:AI 仅用于验证每个章节的可独立运行性、确保指令易懂,以及生成 Mermaid 图表。
- 未来扩展:如果兴趣浓厚,未来可能增加关于使用 Postgres
LISTEN/NOTIFY加速处理、持久化睡眠(Durable sleep)以及事件日志分支/分叉的课程。
关键要点
- 核心目标:通过从零构建,深入理解 Temporal、Hatchet 等主流工作流引擎的底层持久化执行机制。
- 技术选型:使用 Go 语言、Postgres 数据库和 sqlc 进行模板化 SQL 生成,保持依赖极简。
- 学习路径:从简单的任务队列开始,逐步引入并发控制、持久化事件日志、非确定性跟踪,最终实现完整的持久化任务。
- 概念区分:明确区分了“常规任务”(类似 Temporal Activity)和“持久化任务”(类似 Temporal Workflow),并严格区分了“重试”(保留状态)和“重放”(重置状态)的行为差异。
- 非生产级 SDK:本指南侧重于理解基础原理,不包含典型客户端 SDK 的便利功能(如复杂的错误处理、自动重试配置等),旨在构建“最简可行”的核心逻辑。
- 社区互动:作者鼓励贡献其他语言的支持,并对发现核心逻辑错误的贡献者提供实物奖励(面包或周边)。
意义与影响
1. 降低 AI Agent 开发门槛
随着 AI Agent 应用的普及,处理长运行、状态保持的任务成为常态。传统的函数调用模型难以应对网络抖动、服务重启等故障。通过理解持久化执行引擎的构建原理,开发者可以更稳健地设计 AI 工作流,确保 Agent 在复杂环境下的可靠性和可恢复性。
2. 透视“黑盒”架构
Temporal 和 Hatchet 等工具虽然强大,但其内部机制往往对开发者透明。本指南通过“硬核”方式拆解了这一黑盒,揭示了如何利用关系型数据库(Postgres)实现复杂的分布式状态管理和事件溯源(Event Sourcing)。这对于希望定制工作流引擎或优化现有引擎性能的工程师具有极高的参考价值。
3. 强调基础与原理
在框架泛滥的今天,本指南回归基础,强调 SQL 数据库和 Go 语言在构建可靠系统中的作用。它证明了即使没有复杂的分布式基础设施,仅凭 Postgres 和精心设计的 Schema,也能构建出具备生产级可靠性的工作流引擎。这种“少即是多”的设计哲学有助于开发者更好地理解系统边界和故障恢复机制。
4. 促进开源社区协作
作者通过提供清晰的课程结构和明确的贡献路径,鼓励社区参与完善这一教程。这种开放的态度不仅有助于技术传播,也为其他语言的实现者提供了参考范式,推动了持久化执行技术在更广泛生态中的落地。
