Spanner 队列概览

Spanner 队列提供事务性消息传递,可帮助您管理异步工作。此功能将该功能与 Spanner 的可伸缩性和可靠性相结合,让您可以构建事件驱动型应用。Spanner 队列使用拉取模型来消费消息,并公开 SQL 接口,供接收者请求和接收消息。

在 Spanner 队列和变更数据流之间进行选择

以下比较可帮助您选择合适的数据传播和异步处理机制。

Spanner 队列

适用场景

  • 事务性事件通知
  • 未来预定执行的工作
  • 每条消息的确认逻辑

主要特征

  • 用户定义的小型消息载荷
  • 用于消息消费的拉取模型
  • 随 Spanner 实例计算容量而扩缩

Spanner 变更数据流

适用场景

  • 高吞吐量数据复制
  • 同步下游缓存或索引
  • 每次数据库更改的审核日志记录

主要特征

  • 捕获所有记录片段(最多 10 MB)
  • 使用分区令牌进行基于拉取的流式传输
  • 包括心跳和检查点

主要优点

Spanner 队列具有以下几项优势:

  • 集成:消息集成到数据库中。这样一来,您就无需预配、管理数据并将其泄露到单独的消息传递基础架构,从而简化应用架构并降低总体成本。
  • 事务性:您可以在 Spanner 事务中以原子方式发送和确认消息,同时进行其他数据库写入操作。如果事务失败,已加入队列的消息会被回滚,无法进行递送。
  • 持久:无法递送的消息会存储在数据库中。 Spanner 会不断尝试递送消息,并采用退避机制,直到消息被明确确认或删除。
  • 可查询:消息基于与 Spanner 表相同的基元构建,并以行的形式存储。您可以像查询标准表一样查询、联接或过滤这些表。
  • 可伸缩:与 Spanner 表具有相同的可伸缩性,消息处理可随数据库的其余部分一起进行扩展。
  • 可靠:Spanner 队列继承了 Spanner 的所有高可用性原语,使消息发送和处理具有容错能力,并且能够应对可用区级或区域级故障。
  • 可调度:消息可以安排在未来发送,让您可以将任务执行延迟到未来的特定时间戳。
  • 原子性:消息发送(INSERT 或变更 API)和确认(DELETE 或变更 API)在事务中以原子方式执行,确保与数据库状态保持一致。
  • 可扩展:通过结合未来交付和手动租用机制,可以延长消息租用时间,以支持极长的处理时间。

使用场景

Spanner 队列可用于在事务中编排延迟任务。常见示例包括:

  • 延迟执行计算密集型工作:照片分享网站可能需要在上传新照片时执行密集型图片处理。写入新照片元数据的事务可以同时写入队列消息。队列接收器随后会提取消息,执行处理,并以事务方式更新元数据。
  • 延迟处理大型事务性更新:在日历应用中,在单个事务中邀请大型群组参加会议可能会导致锁定冲突和尾部延迟。相反,创建日历条目的交易可以为每位受邀者添加一个队列条目,从而允许接收者单独发送邀请。
  • 安排未来任务:提供 30 天免费试用的软件即服务 (SaaS) 公司可以预配用户的资源,同时将预定在 30 天后传送的消息排入队列。然后,工作器会收到该消息并执行试用期到期逻辑。
  • 将工作推迟到外部系统:用户注册后,应用可能需要在数据库注册成功后才发送欢迎电子邮件。注册交易可以向队列添加条目,从而允许工作线程稍后调用外部电子邮件 API。
  • 编排多步流水线:在订单管理系统中,完成订单涉及多个可能单独失败的步骤。通过将每个步骤表示为队列消息,系统可以对流水线的状态进行检查点设置,并从故障点继续运行。

工作流

Spanner 队列的典型工作流如下:

  • 创建队列:使用 DDL 定义队列,类似于定义表。它必须包含 Payload 列(在 PostgreSQL 中为 payload)和主键。
  • 发送消息:使用标准 DML (INSERT) 或变更 API 以事务方式与其他数据库操作一起将消息排入队列。
  • 接收消息:使用 ExecuteStreamingSQL API 调用名为 RECEIVE_QUEUE_NAME() 的表值函数 (TVF)。此函数以长时间运行的查询形式将消息流式传输到客户端。
  • 处理消息:使用应用逻辑消耗从 TVF 收到的消息。
  • 确认消息:使用 DML (DELETE) 或变更 API(例如 ack)从队列中移除消息。这通常在处理完成后在事务中完成。
  • 管理租约:管理消息租约,以确保 Spanner 队列不会在租约超时时重新传送消息。 最常用的方法是使用 RENEWLEASE_QUEUE_NAME() TVF。

此外,请谨记 Spanner 队列的以下核心行为:

  • 至少一次传送:与大多数基于云的队列系统一样,Spanner 承诺至少传送一次。延长租约可以缓解重新传送问题。
  • 最多一次确认:由于确认消息是通过事务完成的,因此 Spanner ACID 语义可确保消息仅被确认一次。按照一次性处理和最多一次确认页面上的方法正确实现最多一次确认。

限制

Spanner 队列存在以下限制:

  • 接收方数量上限:每个队列最多可有 1,000 个具有相同实参的有效接收查询
  • 并发接收 TVF 配额上限:每个项目在每个区域的并发接收 TVF 配额上限为 2,000。如需提高配额限制,请填写为 Cloud Spanner 项目申请增加配额表单。
  • 手动拆分:队列不支持 AddSplits API。 工作负载分配完全依赖于基于负载的分片。建议在表中交织队列,以便用户可以向表中添加分块点。
  • 地理分区合规性:执行 DROP PARTITION 操作后,地理分区队列不符合数据驻留要求。
  • 队列数量限制:对于具有 1 个或多个节点的实例,队列数量限制为 100 个。对于精细实例(例如,具有 200 个处理单元的实例),该限制会按比例缩小到 20 个队列。
  • 删除并重新创建队列:不支持删除并重新创建同名队列。队列的 RECEIVE TVF 可能需要一段时间才能“重置”,然后才能再次接收同名消息。
  • PostgreSQL 列命名:Spanner 同时公开 deliver_timeDeliverTime 列,用于表示消息的传送时间。我们建议使用 deliver_time 列,以便与标准的 PostgreSQL 命名惯例保持一致,并且因为 DeliverTime 列将在未来的版本中从信息架构中隐藏。
  • 命名架构:无法在命名架构中创建队列。

后续步骤