Azure队列-我可以验证邮件只读取一次吗?

Azure队列-我可以验证邮件只读取一次吗?,azure,azure-storage,azure-storage-queues,Azure,Azure Storage,Azure Storage Queues,我正在使用Azure队列,并且有几个不同的进程从队列中读取数据。 我的系统以一种假定每条消息只读取一次的方式构建。 这表明Azure队列至少有一次传递保证,这可能意味着两个进程可以从队列中读取相同的消息。 这表明,如果我使用GetMessage,则在不可见性超时期间,该消息对所有其他进程都不可见 假设我使用GetMessage(),并且在删除邮件之前从未超过邮件不可见时间,我是否可以假设每个邮件只会收到一次?否。可能会发生以下情况: GetMessage() 在数据库中添加一些记录 生成一些文

我正在使用Azure队列,并且有几个不同的进程从队列中读取数据。
我的系统以一种假定每条消息只读取一次的方式构建。
这表明Azure队列至少有一次传递保证,这可能意味着两个进程可以从队列中读取相同的消息。
这表明,如果我使用GetMessage,则在不可见性超时期间,该消息对所有其他进程都不可见


假设我使用GetMessage(),并且在删除邮件之前从未超过邮件不可见时间,我是否可以假设每个邮件只会收到一次?

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

  • GetMessage()
  • 在数据库中添加一些记录
  • 生成一些文件
  • DeleteMessage()->意外故障(进程崩溃、实例重新启动、网络连接问题等)
在这种情况下,您的逻辑是在不调用DeleteMessage的情况下执行的。这意味着,一旦不可见性超时过期,消息将出现在队列中并再次被处理。您需要确保您的流程是:

幂等性是数学和数学中某些运算的性质 计算机科学,它们可以多次应用,而无需 在初始应用程序之外更改结果

另一种解决方案是使用带有ReceiveAndDelete模式的服务总线队列(请参阅如何从队列接收消息下的页面)。如果您收到该消息,它将被标记为已消费,并且不再出现。通过这种方式,您可以确保它最多交付一次(请参阅与存储队列的比较)。但是,如果在处理消息时发生了什么事情(例如:服务器崩溃,…),您可能会丢失有价值的信息

更新:

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

  • GetMessage()
  • DeleteMessage()
  • AddRecordsToDatabase()
  • 生成文件()

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


我想你可以这样假设。我向我的Microsoft Azure联系人问了以下问题:“我非常依赖队列,希望确保如果我获取message()然后删除message(),没有其他进程将从队列中获取相同的消息。根据这一点,队列最多只能有一次保证。这是否意味着两个进程可以读取相同的队列消息并对其进行处理?”回答:是–这正是它的意思。如果希望每个消息只执行一次,则必须使用ServiceBus队列。假设我的进程从未崩溃,并且始终在不可见期内调用DeleteMessage,是否可以假设没有其他进程将获得相同的消息?是(某些内容满足最小字符数)如果是这种情况,我可以做:queue.GetMessage();紧接着是queue.DeleteMessage();在这种情况下,我最多只能保证一次。如果是这样的话,为什么微软声称最多一次没有担保?是的。即使DeleteMessage失败,您也不会执行任何业务逻辑,因此下次可以安全地再次处理该消息。两个进程都可能执行GetMessage()和get ItemA,但其中一个(较慢的一个)在调用DeleteMessage()时会失败,因此不会执行业务逻辑。这是否正确?如果processA检查DequeueCount并看到它是0,会发生什么。然后processA松开CPU,processB检查DequeueCount并发现它为0。ProcessB然后将消息出列,然后processA再次唤醒并将消息出列。这样,它们都在同一队列消息上执行业务逻辑。我在这里遗漏了什么吗?@Gilad-当项目出列时,
DequeueCount
由服务设置,因此线程问题不适用。因此,通过删除
DequeueCount>0
的任何消息,您最多可以实现一次语义。但是我不认为有任何方法可以精确地获得队列的一次性语义。正如“breischl”所说的那样,
DequeueCount
是由队列服务维护的。消息退出队列后,它将为+1。队列服务本身至少实现一次,如果您选中了
DequeuCount>0
,那么我认为您最多实现一次。只有一件事,您最好将dequeucount>0的消息移动到另一个“有毒消息”中,而不是仅仅删除它们,因为这些消息可能意味着某些后台任务尚未完成。但在并发场景中,这是否一致?两个线程是否可以同时将同一消息出列并将其视为
DequeueCount:0
?您不能依赖
DequeCount
@MikeAsdf场景是有效的。在并发阅读场景中,微软并不保证。你需要使用服务巴士