Spanner queues正式可用:状态与任务同事务提交,外部API仍需幂等保障

昨天 2阅读

2026年10月2日,Google Cloud宣布Spanner queues正式可用,把事务消息直接引入Spanner数据库。业务可以在同一个读写事务中更新状态并写入队列任务,二者一起提交或一起失败。官方文档目前将该功能列在Enterprise和Enterprise Plus版本中。

Spanner queues正式可用:状态与任务同事务提交,外部API仍需幂等保障

配图为AI生成的概念插图,表现数据库状态与待执行任务在同一事务边界内提交、再交给外部工作进程的关系,不是控制台界面。

先解决“决定了,却没发出去”

当业务状态和消息队列属于两个独立系统,数据库提交成功后消息发送失败,会留下已决定但未执行的动作;反过来,消息先发出而数据库事务回滚,下游可能依据无效状态工作。Spanner queues将排队操作变成事务中的一次写入,直接缩小了这段双写不一致窗口。

官方公告用退款审批说明这种关系:订单进入已批准状态的同时写入退款任务。这里一起提交的是状态和执行意图,真正调用退款服务仍由消费者稍后完成。对多智能体系统而言,同样的设计可以用于记录主智能体的交接状态,并可靠地留下给专门工作进程的任务。

队列可查询,消费仍有租约

消息以类似表行的结构存在,可用SQL检查和过滤;消费者通过ExecuteStreamingSQL调用RECEIVE_队列名函数持续拉取任务。任务带有租约,较长的处理可以用RENEWLEASE_函数续租,完成后通过删除队列行确认。延时投递则允许把未来执行时间与业务更新一起写入。

据此,审批超时提醒可以在记录待审批状态时排队;如果审批提前完成,再在同一事务中更新状态并删除待发提醒。这比在独立定时系统中分别维护两份状态更容易保持一致。不过,已开始执行的外部动作仍需要单独协调,不能仅凭删除一条队列记录就推定现实世界中的操作被撤销。

Exactly-once有明确边界

官方承诺的是至少一次投递和至多一次确认,消息有可能重新投递。若业务修改和确认全部发生在一个Spanner事务内,可在删除消息时使用ASSERT_ROWS_MODIFIED 1,确保已删除的消息不能在重试中再次带动同一份数据库更新。

这里有一个重要实现细节:断言失败属于语句级错误,数据库不会因此自动撤销整个仍打开的事务。官方要求让错误传出事务函数,由客户端放弃事务,或在手动事务中显式回滚;捕获错误后继续提交,反而可能把重复业务写入保存下来。

外部API调用无法与Spanner确认天然形成原子提交。假设退款服务已成功,但工作进程在写回结果前崩溃,消息会再次出现。因此应使用稳定的任务标识作为外部接口的幂等键,并依据接口能力查询、复用已有结果。官方示例同样把TaskId传给外部API作幂等键,文档也警告不要把非事务外部操作放进可能重试的数据库事务函数。

它适合哪一类架构

原生队列适合业务数据已经位于Spanner、需要延迟执行或逐条确认任务的系统。官方将它与change streams区分:后者更侧重数据变更捕获、复制和下游索引同步。部署前还需评估队列处理随实例计算资源扩展的影响。数据库与任务意图合并后,团队减少的是可靠双写的负担,外部系统的幂等、重试与结果核对仍是业务设计的一部分。

官方资料

资料核对:2026年10月3日(北京时间)。产品能力、配置与限制以官方后续更新为准。


文章版权声明:除非注明,否则均为云鹊BLOG原创文章,转载或复制请以超链接形式并注明出处。