You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PubSub/SQS FIFO如何实现Exactly-Once Delivery?去重层原理解析

谷歌云Pub/Sub Exactly-once交付去重层的实现逻辑

针对你提出的问题,谷歌云Pub/Sub的去重层并没有采用你假设的简单数据库锁流程,而是通过分布式租约机制+原子事务绑定+全局一致性存储解决了这些问题,具体细节如下:

解决“投递前崩溃导致延迟”的问题

你假设的流程里用固定过期时间的锁,确实会出现崩溃后必须等过期才能重试的情况,但Pub/Sub的去重层用的是带心跳续约的租约锁:

  • 当某个投递节点要处理一条消息时,会向全局去重存储申请该消息的投递租约,租约有一个初始有效期(比如几秒)
  • 节点在投递过程中,会定期向去重存储发送心跳,自动续约租约有效期
  • 如果节点在投递前崩溃,心跳中断,租约会被去重存储主动判定为失效并释放,不需要等到自然过期,其他节点可以立刻获取该消息的租约进行重试,完全避免了等待过期的延迟

解决“进程挂起后重复投递”的问题

你的假设流程里锁和发送操作是分离的,容易出现并发冲突,但Pub/Sub把租约申请、投递状态标记、发送操作做了原子绑定:

  • 节点申请租约时,会原子性地在去重存储中记录「消息ID+当前投递节点标识+租约状态」,全局存储的强一致性保证同一时刻只有一个节点能获取到有效租约
  • 节点发送消息时,会把租约的唯一会话ID嵌入到投递请求中,订阅者收到消息后,会自动和去重层校验这个会话ID的有效性
  • 如果原节点挂起后恢复,再次尝试发送同一条消息,去重层会发现该消息的租约已经被释放或者归属其他节点,直接拒绝这个投递请求;即使消息意外发到订阅者,订阅者也会通过会话ID识别为无效重复消息并丢弃
  • 另外,消息的投递确认和去重记录的删除也是原子绑定的:只有当订阅者成功ACK消息,去重层才会彻底删除该消息的投递记录;如果投递失败,租约到期后,其他节点可以安全地重新发起投递

简单来说,Pub/Sub的去重层通过全局一致的分布式存储保证租约的原子性,用心跳续约解决锁过期延迟,用会话ID绑定投递过程避免重复发送,从底层流程上杜绝了你假设的两个问题。

内容的提问来源于stack exchange,提问作者user6412004

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 20:05:34