重复检测

如果应用程序在发送消息后立即由于致命错误而失败,并且重启的应用程序实例错误地认为先前的消息传递未成功,那么后续发送会导致同一消息在系统中出现两次。

也有可能更早在客户端或网络一级出错,导致已发送的消息被提交到队列,可以确认的是消息没有成功返回到客户端。 在这种情况下,客户端就会对发送操作结果产生怀疑。

重复检测支持发送程序重新发送相同的消息,并让队列或主题放弃任何重复的副本,从而消除了这些情况下的各种怀疑。

注意

基本层的服务总线不支持重复检测。 标准层和高级层支持重复检测。 有关这些层之间的差异,请参阅服务总线定价

工作原理

启用重复检测,有助于跟踪在指定时间范围内发送到队列或主题的所有消息的 MessageId(由应用程序控制)。 如果通过已在相应时间范围内记录的 MessageId 发送任何新消息,则会将该消息报告为“已接受”(即发送操作成功),但将立即忽略和删除新发送的消息。 除了 MessageId 之外,不会检查消息的其他任何部分。

应用程序对此标识符的控制至关重要,因为只有它支持应用程序将 MessageId 绑定到业务流程上下文,当出现故障时,可以根据业务流程上下文预测性地重建它。

如果业务流程是在处理某应用程序上下文的过程中发送多个消息,则 MessageId 可能是应用程序级上下文标识符的组合,如采购订单号和消息主题等,例如 12345.2017/payment

虽然 MessageId 可以始终是某个 GUID,但将标识符绑定到业务流程会产生可预测的可重复性,这是有效使用重复检测功能所需要的。

重要

  • 启用分区时,使用 MessageId+PartitionKey 来确定唯一性 。 启用会话时,分区键和会话 ID 必须相同。
  • 禁用分区(默认设置)时,仅使用 MessageId 来确定唯一性 。
  • 有关 SessionIdPartitionKeyMessageId 的信息,请参阅分区键的用法
  • 使用分区并批量发送消息时,应确保消息中不包含任何标识属性的分区。 由于重复数据删除依赖于显式设置消息 ID 来确定唯一性,因此不建议将重复数据删除和批处理与分区一起使用。

注意

计划消息包含在重复检测中。 因此,如果发送计划消息,然后发送重复的非计划消息,则该非计划消息将被删除。 同样,如果发送非计划消息,然后发送重复的计划消息,则该计划消息将被删除。

重复检测窗口大小

除了启用重复检测外,还可以配置重复检测历史时间窗口的大小,在此期间会保留消息 ID。 对于队列和主题,此值默认为 10 分钟,最小值为 20 秒,最大值为 7 天。

启用重复检测和窗口大小会直接影响队列(和主题)的吞吐量,因为必须将记录的所有消息 ID 与新提交的消息标识符进行匹配。

始终保持窗口较小意味着减少了必须保留和匹配的消息 ID,从而降低了对吞吐量的影响。 对于需要启用重复检测的高吞吐量实体,设置的窗口应尽可能小。

后续步骤

可使用 Azure 门户、PowerShell、CLI、资源管理器模板、.NET、Java、Python 和 JavaScript 来启用重复消息检测。 有关详细信息,请参阅启用重复消息检测

在客户端代码无法使用与以前相同的 MessageId 重新提交消息的场景中,设计能够安全地重新进行处理的消息非常重要。 这篇关于幂等性的博客文章介绍了如何实现这一点的各种技术。

尝试采用所选语言的示例,了解 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 的官方支持和更新。 有关详细信息,请参阅支持停用公告