“仅一次”和“至少一次”保证的区别

35
我正在学习分布式系统,并参考这个旧问题:stackoverflow 链接 我真的不理解什么是 exactly-once、at-least-once 和 at-most-once 保证,我在 Kafka、Flink、Storm 和 Cassandra 中读到了这些概念。例如,有人说 Flink 更好,因为它具有 exactly-once 保证,而 Storm 只有 at-least-once。
我知道 exactly-once 模式对于延迟来说更好,但与此同时,它对于容错性来说更差,对吗?如果没有重复项,如何恢复流?那么......如果这是一个真正的问题,为什么 exactly-once 保证被认为比其他保证更好?
有人可以给我更好的定义吗?

3
请查看Kafka文档的这一部分,并告诉我们是否澄清了您的疑虑。 - Luciano Afranllie
4个回答

76

以下定义摘自Akka文档

最多一次传递

对于每个交给机制的消息,该消息被传递零次或一次;更加随意地说,这意味着消息可能会丢失。

至少一次传递

对于每个交给机制的消息,可能进行多次传递尝试,以确保至少有一个成功传递;同样,更加随意地说,这意味着消息可能会重复但不会丢失。

仅一次传递

对于每个交给机制的消息,恰好传递一次到接收方;该消息既不能丢失也不能重复。

第一个是最便宜的-最高性能,最小的实现开销-因为它可以以“fire-and-forget”方式完成,无需在发送端或传输机制中保持状态。第二个需要重试以抵消传输损失,这意味着需要在发送端保持状态,并在接收端具有确认机制。第三个是最昂贵的-因此性能最差-因为除了第二个要求外,还需要在接收端保持状态以过滤出重复交付。


6

这篇文章是一篇值得阅读的激进文章。

我将尝试回答您的问题:

  • 在大型分布式系统中,精确一次无法容错,因为如果某些系统可能会失败,则所有系统都不可能对每个消息达成一致。您可以实现精确一次,但需要进行昂贵的协调,并且需要在至少一次的基础上进行。想想TCP如何确保可靠的数据传输,即使底层IP协议并不可靠。
  • 通过在至少一次的基础上实现精确一次,您将会有重复的消息(如果不是完全相同的),在发生故障时需要去重。
  • 精确一次不被认为更好,因为代价太高,而至少一次在大多数情况下已经足够好了。

4
Flink使用这些术语来讨论事件对应用程序状态的影响。假设我试图计算每天在stackoverflow上带有apache-flink标签的帖子总数。如果我使用恰好一次保证,那么每篇帖子将被计算恰好一次,我的分析将100%正确,即使在途中发生故障并且某些数据需要重新处理来实现这一点。Flink通过全局一致的快照和流重放的组合实现这一点。如果使用至少一次,则如果出现故障,则可能会计算两次某些帖子,但是保证管道会分析每个帖子。如果使用至多一次,则在故障发生时不会进行快照和重放,这将导致如果出现问题,则会低估帖子数量。

恰好一次在正确性和容错方面是最佳的,但会增加一些延迟。

有关此主题的更详细介绍,请参见data Artisans的这篇博客文章以及Flink内部的文档


4

我发现了一个很棒的网站,其中简洁地讨论了所有(或大多数)云计算模式。我真心向你推荐,快去看看吧:http://www.cloudcomputingpatterns.org

仅一次传递

对于许多关键系统而言,重复消息是不可接受的。消息系统通过自动过滤可能的消息重复,确保每个消息只传递一次。

至少一次传递

在出现导致消息丢失或恢复时间过长的故障时,重新传输消息以确保它们至少被传递一次。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接