Apache kafka 如果卡夫卡消费者订阅多个主题,则接收消息的顺序

Apache kafka 如果卡夫卡消费者订阅多个主题,则接收消息的顺序,apache-kafka,kafka-consumer-api,Apache Kafka,Kafka Consumer Api,我有一个消费者,他可以调查多个主题。对于这个问题,我限制了每个主题一个分区。假设消费者开始轮询时,每个主题都有一些数据。 阅读的顺序是什么 是循环赛吗?它是从第一个读到下一个吗?我使用consumer.poll(N)进行轮询。没有排序,因为底层协议允许在一个请求中发送多个分区的请求 当您调用consumer.poll(N)时,客户机实际上会将FetchRequest对象发送给托管分区领导者的代理(请参见org.apache.kafka.clients.consumer.internal.Fetc

我有一个消费者,他可以调查多个主题。对于这个问题,我限制了每个主题一个分区。假设消费者开始轮询时,每个主题都有一些数据。 阅读的顺序是什么


是循环赛吗?它是从第一个读到下一个吗?我使用consumer.poll(N)进行轮询。

没有排序,因为底层协议允许在一个请求中发送多个分区的请求

当您调用
consumer.poll(N)
时,客户机实际上会将
FetchRequest
对象发送给托管分区领导者的代理(请参见
org.apache.kafka.clients.consumer.internal.Fetcher.createFetchRequests()
)——并且每个节点只有一个请求,而不是每个分区


重要的是,客户端可以为多个分区发送一个FetchRequest(请参阅)。

排序相当复杂。以下是卡夫卡2.6的工作原理:

  • 当您将主题分区分配给使用者时,这些分区将保存在哈希表中,因此顺序是稳定的,但不一定是您使用的顺序
  • 调用
    Consumer.poll(N)
    时,它返回所有排队的消息,但最多返回
    max.poll.records
    (见下文)
  • 当没有任何内容排队时,您分配的所有主题分区都将按Kafka节点(该主题分区的前导节点所在)进行分区
  • 在获取请求中,这些列表中的每一个都被发送到各个节点
  • 每个节点将返回最多
    fetch.max.bytes
    (或至少一条消息,如果可用)
  • 节点将用来自请求分区的消息填充这些字节,始终从第一个开始
  • 如果当前分区中没有剩余的消息,但仍有字节需要填充,它将移动到下一个分区,直到没有更多消息或缓冲区已满
  • 节点还可以决定停止使用当前分区并继续使用下一个分区,即使当前分区中仍然有可用的消息
  • 客户端/使用者收到缓冲区后,会将其拆分为
    CompletedFetches
    ,其中一个
    CompletedFetch
    正好包含缓冲区中一个主题分区的所有消息
  • 那些
    CompletedFetches
    已排队(它们可能包含0条或1000条或更多消息)。每个请求的主题分区将有一个
    CompletedFetch
  • 由于对节点的所有请求都是并行运行的,但只有一个队列,因此与原始分配顺序相反,
    CompletedFetches
    /topic分区可能会在最终结果中混淆
  • 排队的
    CompletedFetches
    在逻辑上扁平化为一个大队列
  • Consumer.poll(N)
    将从扁平的大队列中读取最多
    max.poll.records
  • 在将记录返回给
    poll
    的调用者之前,将启动对所有节点的另一个获取请求,但这一次,已在平坦队列中的所有主题分区都将被排除
  • 这适用于所有未来的
    轮询
    调用
实际上,这意味着你不会挨饿,但在你收到下一个主题的大量消息之前,你可能会收到一个主题的大量消息

在消息大小为10字节的测试中,从一个主题中读取的消息约为58000条,而从下一个主题中读取的消息量大致相同。 所有主题都预先填充了100万条消息


因此,您将有一种批处理循环。

在给定的主题分区内是线性的,但我认为每个轮询循环将循环到其他主题。。。当然,您可以通过打印记录元数据来轻松测试这一点?是的,这是第一次。大约第二天-是的,我可以这样做,但那可能是间接的。卡夫卡规范是否说在任何地方(找不到它)?我找不到类似的东西,不。如果不在更大数量的消息上进行测试,将很难找到关于它的任何东西。常识可能会说这是一种循环/随机的方式,否则hiper活动主题会将消费者视为自己,它永远不会阅读来自其他主题的消息。