文章摘要
文章通过实验证明,Postgres的LISTEN/NOTIFY机制在合理配置下具有良好的可扩展性,能够支持大规模并发场景,并非传统认知中的性能瓶颈。
文章总结
好的,这是根据您的要求,对原文主要内容进行的中文重述,已保留关键细节并删除了与主题无关的内容(如Cookie声明、网站导航、页脚等)。
文章标题:Postgres LISTEN/NOTIFY 实际上具备可扩展性
作者: Peter Kraft 发布日期: 2026年7月24日
核心观点: 尽管有观点认为Postgres的LISTEN/NOTIFY机制不可扩展,但通过优化,它实际上可以高效地支持大规模流式数据处理。
文章主要内容:
背景与挑战: Postgres的LISTEN/NOTIFY是一个强大的工具,可用于实现低延迟的持久化通知、数据流和发布/订阅模式。然而,一篇流行的博客文章声称它“不可扩展”,这主要源于NOTIFY操作中一个全局锁导致的性能问题。文章指出,“反直觉的行为”不等于“不可扩展”。
低延迟流式设计:
- 基本方案: 创建一个流数据表,每个数据块(如LLM响应令牌)作为新行插入。
- 读取难题: 读取方不知道新数据何时到达。轮询(Polling)方案在延迟和资源消耗上难以平衡。
- LISTEN/NOTIFY方案: 读取方通过LISTEN阻塞等待通知,写入方在插入新数据后通过触发器发送NOTIFY通知。这种方式能实现低延迟且不浪费资源。
性能瓶颈分析:
- 问题: 初始实现中,每个流写入都触发NOTIFY,导致吞吐量极低(仅约2.9K次写入/秒),且未消耗明显的CPU、内存或IOPS资源。
- 根因: Postgres在提交一个包含NOTIFY的事务时,会获取一个全局排他锁。该锁从事务开始提交时持有,直到事务完全提交并刷新到磁盘(fsync())后才释放。
- 锁的必要性: 该锁用于保证通知按事务提交顺序发送。Postgres需要将所有待发送通知放入一个全局内部队列,其顺序必须与事务提交顺序完全一致。由于提交顺序在提交完成前无法确定,因此需要全局锁来序列化包含NOTIFY的事务提交。
- 影响: 该锁导致所有流写入必须顺序提交,无法利用Postgres的组提交(group commit)等优化,从而形成瓶颈。
优化方案:
- 核心思路: 对于流式应用,通知本身并非数据源,而只是一个“唤醒”读取方去检查数据库表的信号。因此,通知不需要全局有序或完全持久化。
- 具体方法: 将NOTIFY操作在内存中缓冲,并定期批量刷新(flush)到一个事务中提交。这样,全局锁仅在批量刷新时被获取,而非每次写入都获取。
- 容错处理: 引入缓冲区后,进程崩溃可能导致缓冲中的通知丢失。为此,为流读取方增加一个备用方案:除了等待通知外,还定期轮询数据库,检查是否有未收到通知的新数据。由于这只是备用方案,轮询频率可以很低,不影响性能。
优化结果:
- 在优化后的方案中,性能得到大幅提升。在存在并发读取方的情况下,单个Postgres服务器可实现高达60K次流写入/秒(是之前的20倍),同时保持15-100毫秒的低延迟。
- 在最大吞吐量下,Postgres的CPU被充分利用,表明数据库资源得到了有效利用,而非被锁竞争所限制。
总结: 文章通过分析Postgres LISTEN/NOTIFY的全局锁问题,并采用“内存缓冲、批量刷新”的策略,成功绕过了该瓶颈,证明了LISTEN/NOTIFY机制在经过合理优化后,完全能够支撑大规模、高吞吐、低延迟的流式应用场景。
评论总结
根据评论内容,总结如下:
主要观点与论据:
LISTEN/NOTIFY 的可扩展性存在争议
- 评论1指出早期版本存在性能问题(锁机制缺陷),但后续已修正(5月8日勘误)。
- 评论2强调硬性限制:通知数据上限8000字节,不适合传递大型瞬态事件(如游戏状态变更)。
- 评论3认为“扩展性”是连续谱,60K/s对某些系统足够,但对其他系统不足,需根据实际负载选择技术。
- 评论8质疑“扩展性”一词的实用性,认为批量操作可提升性能,但术语本身模糊。
实际应用中的权衡
- 评论7指出许多批评来自未实际使用过的人,强调技术都有其限制。
- 评论9批评实验使用96核/384GB RAM的高端服务器(成本超10万美元),认为真实场景中突发流量才是关键,而非常规负载。
DBOS 与自定义补丁的关联
- 评论4赞赏DBOS利用Postgres实现持久化工作流,但评论5、6质疑优化是否依赖DBOS或自定义补丁(如改变语义)。
平衡性总结:
- 支持方:LISTEN/NOTIFY 适合中小规模项目,与数据库深度集成,减少运维复杂度(评论3、7)。
- 反对方:硬性限制(8000字节)、早期性能问题、高并发场景需谨慎(评论2、1)。
- 中立观点:扩展性需结合具体场景,避免过度优化或低估需求(评论3、8、9)。
关键引用(保留中英文):
- 评论2:“One way it explicitly doesn't scale... is the hard limit on 8000 bytes of data in a notification.”
- 评论3:“'Scale' isn't a binary, it's a continuum... The ceiling of LISTEN/NOTIFY is small enough that you need to pay attention.”
- 评论9:“60k may seem big number, however in real world the things which bring the systems down are the bursts of traffic.”