根据 生产环境 者分配的分区,Kafka将传入的消息拆分为分区 . 来自分区的消息然后被不同消费者组中的消费者使用 .
这种架构让我担心使用Kafka作为工作/任务队列,因为我必须在 生产环境 时指定分区,这间接限制了哪些消费者可以使用它,因为分区只发送给消费者组中的一个消费者 . 我不希望提前指定分区,因此无论哪个消费者可以接受该任务都可以这样做 . 有没有办法在Kafka架构中构建分区/ 生产环境 者,其中任务可以由下一个可用的消费者提取,而不必在生成工作时通过选择分区来提前分工?
对此主题仅使用一个分区会将所有任务放在同一队列中,但每个使用者组的使用者数量限制为1,因此每个使用者必须位于不同的组中 . 然后,所有任务都分配给每个使用者组,但这不是我正在寻找的那种工作队列 .
Apache Kafka是否适合用作任务队列?
4 回答
本主题中有很多讨论围绕工作或任务队列中的任务执行顺序 . 我会提出这样的概念,即执行顺序不应该是工作队列的一个特征 .
工作队列是通过应用可控制数量的工作线程来完成不同任务来控制资源使用的手段 . 对队列中的任务执行处理顺序意味着您还要对队列中的任务执行完成顺序,这实际上意味着队列中的任务将始终按顺序处理,而下一个任务仅在前一个任务的END之后处理 . 这实际上意味着您拥有单线程任务队列 .
如果执行顺序在某些任务中很重要,那么这些任务应该在完成时将序列中的下一个任务添加到工作队列中 . 要么是支持还是支持顺序作业类型,当处理实际处理类型时,会在一个工作程序上按顺序处理作业列表 .
工作队列实际上不应该对其任何工作进行排序 - 下一个可用的处理器应始终执行下一个任务,而不考虑任务完成之前或之后发生的事情 .
我也把kafka视为工作队列的基础,但是我研究的越多,它看起来就像所需的平台就越少 .
我认为它主要用作同步不同资源的手段,而不是执行不同工作请求的手段 .
我认为在工作队列中重要的另一个领域是支持任务的优先级 . 例如,如果队列中有20个任务,并且新任务以更高的优先级到达,我希望该任务跳转到下一个可用工作人员接收的行的开头 . Kafka 不允许这样做 .
尝试将Kafka用作消息队列有两个主要障碍:
如Ofer's answer中所述
,您只能使用单个使用者的单个分区,并且只能在分区内保证处理顺序 . 因此,如果您无法在分区之间公平地分配任务,则可能会出现问题
默认情况下,您只能确认处理直到给定点(偏移)的所有消息 . 与传统的消息队列不同,您无法进行选择性确认,如果出现故障,则无法进行选择性重试 . 这可以通过使用kmq来解决,它在附加主题的帮助下添加了单独的ack功能(免责声明:我是kmq的作者) .
RabbitMQ当然是一种替代方案,但它也提供了不同(较低)的性能和复制保证 . 简而言之,RabbitMQ文档说明了经纪人is not partition tolerant . 另请参阅我们对消息队列与数据复制的比较,mqperf .
我会说这取决于规模 . 您在一个单位时间内预计了多少项任务?
您描述的最终目标基本上是Kafka默认工作的方式 . 当您生成消息时,默认(最广泛使用)选项是使用随机分区程序,它以循环方式选择分区,保持分区均匀使用(因此可以避免指定分区) .
分区的主要目的是并行处理消息,因此您应该以这种方式使用它 .
其他常用的"thing"分区用于确保某些消息的生成顺序与它们生成的顺序相同(然后您指定分区键,使所有此类消息最终都在同一分区中 . 例如,使用
userId
作为密钥将确保以这种方式处理所有用户) .使用Kafka作为任务队列是一个坏主意 . 使用RabbitMQ,它做得更好,更优雅 .
虽然你可以使用Kafka对于任务队列 - 你会遇到一些问题:Kafka不允许许多消费者使用单个分区(按设计),所以如果例如一个分区充满了许多任务并且拥有该分区的消费者很忙,该分区中的任务将变为“饥饿” . 这也意味着主题中任务的消费顺序与生成任务的顺序不同,如果任务需要按特定顺序消耗,可能会导致严重问题(在Kafka中完全实现必须只有一个消费者和一个分区 - 这意味着只有一个节点的串行消费 . 如果你有多个消费者和多个分区,主题级别的任务消费顺序将无法保证 .
事实上 - Kafka 主题不是计算机科学方面的队列 . 队列意味着先入先出 - 这不是您在主题级别中获得的Kafka .
另一个问题是很难动态更改分区数 . 添加或删除新员工应该是动态的 . 如果要确保新工作人员在Kakfa中获取任务,则必须将分区编号设置为最大可能的工作人员 . 这不够优雅 .
所以底线 - 改为使用RabbitMQ或其他队列 .
说完所有这些 - Samza(通过linkedin)使用kafka作为某种基于流的任务队列:Samza