卡夫卡(Kafka)的许多小队列 - 如何保持扩大负载平衡



我正在使用KAFKA构建消息分配系统。它将每秒处理数以万计的事件(所有统一结构(,并将拥有数千个可能的接收者。消息将到达系统,在Kafka中排队,然后将其派往收件人。要求是:

  • 必须保留特定收件人的消息顺序,不可接受消息丢失。
  • 每个收件人到达的消息的速率以及每个收件人处理消息的速率可能会大不相同,并且收件人可能会有很长的降低时间(例如一周(,因此每个收件人都需要自己的队列以进步(或失速(自己的费率。
  • 停滞的接收者不应影响任何其他收件人的消息流,也不应伤害吞吐量。
  • 可以在运行时的任何时间添加新收件人,并且系统应在合理的时间内开始向新收件人发送消息(但不必立即(。
  • 消耗和处理来自Kafka并将其分配给各种收件人的消息的应用程序应能够扩展到多个节点。每个实例都应处理工作的一部分,无论是由消息处理能力,收件人计数还是其他方式划分,它不必完全平衡,但通常在运行时可以扩展,没有停机时间,并恢复来自节点失败。

是Kafka的新手,我不确定如何建模。首先,我在考虑每个收件人的主题,每个主题有一个分区。我知道Kafka 2.0可以支持无限数量的主题,因此这不是问题。

  • 您可以使用模式来订阅多个主题,这些主题会自动定期刷新。因此,任何新的收件人(拥有自己的主题(都会自动开始消耗。
  • 但是,什么机制将分开应用节点之间的主题?必须保留处理顺序,以便每个主题只能由一个节点来处理。
  • 当应用程序节点出现时,如何知道它应该消耗的主题?当节点下降时,其主题将如何分布到其他节点?

这听起来像消费者群体的机制。因此,我正在研究每个收件人的一个分区。在卡夫卡(Kafka(,每个分区都是它自己的队列可以按照自己的速度进行,并且分区被移出并自动在消费者群体中分配,这就是我所需要的!但是分区的问题在于,它们是一种数据流的负载平衡机制,因此它们有一些限制。

  • 分区并非完全动态。每个接收者都有分区意味着每次将新收件人添加到系统中时添加分区。这将触发重新平衡,并且似乎以不适当的方式将功能性和非功能性问题混为一谈,将业务实体与基础架构配置耦合。
  • 分区编号,那么如何以1比1的方式将收件人名称(字符串(映射到分区编号?我想我可以使用序列发生器来编号收件人,但这感觉就像是错误的解决方案。如果我需要删除收件人,那将在编号中留下一个洞。我不希望有多个收件人映射到同一分区的可能性,因为一个接收者的摊位会影响其他分区。
  • 我应该预先分配分区以防止重新平衡吗?如果我有5000名接收者,并且预计该数量将增加,我应该定义20,000个分区,而其中75%的分区仍未使用?这将阻止每次添加接收者时都会重新平衡,但感觉就像是黑客。

我应该如何使用kafka解决这个排队问题?也许Kafka不是工作的正确工具?

我认为Kafka不适合此类用例。它不是为大量的队列和下游消费者而设计的。它还依赖于基于时间的保留,这在漫长的消费者的降低时间内表现不佳。

我建议您研究Cadence Workflow以实现您的应用程序。

Cadence比使用队列进行任务处理提供了许多其他优点。

  • 动态创建的任务队列。队列的数量是无限的。
  • 建立了指数级的回程,以无限的到期间隔
  • 失败处理。例如,它允许执行一个任务,该任务如果两个更新在配置的间隔内都无法成功。
  • 支持长期运行的心跳操作
  • 能够实施复杂的任务依赖性。例如,在发生无恢复失败(SAGA(
  • 的情况下,实施链接或补偿逻辑的链接
  • 对更新的当前状态提供了完整的可见性。例如,当使用队列时,您知道队列中是否有一些消息,并且需要其他DB来跟踪整体进度。记录每个事件的节奏。
  • 能够取消航班更新的能力。

请参阅节奏编程模型的演示文稿。

最新更新