Apache Kafka是否适合用作无序任务队列?

时间:2016-03-24 17:18:07

标签: architecture message-queue apache-kafka

根据生产者分配的分区,Kafka将传入的消息拆分为分区。来自分区的消息然后被不同消费者组中的消费者使用。

这种架构让我担心使用Kafka作为工作/任务队列,因为我必须在生产时指定分区,这间接限制了哪些消费者可以使用它,因为分区只发送给一个消费者。消费者群体。我宁愿不提前指定分区,因此无论哪个消费者可以接受该任务都可以这样做。有没有办法在Kafka架构中构建分区/生产者,其中任务可以由下一个可用的消费者提取,而不必在生成工作时通过选择分区来提前分工?

对此主题仅使用一个分区会将所有任务放在同一队列中,但每个使用者组的使用者数量限制为1,因此每个使用者必须位于不同的组中。然后,所有任务都分配给每个消费者群体,这不是我正在寻找的那种工作队列。

Apache Kafka是否适合用作任务队列?

5 个答案:

答案 0 :(得分:29)

将Kafka用于任务队列是个坏主意。 使用RabbitMQ,它会做得更好,更优雅。

虽然您可以将Kafka用于任务队列 - 但您会遇到一些问题: Kafka不允许许多消费者使用单个分区(按设计),因此,例如,如果单个分区充满了许多任务,并且拥有该分区的消费者忙,则该分区中的任务将得到"饥饿&#34 ;. 这也意味着主题中任务的消耗顺序与生成任务的顺序不同,如果任务需要按特定顺序使用,可能会导致严重问题(在Kafka中完全实现必须只有一个消费者和一个分区 - 这意味着仅由一个节点进行串行消费。如果您有多个消费者和多个分区,则无法保证主题级别的任务消费顺序。)

事实上 - 卡夫卡主题不是计算机科学方面的队列。队列意味着先入先出 - 这不是您在主题级别中获得的Kafka。

另一个问题是很难动态更改分区数。添加或删除新员工应该是动态的。如果要确保新工作人员在Kakfa中获取任务,则必须将分区编号设置为最大可能的工作人员。这不够优雅。

所以底线 - 改为使用RabbitMQ或其他队列。

说完所有这些 - Samza(通过linkedin)使用kafka作为某种基于流的任务队列: Samza

编辑: 规模考虑因素:我忘了提到Kakfa是一个大数据/大规模工具。如果你的工作率是巨大的,那么尽管我之前写过的东西,卡夫卡可能是你的好选择,因为处理大规模是非常具有挑战性的,卡夫卡非常擅长这样做。如果我们谈论的是较小的规模(比如,每秒最多几次/数百个工作),那么与RabbitMQ相比,Kafka再次是一个糟糕的选择。

答案 1 :(得分:5)

我想说这取决于规模。你在一个单位时间内预计了多少个任务?

您描述的最终目标基本上是Kafka默认工作的方式。 当您生成消息时,默认(最广泛使用)选项是使用随机分区器,它以循环方式选择分区,保持分区均匀使用(因此可以避免指定分区)。
分区的主要目的是并行处理消息,因此您应该以这种方式使用它 分区用于的其他常用“事物”是确保某些消息按照生成它们的顺序消耗(然后指定分区键,使所有此类消息最终都在同一分区中。例如使用{ {1}}关键是确保以这种方式处理所有用户。)

答案 2 :(得分:3)

本主题中有很多讨论围绕工作或任务队列中的任务执行顺序。我会提出这样一种观念,即执行顺序不应该是工作队列的一个特征。

工作队列是一种通过应用可控制数量的工作线程来完成不同任务来控制资源使用的方法。对队列中的任务执行处理顺序意味着您还要对队列中的任务执行完成顺序,这实际上意味着队列中的任务将始终按顺序处理,而下一个任务仅在前一个任务的END之后处理。这实际上意味着您有一个单线程任务队列。

如果执行顺序在某些任务中很重要,那么这些任务应该在完成时将序列中的下一个任务添加到工作队列中。要么是您支持顺序作业类型,要么在处理时实际上按顺序处理一个作业的作业列表。

工作队列实际上不应该对其任何工作进行排序 - 下一个可用的处理器应始终执行下一个任务,而不考虑任务完成之前或之后发生的事情。

我也把kafka视为工作队列的基础,但是我研究的越多,它看起来就像所需的平台就越少。

我认为它主要用作同步不同资源的手段,而不是执行不同工作请求的手段。

我认为在工作队列中重要的另一个领域是支持任务的优先级。例如,如果队列中有20个任务,并且新任务以更高的优先级到达,我希望该任务跳转到下一个可用工作人员接收的行的开头。卡夫卡不允许这样做。

答案 3 :(得分:2)

尝试将Kafka用作消息队列有两个主要障碍:

  1. Ofer's answer中所述,您只能使用单个使用者的单个分区,并且只能在分区内保证处理顺序。因此,如果您无法在分区之间公平地分配任务,那么这可能是一个问题

  2. 默认情况下,您只能确认处理到达给定点(偏移)的所有消息。与传统的消息队列不同,您无法进行选择性确认,如果出现故障,则无法进行选择性重试。这可以通过使用kmq解决,is not partition tolerant在附加主题的帮助下添加单个ack功能(免责声明:我是kmq的作者)。

  3. RabbitMQ当然是一种替代方案,但它也提供了不同(较低)的性能和复制保证。简而言之,RabbitMQ文档声明了经纪人mqperf。另请参阅我们对消息队列与数据复制的比较{{3}}。

答案 4 :(得分:0)

我正在开发一个在 kafka 之上实现作业队列的库,https://github.com/JingIsCoding/kafka-job-queue 我正在使用多个队列来维护准备处理的任务、未来任务和死任务,欢迎贡献