Postgres是否合适替代Redis或Kafka实现发布订阅作业? - HN


黑客新闻网友针对原文的讨论,原文披露:
使用 postgres 作为其发布/订阅实现,每天处理数十万条消息。postgres 实例现在在 32 个内核和 128GB 内存上运行,并且扩展性很好。
 
Postgres是否合适做些Redis或Kafka的发布订阅作业?下面是网友讨论摘录:
仅仅因为某物可以用来做某事并不意味着它应该做某事。Kafka 是专门为此目的而设计的,它是免费的,并且易于学习和使用。如果“从 Postgres 开始,然后在时机成熟时切换”可以节省资金,那么我可以理解。否则,从一开始就为正确的工作使用正确的工具。
 
这似乎每年至少在 HN 上出现一次。当然它可以工作,但 LISTEN 绑定了一个连接,这限制了可扩展性,因为连接是有限且昂贵的。此外,像 PgBouncer 这样的缓解策略不能与这种方法一起使用(我认为也不能扩展像 CitusDB 这样的解决方案)。
当然,如果可扩展性不是问题(或者连接限制最终在 postgres 中得到修复 - 这在 14 中有所改进),这将是一个非常可行的方法。
 
与几个用户一起创业。高级工程师决定他们需要发布/订阅来发布新功能。借助 Kafka,团队将了解 Kafka 最佳实践、选择客户端库并了解 Kafka 的怪癖。他们还需要启动 Kafka 实例。他们在一个月内交付。使用 postgres,他们可以在一天内获得 MVP,并在一周内发货。
 
我只花了两个月的时间来展开一个不守规矩的 pg_boss 实现,那次经历让我对使用 postgres 进行发布订阅、工作或消息传递感到厌烦。就我而言,Github Actions 适用于不频繁的 cron 作业,或者即使是带有 CloudWatch 规则的小型 lambda 也非常便宜,基础设施即代码可以让任何人都可以轻松(相对如此)部署。毕竟,我宁愿将大部分时间花在编写代码上,也不愿成为 DevOps。如果我需要发布/订阅,我更愿意使用 SNS 快速和肮脏,或 SNS+SQS 来处理繁重的工作。关注点分离和层分离对我来说仍然很重要,我不想依靠维护服务器向前发展。
 
强烈反对将数据库用作消息队列。这篇文章[0] 涵盖了许多原因。总结:额外的应用程序复杂性并且不能很好地与工作人员一起扩展。
https://www.cloudamqp.com/blog/why-is-a-database-not-the-rig...
但是这篇文章可扩展性问题被夸大了。设置正确的隔离级别和锁定模式并不难,现代云托管的 PG/MySQL 可以每秒推送 10 万次插入,没问题。
 
我越来越认为关系数据库绝对是为大多数项目构建队列系统的正确方法。
当您开始从事务的角度考虑它们时,最大的优势之一就会出现。事务保证在这里非常有用:保证如果事务提交成功则将消息写入队列,否则保证消息不会写入队列。https://brandur.org/job-drain描述了使用 PostgreSQL 事务实现这一目标的绝佳模式。
 
rabbitmq 真的很难正确设置,而且诸如优先级、基于时间的调度之类的东西并不比rabbitmq 容易得多。事实上,队列增加了更多的复杂性,除非您超过数据库规模,否则没有必要。并不是说rabbitmq 可能更适合,它只是不适合开始。如果你有一个小于 8 的小团队,最好尽可能少做一些事情,尤其是你知道的事情(很好)。
 
我之前曾考虑过使用 postgres 作为作业队列,但我无法弄清楚如何确保两个进程不会同时执行相同的工作。“FOR UPDATE”和“SKIP LOCKED”是本文中使这项工作成功的关键。本质上,据我所知,“SELECT FOR UPDATE”会在行被选中时锁定它们(锁定在事务之外显然可见),而“SKIP LOCKED”则跳过其他事务已锁定的选择行。
下面的文章讨论了将 postgres 用于作业队列的一些缺点:即数据模型没有优化以查找新作业并将其发送给大量订阅者。像 Kafka/NATS 这样的实际消息传递系统在这方面做得更好。
https://www.2ndquadrant.com/en/blog/what-is-select-skip-lock...
 
这篇文章似乎是“消息队列公司讨厌的一个奇怪的技巧”,因为据我所知,它正在以一种非常具体的方式利用一些 SQL 语义,以拼凑出一种方式来实现其他软件旨在开箱即用的功能. 对于玩具系统来说,这似乎很好,但我不会将一家真正公司的成功押在这种方法上。
 
这篇文章再次证明,在 90% 的情况下 Postgres 是完全足够的。如果您不期望高负载(并且大多数应用程序不期望),那么就使用 Postgres,简单胜出!
 
如果有人希望使用 postgres 作为带有 node.js 客户端的作业服务器,我强烈推荐 pg-boss 库 ( https://github.com/timgit/pg-boss )。看起来它也刚刚添加了 pub/sub(昨天),所以我想你也可以使用它。