Spanner 队列提供事务性消息传递,可帮助您管理异步工作。该功能将此功能与 Spanner 的可伸缩性和可靠性相结合,让您可以构建事件驱动型应用。Spanner 队列使用拉取模型来使用消息,并提供 SQL 接口供接收方请求和接收消息。
在 Spanner 队列和变更数据流之间进行选择
以下比较提供了有关如何选择合适的数据传播和异步处理机制的指导。
Spanner 队列适用场景
主要特征:
|
Spanner 变更数据流适用场景
主要特征:
|
主要优点
Spanner 队列具有以下几项优势:
- 集成:消息传递功能已集成到数据库中。这样就无需预配、管理数据以及将数据渗漏到单独的消息传递基础架构,从而简化了应用架构并降低了总体成本。
- 事务性:您可以在 Spanner 事务中以原子方式发送和确认消息,同时执行其他数据库写入操作。如果事务失败,已加入队列的消息会回滚,并且无法传送。
- 持久性:无法递送的消息会存储在数据库中。Spanner 会持续尝试递送消息并采用退避算法,直到消息被明确确认或删除。
- 可查询:消息基于与 Spanner 表相同的基元构建,并存储为行。您可以像查询、联接或过滤标准表一样查询、联接或过滤这些表。
- 可扩缩:消息处理功能与 Spanner 表具有相同的可伸缩性,可随数据库的其他部分一起扩缩。
- 可靠:Spanner 队列继承了 Spanner 的所有高可用性原语,使消息发送和处理具有容错能力,并能从可用区级或区域级故障中恢复。
- 可调度:可以调度消息以供将来传送,从而允许您将任务执行推迟到将来的特定时间戳。
- 原子性:消息发送(
INSERT或变更 API)和确认(DELETE或变更 API)在事务中以原子方式执行,确保与数据库状态保持一致。 - 可延长:通过结合未来传送和手动租用机制,可以延长消息租用时间,以支持极长的处理时间。
使用场景
Spanner 队列对于在事务中编排延迟任务非常有用。常见示例包括:
- 推迟计算密集型工作:照片分享网站可能需要在上传新照片时执行密集型图片处理。写入新照片元数据的事务可以同时写入队列消息。队列接收器稍后会提取消息、执行处理并以事务方式更新元数据。
- 推迟大型事务性更新:在日历应用中,在单个事务中邀请大型群组参加会议可能会导致锁定冲突和尾部延迟。相反,创建日历条目的事务可以为每个邀请对象添加一个队列条目,从而允许接收器单独发送邀请。
- 安排未来任务:提供 30 天免费试用期的软件即服务 (SaaS) 公司可以预配用户资源,同时将计划在 30 天后传递的消息加入队列。然后,工作器会收到消息并执行试用期到期逻辑。
- 将工作推迟到外部系统:用户注册后,应用可能需要在数据库注册成功后才发送欢迎电子邮件。注册事务可以向队列添加条目,以便工作器稍后调用外部电子邮件 API。
- 编排多步流水线:在订单管理系统中,履行订单涉及多个可能独立失败的步骤。通过将每个步骤表示为队列消息,系统可以检查流水线的状态并从故障点继续。
工作流
Spanner 队列的典型工作流遵循以下步骤:
- 创建队列:使用 DDL 定义队列,类似于创建表。它必须包含
Payload列(PostgreSQL 中为payload)和主键。 - 发送消息:使用标准 DML (
INSERT) 或变更 API 将消息排入队列,并与其他数据库操作一起作为事务执行。 - 接收消息:使用
ExecuteStreamingSQLAPI 调用名为RECEIVE_QUEUE_NAME()的表值函数 (TVF)。此函数会以长时间运行的查询的形式将消息流式传输到客户端。 - 处理消息:使用应用逻辑使用从 TVF 接收的消息。
- 确认消息:使用 DML (
DELETE) 或变更 API(例如ack)从队列中移除消息。这通常在事务中处理完成后完成。 - 管理租约:管理消息租约,确保 Spanner 队列不会在租约超时时重新传送消息。最常见的方法是使用
RENEWLEASE_QUEUE_NAME()TVF。
此外,请注意 Spanner 队列的以下核心行为:
- 至少一次传送:与大多数基于云的队列系统一样,Spanner 承诺至少一次传送。可以通过延长租约来减少重新传送。
- 至多一次确认:由于确认消息是通过事务进行的,因此 Spanner ACID 语义可确保消息仅确认一次。按照“正好一次”处理和“最多一次”确认页面上的方法,正确实现“最多一次”确认。
限制
Spanner 队列存在以下限制:
- 接收器数量上限:每个队列中具有相同参数的活跃接收查询数量上限为 1,000 个
- 并发接收 TVF 配额限制:每个项目每个区域有 2,000 个并发接收 TVF 的配额限制。如需提高配额限制,请填写为 Cloud Spanner 项目申请增加配额表单。
- 手动拆分:队列不支持
AddSplitsAPI。工作负载分配完全依赖于基于负载的分片。建议在表中交错队列,以便用户可以向表中添加分块点。 - 地理分区合规性:执行
DROP PARTITION操作后,地理分区队列不符合数据驻留要求。 - 队列数量限制:对于具有 1 个或多个节点的实例,实例最多只能有 100 个队列。对于精细实例,该限制会按比例缩容(例如,具有 200 个处理单元的实例限制为 20 个队列)。
- PostgreSQL 列命名:Spanner 会同时公开消息传送时间的
deliver_time和DeliverTime列。我们建议使用deliver_time列,以便与标准 PostgreSQL 命名惯例保持一致,并且DeliverTime列将在未来版本中从信息架构中隐藏。 - 命名架构:无法在命名架构中创建队列。
后续步骤
- 了解如何使用 Spanner 队列,包括最佳实践和监控。
- 探索更多 Spanner 队列场景和示例。
- 了解“正好一次”处理和“最多一次”确认。
- 使用队列的精细访问权限控制配置访问权限控制。