Agent 把订单状态从"待支付"改成"已支付",然后没有然后了。该发的确认邮件没发出去,而数据看起来完全正常。
10 月 2 日,谷歌宣布 Spanner Queues 正式全面开放。它要做的事一句话能说完:让"改数据"和"排下一个任务"变成同一次提交,要么一起成,要么一起不成。
队列从外部中间件变成表里的一行
过去的做法是把两件事分给两个系统:业务数据写进数据库,待办任务发进消息队列。数据提交成功、消息没发出去,任务就永久丢了;消息发出去了、数据回滚了,任务又会对着一个不存在的状态往下跑。这个窗口很窄,但它一直在。
Spanner Queues 只是换了个位置:消息不发给外部服务,而是写进 Spanner 的表,成为一行普通的行。它和触发它的那次数据变更在同一个读写事务里提交,谷歌把这种操作叫"决定并行动"。
拆开看,它是几块 SQL 能力拼起来的:
- 原子入队:在标准读写事务里创建消息,与数据一起提交或一起回滚
- 定时投递:可以指定将来某个时刻才可见,延迟重试、定时回访不用再外挂调度器
- 租约加逐条确认:消费者取走消息后持有租约,处理完按条确认,租约到期后消息可以重新投递
- SQL 拉取消费:用流式查询取消息,消费端不用再学一套新协议
因为消息就是表里的行,还有两个副作用:等待中的任务可以被 join、被过滤;"现在积压了多少、哪些超时了"这类问题能直接写 SQL 查,不必新建一套监控。
它补的不是吞吐,是"决定"和"行动"的裂缝
放到具体场景里看。一个 agent 干活是个循环:读状态、做判断、写回数据、排出下一步。前两步和后两步分属两个系统时,任何一次超时都能让循环停在中间,状态已经改了,任务却没排上,日志两边都不报错。
多 agent 协作时这个问题会被放大。A 交接给 B 的那一刻,交接记录和任务必须在同一个事务里落地,否则 B 可能拿着过期的上下文开工。官方博客里还提到,agent 的记忆落库和任务交接同