重复检测
如果应用程序在发送消息后立即由于致命错误而失败,并且重启的应用程序实例错误地认为先前的消息传递未成功,那么后续发送会导致同一消息在系统中出现两次。
也有可能更早在客户端或网络一级出错,导致已发送的消息被提交到队列,可以确认的是消息没有成功返回到客户端。 在这种情况下,客户端就会对发送操作结果产生怀疑。
重复检测支持发送程序重新发送相同的消息,并让队列或主题放弃任何重复的副本,从而消除了这些情况下的各种怀疑。
注意
基本层的服务总线不支持重复检测。 标准层和高级层支持重复检测。 有关这些层之间的差异,请参阅服务总线定价。
工作原理
启用重复检测,有助于跟踪在指定时间范围内发送到队列或主题的所有消息的 MessageId
(由应用程序控制)。 如果通过已在相应时间范围内记录的 MessageId
发送任何新消息,则会将该消息报告为“已接受”(即发送操作成功),但将立即忽略和删除新发送的消息。 除了 MessageId
之外,不会检查消息的其他任何部分。
应用程序对此标识符的控制至关重要,因为只有它支持应用程序将 MessageId
绑定到业务流程上下文,当出现故障时,可以根据业务流程上下文预测性地重建它。
如果业务流程是在处理某应用程序上下文的过程中发送多个消息,则 MessageId
可能是应用程序级上下文标识符的组合,如采购订单号和消息主题等,例如 12345.2017/payment。
虽然 MessageId
可以始终是某个 GUID,但将标识符绑定到业务流程会产生可预测的可重复性,这是有效使用重复检测功能所需要的。
重要
- 启用分区时,使用
MessageId+PartitionKey
来确定唯一性 。 启用会话时,分区键和会话 ID 必须相同。 - 禁用分区(默认设置)时,仅使用
MessageId
来确定唯一性 。 - 有关
SessionId
、PartitionKey
和MessageId
的信息,请参阅分区键的用法。 - 使用分区并批量发送消息时,应确保消息中不包含任何标识属性的分区。 由于重复数据删除依赖于显式设置消息 ID 来确定唯一性,因此不建议将重复数据删除和批处理与分区一起使用。
注意
计划消息包含在重复检测中。 因此,如果发送计划消息,然后发送重复的非计划消息,则该非计划消息将被删除。 同样,如果发送非计划消息,然后发送重复的计划消息,则该计划消息将被删除。
重复检测窗口大小
除了启用重复检测外,还可以配置重复检测历史时间窗口的大小,在此期间会保留消息 ID。 对于队列和主题,此值默认为 10 分钟,最小值为 20 秒,最大值为 7 天。
启用重复检测和窗口大小会直接影响队列(和主题)的吞吐量,因为必须将记录的所有消息 ID 与新提交的消息标识符进行匹配。
始终保持窗口较小意味着减少了必须保留和匹配的消息 ID,从而降低了对吞吐量的影响。 对于需要启用重复检测的高吞吐量实体,设置的窗口应尽可能小。
后续步骤
可使用 Azure 门户、PowerShell、CLI、资源管理器模板、.NET、Java、Python 和 JavaScript 来启用重复消息检测。 有关详细信息,请参阅启用重复消息检测。
在客户端代码无法使用与以前相同的 MessageId 重新提交消息的场景中,设计能够安全地重新进行处理的消息非常重要。 这篇关于幂等性的博客文章介绍了如何实现这一点的各种技术。
尝试采用所选语言的示例,了解 Azure 服务总线功能。
- 适用于 .NET(最新)的 Azure 服务总线客户端库示例
- 适用于 Java(最新)的 Azure 服务总线客户端库示例
- 适用于 Python 的 Azure 服务总线客户端库示例
- 适用于 JavaScript 的 Azure 服务总线客户端库示例
- 适用于 TypeScript 的 Azure 服务总线客户端库示例
在此处查看早期 .NET 和 Java 客户端库示例:
注意
2026 年 9 月 30 日,我们将停用 Azure 服务总线 SDK 库 WindowsAzure.ServiceBus、Microsoft.Azure.ServiceBus 和 com.microsoft.azure.servicebus,这些库不符合 Azure SDK 准则。 我们还将结束对 SBMP 协议的支持,因此在 2026 年 9 月 30 日之后,你将无法再使用此协议。 请在该日期之前迁移到最新的 Azure SDK 库,新库提供了关键安全更新和改进功能。
尽管旧库在 2026 年 9 月 30 日之后仍可使用,但它们将不再获得 Azure 的官方支持和更新。 有关详细信息,请参阅支持停用公告。