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

mor*_*der 45 architecture message-queue apache-kafka

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

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

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

Apache Kafka适合用作任务队列吗?

Ofe*_*saf 37

使用Kafka作为任务队列是个坏主意.使用RabbitMQ代替它,它做得更好,更优雅.

虽然您可以将Kafka用于任务队列 - 但是您会遇到一些问题:Kafka不允许许多消费者(按设计)使用单个分区,因此,例如,如果单个分区被许多任务填充,那么拥有者分区繁忙,该分区中的任务将变为"饥饿".这也意味着主题中任务的消耗顺序与生成任务的顺序不同,如果任务需要按特定顺序使用,可能会导致严重问题(在Kafka中完全实现必须只有一个消费者和一个分区 - 这意味着仅由一个节点串行消费如果有多个消费者和多个分区任务的消费不会在话题层面得到保证的顺序).

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

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

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

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

编辑:规模考虑因素:我忘了提及Kakfa是一个大数据/大规模工具.如果你的工作率是巨大的,那么尽管我之前写过的东西,卡夫卡可能是你的好选择,因为处理大规模是非常具有挑战性的,卡夫卡非常擅长这样做.如果我们谈论的是更小尺度(比如说,高达几dosens /每秒数百职位)然后再次卡夫卡相比的RabbitMQ一个糟糕的选择.

  • "在卡夫卡完全实现你必须只有一个消费者和一个分区"是不正确的.根据分区键保证主题中每个分区的顺序.因此,如果订单很重要,您需要按照哪个订单的值进行分区.这实际上是比rabbitmq更强的订购保证,而rabbitmq可能只有一个消费者来保证订购. (6认同)
  • 每个分区一个消费者,而不是每个主题.问题也在于rabbitmq.如果希望按保证顺序处理消息,则该队列只能有一个使用者.您无法按顺序处理并行处理工作. (6认同)
  • 可能还值得一提的是,快速提交偏移变得复杂,以处理需要重试的失败任务. (4认同)
  • 如果您以任何有意义的方式拥有多个消费者,则无法保证订单.如果一个消费者失败并且任务被重新排队怎么办?如果消费者A在消费者B之前完成任务,即使他们以相反的顺序收到任务,该怎么办?Kafka有铁包装订单保证.绝大多数消息队列都没有,包括rabbit mq,除非你有一个生产者和一个消费者. (3认同)
  • Kafka 的主要优势在于流式传输大量数据。如果你没有流式传输大量数据 - Kafka 可能是一个糟糕的选择 (2认同)
  • "对于版本2.7.0及更高版本,如果队列有多个订阅者,个别消费者仍然可以无序地观察消息.这是由于其他订阅者可能会重新排队消息的行为.从队列的角度来看消息始终保持在出版顺序中." https://www.rabbitmq.com/semantics.html (2认同)

Rod*_*ati 8

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

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

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

工作队列绝不应该实际对其任何工作进行排序——下一个可用的处理器应该始终执行下一个任务,而不管任务完成之前或之后发生了什么。

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

我认为它主要用作同步不同资源的一种方式,而不是作为执行不同作业请求的一种方式。

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


ada*_*amw 6

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

  1. 正如Ofer 的回答中所述,您只能从单个消费者消费单个分区,并且仅在分区内保证处理顺序。因此,如果您无法在分区之间公平分配任务,这可能是一个问题

  2. 默认情况下,您只能确认对给定点(偏移量)之前的所有消息的处理。与传统消息队列不同,您无法进行选择性确认,并且在失败时无法进行选择性重试。这可以通过使用kmq来解决,它在附加主题的帮助下添加了单独的 ack 功能(免责声明:我是 kmq 的作者)。

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


Mar*_*aci 5

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

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

  • 感谢Marko的回答,也许我们可以通过一个例子来了解这个问题.所以说我们有20个分区和2个工作,并且有100个新工作进入.通过循环,作业消息被分配到每个分区5,然后每个消费者获得10个分区,即50个作业.假设一个消费者的50个工作需要100毫秒(所有这些工作合计),但另一个消费者的50个工作需要2分钟.提前完成的消费者是否能够帮助超负荷的消费者?卡夫卡是否对同等的工作困难做出了某种假设? (2认同)