持久化执行:硬核方式
摘要
一本教程指南,教你如何受Kubernetes the hard way启发,从零开始使用Go和Postgres构建持久化执行引擎。
查看缓存全文
缓存时间: 2026/05/29 19:21
hatchet-dev/durable-execution-the-hard-way
来源: https://github.com/hatchet-dev/durable-execution-the-hard-way
持久化执行,硬核方式
受 Kelsey Hightower 的 Kubernetes the hard way(https://github.com/kelseyhightower/kubernetes-the-hard-way)启发,我们将使用 Go 和 Postgres 从头构建一个持久化执行引擎。
持久化执行是一种机制,能够在函数执行过程中逐步检查其状态,以便在意外失败时从断点恢复执行。它在实现 AI 智能体的现代技术栈和项目中尤为重要,因为 AI 智能体通常是长时间运行且有状态的。实现持久化执行的系统通常被称为“工作流引擎”。
本指南使用 Go 和基于 sqlc(https://sqlc.dev/)的模板化 SQL。唯一的依赖是:
- Go 1.25+
- Postgres(默认通过 Docker 创建)
- pgx
如果你有兴趣为其他语言贡献支持,请创建一个 Github issue。我将在 Twitter(https://x.com/abelanger5)上分享本指南的更新(新课程、其他语言),欢迎关注。
目标受众
如果你符合以下情况,本指南将对你有帮助:
- 希望深入理解 Hatchet 和 Temporal 等持久化执行引擎的工作原理
- 正在实现自己的工作流引擎,并希望获得一个简单的架构起点
本指南要求你掌握 SQL 数据库的基础知识,能够阅读代码,并熟悉一些基本的后端工程概念(如队列)。每节课都会介绍更高级的术语。
关于持久化执行的入门指南,请参阅博客文章《如何思考持久化执行》(https://hatchet.run/blog/durable-execution)。
课程导航
/lessons 目录下的每个文件夹都采用相同的结构:
- 一个
README.md文件用于浏览课程 - 一个
main.go文件用于运行课程生成的示例代码,可通过go run .执行 - 一个
sql目录,包含schema.sql、queries.sql以及一些用于通过sqlc生成模板化查询的文件
到最后一课时,我们将拥有一个最小但可以正常运行的工作流引擎。请注意,这些课程不关注开发人员体验:我们将构建理解基础知识所需的最小功能,但不会实现客户端 SDK 中常见的便利特性。
课程
观点
本指南对持久化执行持有些许主观看法。具体来说,它实现了:
- 完全在 Postgres 中实现的持久化执行。
- 两种类型函数:持久化任务和常规任务。这两种任务直接对应 Hatchet 中的持久化任务和任务,类似于 Temporal 的工作流和活动。
- 常规任务可作为独立任务调用,这意味着本指南在前几课中也实现了一个简单的基于 Postgres 的任务队列。
- 多种类型的重试和重放,它们被视为不同的操作:
- 重试会重试一个持久化任务而不重置事件历史(保留函数的执行状态)
- 重放会将持久化任务的执行历史重置为从头开始
- 分支会在执行历史的某个点重置持久化任务的执行历史,从而有效地创建该任务的一个“分支”。这将是未来一课的主题。
修改课程
你可以修改每节课的 schema、查询和代码进行实验。要重新生成每个目录中的 SQL 文件,请运行以下命令:
go run github.com/sqlc-dev/sqlc/cmd/sqlc generate --file sql/sqlc.yaml
报告问题
如果你发现某节课的核心逻辑中存在错误,请提交一个 Github issue。我们将很高兴用附近面包店的烘焙食品奖励你(没错,我们是认真的)。如果没有面包店,我们很高兴送你一件 Hatchet T恤或帽子。如果你并不想要更多供应商赠品,我将对你永怀感激。
使用 AI
本指南中的任何文字均未使用 AI 撰写。所有错误和措辞都是我的个人问题。AI 用于:
- 验证本指南的每节课均可独立运行且说明易于遵循
- 生成 mermaid 图
未来课程构想
如果大家兴趣足够,我很乐意再编写一些额外的课程,例如:
- 使用 Postgres 的
LISTEN/NOTIFY大幅提升处理速度 - 持久化睡眠
- 持久化事件日志的分支与分叉
相似文章
生产中的荒谬
Armin Ronacher(pocoo)分享了他在Absurd(一个完全基于Postgres构建的持久执行系统)上的生产经验,重点介绍了诸如分解步骤、任务结果以及名为absurdctl的命令行工具等改进。
我刚刚为了可靠性重写了整个代理基础设施,有人也这样做吗?
作者描述了在遭遇级联故障后,使用DBOS持久化执行重写其AI代理基础设施以提高可靠性的经历,并向社区询问类似的经历、工具选择以及自建与购买决策。
从Go迁移到Rust
一份为Go开发者迁移到Rust编写的全面指南,专注于后端服务,对比正确性、运行时和人体工程学方面的权衡,并提供关于渐进式迁移的实用建议。
优化CPU密集型Go热路径的笔记
本文讨论了CPU密集型Go代码的性能优化技术,指出了泛型和接口抽象因无法内联而产生的局限性,并主张在热路径中使用代码复制。文章通过一个Brotli移植示例和深入基准测试进行了说明。
在遇到 LangGraph 天花板后,我构建了自己的智能体运行时——将 UI 作为图节点,Postgres 持久化,零编排成本
作者介绍了 cascaide,这是一个全栈智能体运行时和 AI 编排框架,使用 TypeScript 编写,可在任何支持 JS/TS 的环境运行。它提供 UI 作为图节点、持久化 Postgres 检查点、零编排成本,并且设计为可自托管,无供应商锁定。