Hacker News 中文摘要

RSS订阅

Postgres事务:分布式系统的超能力 -- Postgres transactions are a distributed systems superpower

文章摘要

文章主张将工作流状态与数据共同部署,以提升系统性能和可靠性。通过减少网络延迟和简化架构,这种设计能更高效地管理事务,避免分布式协调的复杂性,尤其适用于需要强一致性的应用场景。

文章总结

好的,这是根据您的要求,对原文主要内容进行的中文重述,保留了核心细节,并删除了与主题无关的页面元素(如导航栏、页脚、Cookie声明等)。


文章标题:将工作流状态与数据共存:Postgres事务是分布式系统的超能力

核心观点:

本文主张,在构建持久化工作流系统时,不应将工作流状态和应用数据分离存储,而应将它们共同部署在同一个Postgres数据库中。这种“数据共存”的策略,利用数据库事务的原子性,能极大地简化分布式系统中常见的幂等性和原子性难题。

主要论点与细节:

  1. 误解澄清:作者此前提出“只用Postgres”来实现持久化工作流,但被误解为仅指使用一个将状态存储在Postgres中的工作流引擎。作者真正的意思是,工作流系统本身应该与应用数据运行在同一个Postgres数据库实例中

  2. 共存的优势:在分布式系统中,数据共存是一种“超能力”。当工作流元数据和应用数据在同一个Postgres数据库中时,它们可以在同一个数据库事务中被更新。这意味着部分失败不再可能发生,从而更容易构建能正确处理所有边缘情况的工作流。

  3. 解决幂等性问题

    • 问题:持久化工作流通过检查点(checkpoint)实现容错。但工作流可能在完成一个步骤后、记录检查点前崩溃。恢复时,由于没有该步骤已执行的记录,会重新执行,导致非幂等操作(如银行账户加钱)被重复执行。
    • 传统方案:需要在应用层添加额外的记账逻辑(如applied_payments表)来防止重复,增加了复杂性。
    • 共存方案:工作流引擎可以在同一个数据库事务中,既执行步骤的数据库更新,又写入步骤的检查点。如果事务提交,更新和检查点都持久化,保证步骤恰好执行一次;如果事务失败,两者都回滚,工作流恢复后可安全地从头重试。这消除了应用层的幂等性需求。
  4. 解决原子性问题

    • 问题:可靠地在多个系统中执行更新(如更新数据库记录并同时通知另一个系统)需要原子性,即要么都发生,要么都不发生。
    • 传统方案:使用“事务性发件箱”模式。在一个数据库事务中,同时更新业务记录并向一个“发件箱”表写入消息,再由一个后台进程轮询并投递消息。这引入了额外的运维复杂性(轮询、重试、监控、数据同步等)。
    • 共存方案:利用数据库支持的工作流,通过一个Postgres用户自定义函数(UDF),在同一个数据库事务中,既执行应用更新,又将工作流(表示为数据库中的一行)入队。这保证了原子性:要么更新完成且工作流入队,要么都不发生。之后,一个工作进程可以异步地、可靠地执行该工作流。

结论:

通过将工作流状态与应用数据在Postgres中“共存”,可以显著简化分布式系统的设计,解决幂等性和原子性等核心难题。DBOS的目标就是让这种基于Postgres的持久化执行变得尽可能简单和高效。

评论总结

根据评论内容,总结主要观点如下:

1. 对“分布式系统”定义的质疑(评分:无) - 评论1指出:“Is it really a distributed system or just a bunch of services with a central database?”(这真的是分布式系统,还是只是带中央数据库的一组服务?) - 评论10批评:“Postgres transactions are not distributed.”(Postgres事务不是分布式的。)

2. 对事务一致性与工作流耦合的讨论(评分:无) - 评论4认为:“the database itself becomes tightly coupled to the workflow, which will make it architecturally difficult to separate later on.”(数据库与工作流紧密耦合,后续架构分离困难。) - 评论7质疑outbox模式:“just pretend that you have a transaction across D and Q.”(只是假装在数据库和消息队列间有事务。)

3. 对UDF和外部系统交互的担忧(评分:无) - 评论2指出:“writing a row in a system in order to update the second one at any random time in the future isn't much different from enqueuing a job in queue.”(写入一行数据以在未来随机时间更新第二个系统,与入队任务没有本质区别。) - 评论11补充:“your external system has to poll and retry either way.”(外部系统无论如何都需要轮询和重试。)

4. 对Postgres作为状态存储的认可(评分:无) - 评论6表示:“We’ve got an in-house pubsub solution that lives in the main applications database... the atomicity it allows is indeed really nice!”(我们内部有基于主数据库的pubsub方案,其原子性确实很好。) - 评论5分享实践经验:“We've leveraged the atomicity of transactions with a fail-safe approach for external service interactions.”(我们利用事务原子性结合故障安全方法处理外部服务交互。)

5. 对单点故障风险的警告(评分:无) - 评论12指出:“when the database goes down it all goes down, so you get to fix nothing most days then everything all at once.”(数据库宕机时一切崩溃,平时无事可修,出问题则全部同时爆发。)

6. 对文章标题和概念的批评(评分:无) - 评论10认为:“The article is ridden with misconception... The title is also misleading.”(文章充满误解,标题具有误导性。) - 评论8质疑:“Where is the distributed part? You store data in a single transaction into postgres.”(分布式体现在哪里?你只是将数据存储在Postgres的单个事务中。)

平衡总结: 评论者普遍认可Postgres事务原子性在简化工作流方面的价值,但对其是否真正实现“分布式”存在根本分歧。支持者强调原子性带来的可靠性,反对者指出其本质仍是单点系统,且与外部系统交互时仍需妥协。多数评论认为outbox模式只是将问题转移而非解决,并警告紧密耦合带来的架构风险。