kafka pulsar client 调用 kafka是pull还是push_偏移量

kafka pulsar client 调用 kafka是pull还是push_kafka_02

kafka pulsar client 调用 kafka是pull还是push_偏移量_03

(图片来源于网络,侵删)


这一篇博客对于Consumer的概念做一些归纳整理!

废话不多说,那就开始吧!!!


【1】Consumer消费方式

consumer 采用 pull(拉)模式从 broker 中读取数据
push(推)模式很难适应消费速率不同的消费者,因为消息发送速率是由 broker 决定的
它的目标是尽可能以最快速度传递消息,但是这样很容易造成 consumer 来不及处理消息,
典型的表现就是拒绝服务以及网络拥塞,而 pull 模式则可以根据 consumer 的消费能力以适
当的速率消费消息

pull 模式不足之处是,如果 kafka 没有数据,消费者可能会陷入循环中,一直返回空数
据,针对这一点,Kafka 的消费者在消费数据时会传入一个时长参数 timeout,如果当前没有
数据可供消费,consumer 会等待一段时间之后再返回,这段时长即为 timeout

【2】Kafka消费者offset提交策略

Kafka消费者消费数据后提交offset有自动提交与手动提交两种策略
在创建KafkaConsumer对象时,通过参数enable.auto.commit设定, true表示自动提交(默认)
自动提交策略由消费者协调器(ConsumerCoordinator)每隔${auto.commit.interval.ms} 毫秒执行一次偏移量的提交
手动提交需要由客户端自己控制偏移量的提交

Kafka 提供了异步提交(commitAsync)及同步提交(commitSync)两种手动提交的方式
两者的主要区别在于同步模式下提交失败时一直尝试提交,直到遇到无法重试的情况下才会结束,同时,同步方式下消费者线程在拉取消息时会被阻塞,直到偏移量提交操作成功或者在提交过程中发生错误
而异步方式下消费者线程不会被阻塞,可能在提交偏移量操作的结果还未返回时就开始进行下一次的拉取操作,在提交失败时也不会尝试提交

实现手动提交前需要在创建消费者时关闭自动提交,即设置enable.auto.commit=false。然后在业务处理成功后调用commitAsync()或commitSync()方法手动提交偏移量。由于同步提交会阻塞线程直到提交消费偏移量执行结果返回,而异步提交并不会等消费偏移量提交成功后再继续下一次拉取消息的操作,因此异步提交还提供了一个偏移量提交回调的方法commitAsync(OffsetCommitCallback callback)。当提交偏移量完成后会回调OffsetCommitCallback 接口的onComplete()方法,这样客户端根据回调结果执行不同的逻辑处理


【3】offset

Kafka 0.9 版本之前,consumer 默认将 offset 保存在 Zookeeper 中,从 0.9 版本开始,
consumer 默认将 offset 保存在 Kafka 一个内置的 topic中,该 topic 为__consumer_offset Consumer连接指定的Topic partition所在leader broker,采用pull方式从kafka logs中获取消息,对于不同的消费模式,会将offset保存在不同的地方

查看 offset
1)修改配置文件 consumer.properties

exclude.internal.topics=false

2)读取 offset
0.11.0.0 之前版本:

bin/kafka-console-consumer.sh --topic __consumer_offsets --
zookeeper 主机名:2181 --formatter 
"kafka.coordinator.GroupMetadataManager\$OffsetsMessageFormatter" 
--consumer.config config/consumer.properties --from-beginning

0.11.0.0 之后版本(含):

bin/kafka-console-consumer.sh --topic __consumer_offsets --
zookeeper 主机名:2181 --formatter 
"kafka.coordinator.group.GroupMetadataManager\$OffsetsMessageForm
atter" --consumer.config config/consumer.properties --from-beginning

【4】Topic 和 Consumer Group 、Consumer Group 和 Partition的关系

一个Topic能被多个消费者组消费

一个分区只能被一个消费者组内的一个消费者所消费

同一个消费者组中的消费者对于同一条消息只消费一次

每个消费者都必须属于某个消费者组,每个消费者组内至少有一个消费者

分区数量并不是越多越好,一般 3 - 10 个即可

分区数越多,同一时间可以有越多的消费者来进行消费,消费数据的速度就会越快,提高消费的性能


【5】消费者群组和分区再平衡

一个新的消费者加入群组时,它读取的是原本由其他消费者读取的消息。当一个消费者被关闭或发生奔溃时,它就离开群组,原本由它读取的分区将由群组里的其他消费者来读取,在主题发生变化时, 比如管理员添加了新的分区,这些情况都会发生分区重分配
分区的所有权从一个消费者变成了里另一个消费者,这样的行为被称为再平衡。再平衡非常重要, 它为消费者组带来了高可用性伸缩性(我们可以放心地添加或移除消费者),不过在正常情况下,我们并不希望发生这样的行为。在再均衡期间,broker为了重新分配该Topic的分区,让该Topic在一小段时间内不可读取,因此消费者无法读取该Topic的消息。另外,当分区被重新分配给另一个消费者时,消费者当前的读取状态会丢失,它有可能还需要去刷新缓存,在它重新恢复状态之前会拖慢应用程序

消费者通过向被指派为群组协调器的broker (不同的群组可以有不同的协调器)发送心跳来维持它们和群组的从属关系以及它们对分区的所有权关系。只要消费者以正常的时间间隔发送心跳,就被认为是活跃的,说明它还在读取分区里的消息。消费者会在轮询消息(为了获取消息)或提交偏移量时发送心跳。如果消费者停止发送心跳的时间足够长,会话就会过期,群组协调器认为它已经死亡,就会触发一次再均衡。如果一个消费者发生崩溃,井停止读取消息,群组协调器会等待几秒钟,确认它死亡了才会触发再均衡。在这几秒钟时间里,死掉的消费者不会读取分区里的消息。在清理消费者时,消费者会通知协调器它将要离开群组,协调器会立即触发一次再均衡,尽量降低处理停顿


【6】消费者分区分配规则

RoundRobin strategy(轮询分区):

轮询分区策略是把所有 partition 和所有订阅了该主题的 consumer 线程都列出来,然后按照 hashcode 进行排序,最后通过轮询算法分配 partition 给消费线程。如果所有 consumer 实例的订阅是相同的,那么 partition 会均匀分布

注意:使用轮询分区策略必须满足两个条件
1、每个主题的消费者实例具有相同数量的流
2、每个消费者订阅的主题必须是相同的

什么时候会触发轮询分区策略呢?当出现以下几种情况时,kafka 会进行一次分区分配操作,也就是 kafka consumer 的 rebalance(再均衡)
1、同一个 consumer group 内新增了消费者
2、消费者离开当前所属的 consumer group,比如主动停机或者宕机
3、topic 新增了分区(也就是分区数量发生了变化)
4、消费者主动取消订阅topic

kafka consuemr 的 rebalance 机制规定了一个 consumer group 下的所有 consumer 如何达成一致来分配订阅 topic的每个分区。而具体如何执行分区策略,就是前面提到过的两种内置的分区策略。而 kafka 对于分配策略这块,提供了可插拔的实现方式, 也就是说,除了这两种之外,我们还可以创建自己的分配机制。可以通过继承 AbstractPartitionAssignor抽象类实现 assign来做到

Range strategy(范围分区):

Range 策略是对每个主题而言的,首先对同一个主题里面的分区按照序号进行排序,并对消费者按照字母顺序进行排序,然后将 partitions 的个数除于消费者线程的总数来决定每个消费者线程消费几个分区,如果除不尽,那么前面几个消费者线程将会多消费一个分区


【7】Zookeeper在Kafka中的作用

Kafka基于Controller的Leader Election
原理是在整个集群中选举出一个Broker作为Controller,Controller为所有Topic的所有Partition指定Leader及Follower,Kafka通过在zookeeper上创建/controller临时节点来实现leader选举,并在该节点中写入当前broker的信息 {“version”:1,”brokerid”:1,”timestamp”:”1512018424988”}

利用Zookeeper的强一致性特性,一个节点只能被一个客户端创建成功,创建成功的broker即为leader,即先到先得原则,leader也就是集群中的controller,负责集群中所有大小事务。 当leader和zookeeper失去连接时,临时节点会删除,而其他broker会监听该节点的变化,当节点删除时,其他broker会收到事件通知,重新发起leader选举

这样做极大缓解Herd Effect问题,减轻Zookeeper负载,Controller与Leader及Follower间通过RPC通信,高效且实时,但是由于引入Controller增加了复杂度,同时需要考虑Controller的Failover(容错)

以下为 Partition 的 Leader 选举过程👇

kafka pulsar client 调用 kafka是pull还是push_群组_04

【8】Kafka 事务

Kafka 从 0.11 版本开始引入了事务支持。事务可以保证 Kafka 在 Exactly Once 语义的基础上,生产和消费可以跨分区和会话,要么全部成功,要么全部失败

Producer 事务

为了实现跨分区跨会话的事务,需要引入一个全局唯一的 Transaction ID,并将 Producer
获得的PID 和Transaction ID 绑定。这样当Producer 重启后就可以通过正在进行的 Transaction
ID 获得原来的 PID

为了管理 Transaction,Kafka 引入了一个新的组件 Transaction Coordinator。Producer 就
是通过和 Transaction Coordinator 交互获得 Transaction ID 对应的任务状态。Transaction
Coordinator 还负责将事务所有写入 Kafka 的一个内部 Topic,这样即使整个服务重启,由于
事务状态得到保存,进行中的事务状态可以得到恢复,从而继续进行

Consumer 事务

上述事务机制主要是从 Producer 方面考虑,对于 Consumer 而言,事务的保证就会相对
较弱,尤其是无法保证 Commit 的信息被精确消费。这是由于 Consumer 可以通过 offset 访
问任意信息,而且不同的 Segment File 生命周期不同,同一事务的消息可能会出现重启后被
删除的情况


都看到这里了,点赞评论一下吧!!!

kafka pulsar client 调用 kafka是pull还是push_偏移量_05