【问题标题】:Detecting where to start replay of messages when some messages might have been lost due to a disaster当某些消息可能由于灾难而丢失时,检测从哪里开始重播消息
【发布时间】:2019-01-14 10:43:29
【问题描述】:

我有一个向多个订阅者发送消息的发布者应用程序。每条消息都被分配一个递增的序列号。假设 A、B 和 C 是三个订阅者,Publisher 已将消息编号 1 发送给 A,将 2,3,4,7 发送给 B,将 5,6 发送给 C。

消息编号 x 将发送给 A、B 还是 C 订阅者是消息的某些不可变属性(不是编号)的函数,即消息编号 7 被路由到 B,因为它可能与符号以开头的股票有关'b'。

发布者有一个映射,其中包含发送给每个订阅者的最大序列号。目前的地图将如下所示:

{"A" -> 1, "B" ->7, "C" ->6}

此时我们不知道这些消息是否成功传递给各自的订阅者。但是,保证消息将按顺序传递。

如果我们遇到需要重启发布者的灾难,我们需要重播可能已经丢失给订阅者的消息。

重要提示:为了向订阅者重播消息,发布者需要向另一个上游服务器发送重播请求,并且它没有持久存储之前看到的所有消息。所以这里的发布者更像是一个路由器。从上游服务器重播消息是有成本的,所以我想尽量减少需要重播的消息数量。

我使用的当前算法是找到每个订阅者收到的最大消息序列。假设我们返回如下内容:

{"A"->1, "B" ->7, "C" ->6}

当前算法只是假设我们需要从订阅者恢复的最小消息数(在本例中为 1)重播。而实际上,只有在这种情况下,我们才需要担心数量大于 7 的消息。

我可以在发布者端定期保存每个订阅者发送的最高消息数的映射。

所以我可以每 5 分钟保存一次地图的状态。如果重新启动后我看到所有订阅者都收到了高于上次保存值的消息号,我可以从最大恢复的序列号(在本例中为 7)重播。这减少了要重播的消息数量。

我认为这个问题可能有一个标准算法,但是网络搜索并没有产生任何有用的东西。如果有人可以向我指出非常有用的相关算法。

请假设:

  • 保存发送给每个订阅者的每个消息号不是一种选择。
  • 订阅者可以很好地处理重复消息,因此我们希望在重播超过所需消息方面犯错。

【问题讨论】:

  • 也许我在这里误解了一些东西,但是如果每个订阅者都有一个单独的频道来接收消息,那么每个频道不应该单独处理吗?
  • 为什么不保留每个订阅者最后发送的消息号,因为在您的情况下订阅者似乎是独立的(他们都可以接收完全不同的消息)?还是我错过了什么?
  • Paul - 是的,订阅者是独立的。假设订阅者 A 看到了 5 号消息,所以我们只需要从发布者的当前状态中判断它是否应该发送高于 5 的任何内容,然后只发送这些消息。这里的问题是发布者在缓存中没有这些消息(它必须从另一个外部 FIX 服务器请求它们)。所以这里的想法是尽量减少我们请求重播的次数。很抱歉没有早点澄清这一点。
  • 为什么不保留每个订阅者最后发送的消息号,因为在您的情况下订阅者似乎是独立的 ----- 是的,它们是独立的,实际上我正在尝试保留最后发送的消息对于每个订阅者,问题是在给定此状态的情况下确定从哪里开始重播。基本上假设发布者突然重新启动,因此它保存在持久存储中的最后发送消息的值可能不是最新的。为每条消息发送更新此状态的成本很高。
  • 好的,那么您有两种情况: 1. 订阅者是完全独立的,在这种情况下,您不能最小化请求,因为您需要请求所有不同的消息; 2.订阅者不是完全独立的,在这种情况下,有时一条消息需要重新发送给多个订阅者。在第 2 种情况下,您需要找到要重新发送给订阅者的常见消息并保留它们,直到它们不再有用为止。

标签: algorithm disaster-recovery


【解决方案1】:

我认为这不需要特定的算法,但您拥有的是特定的用例。我在 Kafka 中看到过类似的用例,每个用例都有一个单独的设置。您的问题的答案归结为订阅者如何阅读消息的问题。

是否所有订阅者在收到更新后都会更新同一个数据库(或执行相同的操作)?在这种情况下,您可以将最新消息(7)发送给其中一位订阅者。

或者每个订阅者在收到消息后都执行自己的操作?然后你需要重播每个订阅者的最新消息。{"A"->1, "B" ->7, "C" ->6}

【讨论】:

  • 每个订阅者都会以相同的方式处理消息,但是我们有一个分区逻辑来决定消息应该去哪里,例如所有与名称以 A 开头的股票相关的消息都会说“A”订户。我们可以确定消息 7 属于订阅者 B,但要做到这一点,我们需要从上游服务器请求重播消息 7 起。我正在寻找最小化重播请求的方法,我可以进行一些特别优化,但我认为可能存在围绕类似问题的模式或算法。
  • 我认为除了持久化该数据@AmolRegmi 之外,您别无选择。为每个订阅者提供一条记录,或为整个订阅者列表提供一条记录,告知当前传递给每个订阅者的消息(根据您的用例选择上述方法之一)。并在您致电订阅者时收到 200 条消息后保留该消息。在重启的情况下,从 DB 中读取消息,并从 DB 中的消息 id 发送所有更新,直到最新的消息 id。
  • 我有一种强烈的感觉,这是一个架构问题,而不是算法问题。
  • 你只需要找到你最后发送的最后一条消息id(或消息id中id的最大值)即可。并从该消息 ID 重播。这不是真的吗?将订阅者读取的最新消息 ID 保存在数据库中。
猜你喜欢
  • 2014-08-23
  • 1970-01-01
  • 2016-09-15
  • 1970-01-01
  • 1970-01-01
  • 2014-01-28
  • 2018-05-09
  • 2022-01-10
  • 2015-05-07
相关资源
最近更新 更多