Bar*_*lom 8 language-agnostic queue design-patterns transactions reliability
采取这个概念上简单的任务:消耗队列,为每个条目发送电子邮件.
一个简单的方法是:
while true:
entry = queue.pop()
sendMail();
Run Code Online (Sandbox Code Playgroud)
这里的问题是,如果消费者在弹出后但在发送邮件之前/期间崩溃,则邮件丢失.所以你把它改成:
while true:
entry = queue.peek()
sendMail();
queue.pop();
Run Code Online (Sandbox Code Playgroud)
但是现在,如果消费者在邮寄之后崩溃,但在弹出之前,邮件将在消费者重新启动时再次发送.
处理这个问题的最佳实践方法是什么?
发送电子邮件只是一个例子,可以替代任何关键任务.还假设队列的弹出是已发送邮件的唯一记录,因此邮件子系统本身不记录任何内容.
您的要求是否看起来像是试图解决两个将军问题(没有确定性解决方案/限制)?https://en.wikipedia.org/wiki/Two_Generals%27_Problem
窥视 - 处理 - 删除
您只想在确保成功处理后才删除,并确保正确删除。那么任何这些消息都可能丢失/程序可能在任何步骤崩溃。
大多数强大的消息队列依赖于一组 ack + 重复尝试(交付)来获得所需的行为(直到 ack 返回)。
但实际上不可能保证在每种情况下都有完美的行为。您只需要最终权衡可能性,并在重复(至少尝试)处理和“从不”(无限内存等)丢失消息之间做出工程折衷 - 具体到您的实际应用程序需求。这又不是一个新问题:),并且您不太可能需要为其编写临时代码 - 就像我提到的,大多数 MQ 都解决了这个问题。