如何 运行 一个 Kafka 金丝雀消费者

How to run a Kafka Canary Consumer

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

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

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

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

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

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

我看不出有什么方法可以在没有 "ignoring" 或 double-processing 记录的情况下跨 2 台机器更改 "sampling strategy"。由于不同的 Kafka 消费者可能位于分区中的不同位置,并且也可能在不同时间获得新配置,因此您不可避免地会 运行 进入以下两种情况之一:

  1. 两台机器对同一条记录进行双重处理
  2. "Skipping" 一条记录,因为两台机器在看到它时都不认为应该 "own" 它。

我建议对您的体系结构进行一些小改动:

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

现在您有了一个管道设置,其中只在一个点做出决定,没有记录被遗漏或双重处理。

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

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

如果(如上所述)你不能有第二个主题,你仍然可以只在 99% 的机器上做出决定,然后对于需要去金丝雀的记录,re-produce 它们进入带有某种 "marker" 的原始分区(在有效负载中或作为 kafka header,由您决定)。 99% 的机器将忽略任何带有标记的传入记录,而 Canary 机器将 处理带有标记的记录。

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