alm*_*mel 57 distributed apache-kafka
我正在学习卡夫卡,在这里阅读介绍部分
https://kafka.apache.org/documentation.html#introduction
特别是有关消费者的部分.在引言的倒数第二段中,它读到了
卡夫卡做得更好.通过在主题中具有并行性概念 - 分区 - ,Kafka能够在消费者流程池中提供订购保证和负载平衡.这是通过将主题中的分区分配给使用者组中的使用者来实现的,以便每个分区仅由该组中的一个使用者使用.通过这样做,我们确保使用者是该分区的唯一读者并按顺序使用数据.由于有许多分区,这仍然可以平衡许多消费者实例的负载.但请注意,除分区之外不能有更多的消费者实例.
我的困惑源于最后一句话,因为在该段落的正上方,作者描绘了两个消费者群体和一个4分区主题,消费者实例多于分区!
没有比分区更多的消费者实例也没有意义,因为那时分区将非常小,并且似乎为每个消费者实例创建新分区的开销会使Kafka陷入困境.我知道分区用于容错并减少任何一台服务器上的负载,但上述句子在分布式系统的环境中没有意义,该分布式系统应该能够一次处理数千个消费者.
pet*_*ter 58
好的,要理解它,需要了解几个部分.
但是,尽管服务器按顺序分发消息,但消息是异步传递给消费者的,因此它们可能会在不同的消费者上无序传送.这实际上意味着在并行消费的情况下消息的排序会丢失.消息传递系统通常通过具有"独占消费者"的概念来解决这个问题,该概念只允许一个进程从队列中消耗,但这当然意味着处理中没有并行性.
卡夫卡做得更好.通过在主题中具有并行性概念 - 分区 - ,Kafka能够在消费者流程池中提供订购保证和负载平衡.这是通过将主题中的分区分配给使用者组中的使用者来实现的,以便每个分区仅由该组中的一个使用者使用.通过这样做,我们确保使用者是该分区的唯一读者并按顺序使用数据.由于有许多分区,这仍然可以平衡许多消费者实例的负载.但请注意,除分区之外不能有更多的消费者实例.
Kafka仅对分区内的消息提供总订单,而不是在主题中的不同分区之间.
您认为性能损失(多个分区)实际上也是性能提升,因为Kafka可以完全并行执行不同分区的操作,同时等待其他分区完成.
最初描述了两种情况:
如果所有使用者实例具有相同的使用者组,那么这就像传统的队列平衡对消费者的负载一样.
如果所有消费者实例具有不同的消费者组,则其工作方式类似于发布 - 订阅,并且所有消息都广播给所有消费者.
因此,您拥有的订阅者组越多,性能就越低,因为kafka需要将消息复制到所有这些组并保证总订单.
另一方面,较少的组,您拥有的分区越多,您从平行消息处理中获得的越多.
小智 11
Kafka消费者组模型是队列机制和发布/订阅机制的混合体,其中消息一旦被一个消费者实例读取,就会立即从队列中删除,而发布/订阅机制则直到设置的保留期或过期并且可供使用时才删除消息。所有消费者实例直到过期。因此,如果您有想要使用发布/订阅模型但希望将其用作排队机制的用例,则可以为所有消费者实例创建消费者组。鉴于 Kafka 在单个消费者组内的消费者实例之间分配分区,可以保证 1 条消息仅处理一次。如果 Kafka 允许您在单个消费者组中拥有更多消费者实例,那么它就违背了拥有消费者组的目的。
考虑这个例子:
REST API pub1 向 topic1 发布了 4 条消息,topic1 有 4 个分区(part1 到 part4),因此每个部分都有 1 条消息。
您有 2 个微服务 sub1 和 sub2 作为订阅者,每个微服务有 4 个实例正在运行。
现在,如果您创建 2 个消费者组,则每个 miroservice 都有一个 sub1instance1 将映射到part1,sub1instance2 将映射到part2,以此类推。类似地,sub2instance1 将映射到part1,sub2instance2 映射到part2 等。
只要每个消费者组中的消费者实例小于或等于分区数量,微服务的每个实例就只会处理消息一次。在这种情况下,sub1instance1和sub2instance将处理来自part1的msg1。
如果消费者实例多于分区,那么 Kafka 将必须将相同的分区分配给多个消费者实例,因此映射到该分区的每个消费者实例将多次处理消息。这就是为什么 Kafka 阻止我们在一个消费者组中拥有比消费者组订阅的主题内的分区数量更多的消费者实例。
希望这是有道理的。
在 Kafka 中,只有一个消费者实例可以消费来自分区的消息。如果消费者实例多于分区,则不会使用额外的消费者实例。所以kafka不允许这些额外的消费者实例。
现在,如果多个消费者可以消费分区,那么消息的消费将不会有任何顺序。这就是kafka不允许每个分区有多个消费者的原因
重要的是要记住,Kafka每个[消费者群体,主题,分区]保留一个偏移量.这就是原因.
我猜这句话
但请注意,除分区之外不能有更多的消费者实例.
指的是"自动消费者群体重新平衡"模式,当您只是订阅()一些消费者的主题列表时,默认的消费者模式.
我假设,因为,至少对于Kafka 0.9.x,没有什么可以防止有几个消费者实例,同一组的成员,从同一个分区读取.
你可以在两个或多个不同的线程中做这样的事情
Properties props = new Properties();
props.put(ConsumerConfig.GROUP_ID_CONFIG, "MyConsumerGroup");
props.put("enable.auto.commit", "false");
consumer = new KafkaConsumer<>(props);
TopicPartition partition0 = new TopicPartition("mytopic", 0);
consumer.assign(Arrays.asList(partition0));
ConsumerRecords<Integer, String> records = consumer.poll(1000);
Run Code Online (Sandbox Code Playgroud)
并且您将有两个(或更多)消费者从同一分区读取.
现在,"问题"是两个消费者将共享相同的偏移,你没有其他选择,因为只有一个组,主题和分区发挥作用.
如果两个消费者同时读取当前偏移量,那么它们将读取相同的值,并且它们都将获得相同的消息.
如果您希望每个使用者阅读不同的消息,您将必须同步它们,因此只有一个消费者可以在时间获取并提交偏移量.
我们这样想,我们知道一个消费者组可以订阅多个主题,对吗?这里,我们还可以假设它订阅的每个主题都有不同的编号。分区,有可能吗?
现在,在这种情况下,没有。实例数等于数量 分区规则不能应用于所有主题,因为每个主题假设有不同的编号。分区,对吧?因此,对于相同的消费者组,对于某些主题,我们将有 i == p,对于某些主题,有 i < p,对于某些主题,有 i > p。
换句话说,理想情况下您至少希望没有。消费者组中的实例数量等于数量。主题中的分区,但如果您最终拥有更多实例,那么它不会失败或造成损害,即对于该主题,额外的实例将保持空闲状态。
例子:
主题 A 有 2 个分区
具有 3 个分区的主题 B
具有 3 个实例的消费者组
A[1 2] B[1 2 3]
[x y z] (consumer group)
Run Code Online (Sandbox Code Playgroud)
现在,对于主题“B”,所有 3 个消费者实例都将处于活动状态(每个从 1 个分区读取),但是,对于主题“A”,只有 3 个消费者实例中的任意 2 个将处于活动状态(即,其中 1 个将作为主题闲置)只有 2 个分区)。
| 归档时间: |
|
| 查看次数: |
37432 次 |
| 最近记录: |