1

我们有一个 Kafka 队列,有两个消费者,都从同一个分区读取(扇出场景)。其中一个消费者应该是金丝雀并处理 1% 的消息,而另一个处理剩下的 99% 的消息。

这个想法是基于消息的属性做出决定,例如消息 ID 或时间戳(例如 mod 100),并基于此接受或丢弃,只是针对金丝雀和非金丝雀的相反逻辑。

现在我们面临如何稳健地做到这一点的问题,例如在运行时重新配置百分比并避免丢失消息或处理它们两次。看起来这升级为分布式共识问题以保持决策逻辑同步,我们非常希望避免这种情况,即使我们可以只使用 ZooKeeper。

这是一个可行的策略,还是有更好的方法来做到这一点?可能是一种避免达成共识的方法?

更新:不幸的是,Kafka 集群不在我们的控制之下,我们无法进行任何更改。

更新 2消息延迟不是一个大问题,添加几百个 100 毫秒是可以的,不会被注意到。

4

1 回答 1

3

我没有看到任何方法可以在不“忽略”或双重处理记录的情况下更改 2 台机器的“采样策略”。由于不同的 Kafka 消费者可能位于分区中的不同位置,并且还可能在不同时间获取新配置,因此您不可避免地会遇到以下两种情况之一:

  1. 两台机器对同一记录进行双重处理
  2. “跳过”一条记录,因为任何一台机器在看到它时都不认为它应该“拥有”它。

我建议对您的架构进行一些小改动:

  • 让 99% 的机器(非金丝雀)拾取所有记录,然后为每条记录决定它是否要处理它,或者它是否属于金丝雀
  • 如果属于金丝雀,则将记录发送到第二个主题(来自 99% 的机器)
  • Canary 机器只监听第二个主题,并处理每个到达的记录

现在您有了一个管道设置,其中只在一个点上做出决策,没有记录丢失或重复处理。

明显的缺点是金丝雀机器上的延迟稍高。如果您绝对不能容忍延迟将生成哪个主题的决定推到上游到生产者?(我不知道这对你有多可行)

变体以防第二个主题不被允许

如果(如上所述)你不能有第二个主题,你仍然可以只在 99% 的机器上做出决定,然后对于需要去金丝雀的记录,用某种方式将它们重新生成到原始分区中“标记”(在有效负载中或作为 kafka 标头,由您决定)。99% 的机器会忽略任何传入的带有标记的记录,而金丝雀机器只会处理带有标记的记录。

同样,主要的缺点是增加了延迟。

于 2020-03-05T17:10:49.070 回答