12

我正在使用 Azure 队列,并且有几个不同的进程从队列中读取。
我的系统是以一种假设每条消息只读一次的方式构建的。
这篇Microsoft 文章声称 Azure 队列具有至少一次传递保证,这可能意味着两个进程可以从队列中读取相同的消息。
这个StackOverflow 线程声称,如果我使用GetMessage,那么消息对于所有其他进程变得不可见,因为不可见超时。

假设我使用GetMessage()并且在DeleteMessage之前从未超过消息不可见时间,我可以假设我只会收到每条消息一次吗?

4

2 回答 2

10

我认为队列消息中有一个名为 的属性DequeueCount,即该消息已出列的次数。它由队列服务维护。我认为您可以使用此属性来确定您的消息是否已被阅读过。

https://docs.microsoft.com/en-us/dotnet/api/azure.storage.queues.models.queuemessage.dequeuecount?view=azure-dotnet

于 2012-11-29T02:02:48.327 回答
8

不可以。可能会发生以下情况:

  • 获取消息()
  • 在数据库中添加一些记录...
  • 生成一些文件...
  • DeleteMessage() -> 意外失败(进程崩溃、实例重启、网络连接问题……)

在这种情况下,您的逻辑在没有调用 DeleteMessage 的情况下被执行。这意味着,一旦隐身超时到期,消息将出现在队列中并再次被处理。您需要确保您的进程是幂等的:

幂等性是数学和计算机科学中某些运算的属性,它们可以多次应用而不会改变超出初始应用的结果。

另一种解决方案是将服务总线队列与ReceiveAndDelete模式一起使用(请参阅如何从队列接收消息下的页面)。如果您收到该消息,它将被标记为已使用并且不再出现。这样您就可以确保它是At-Most-Once交付的(请参阅此处与 Storage Queues 的比较)。但是话又说回来,如果您在处理消息时发生了某些事情(即:服务器崩溃,...),您可能会丢失有价值的信息。

更新:

这将模拟存储队列中的 At-Most-Once。消息可以通过 GetMessage 多次到达,但只会由您的业务逻辑处理一次(存在您的某些业务逻辑永远不会执行的风险)。

  • 获取消息()
  • 删除消息()
  • AddRecordsToDatabase()
  • 生成文件()
于 2012-11-28T09:28:55.253 回答