kafka中offset和__consumer_offsets_理解

offset理解

在这里插入图片描述

在kafka的topic中每个分区都是有序且顺序不可变的记录集,并且不断地追加到结构化的log文件。分区中的每一个记录都会分配一个id号来表示顺序,我们称之为offset,offset用来唯一的标识分区中每一条记录
消息在不同的 Partition 是不能保证有序的,只有一个 Partition 内的消息是有序的。

消费者在消费数据时,发生宕机后,再次重新启动后,消费的数据需要从宕机位置开始读取。如果从头读取,有一部分消息一定出现了重复消费,而从宕机时的消费位置读取,就不会出现重复消费,因此kafka设计了offset可以用于处理这种情况。

kafka的broker是无状态的;每次生产消息时,都是往对应partition的文件中追加写入,而消息的被读取状态是由consumer来维护的
所以每个partition中offset一般都是连续递增的(如果开启了压缩,因为对旧数据的merge会导致不连续),被读取的消息并不会删除,所以每次都是追加写入顺序读写,具备很好的吞吐量。

__consumer_offsets理解

在这里插入图片描述
在这里插入图片描述

新版本 Consumer 的offsets管理机制就是将 Consumer 的位移数据作为一条条普通的 Kafka 消息,提交到 __consumer_offsets 中。_consumer_offsets 的主要作用是保存 Kafka 消费者的位移信息。这个提交过程不仅要实现高持久性,还要支持高频的写操作。

当 Kafka 集群中的第一个 Consumer 程序启动时,Kafka 会自动创建offsets主题。offsets主题就是普通的 Kafka topic,它也有对应的分区数。但如果是 Kafka 自动创建的,分区数的设定要看 Broker 端参数
offsets.topic.num.partitions 的取值。它的默认值是 50,因此 Kafka 会自动创建一个 50分区的位移主题。副本数或备份因子是 Broker 端参数 offsets.topic.replication.factor 控制的。默认值是 3。如果 Kafka 日志路径下冒出很多 __consumer_offsets-xxx 这样的目录,这是 Kafka 自动创建的位移主题。

也可以选择手动创建offsets主题,在 Kafka 集群尚未启动 Consumer 之前,使用 Kafka API 创建它。手动创建的好处在于,可以创建满足你实际场景需要的位移主题。比如50 个分区太多了那么可以自己创建它,不用理会 offsets.topic.num.partitions 的值。

Consumer 端有个参数叫 enable.auto.commit,如果值是 true,则 Consumer在后台定期提交位移,提交间隔由参数 auto.commit.interval.ms来控制。自动提交位移的优点就是省事,不用操心位移提交的事情,就能保证消息消费不会丢失。但这一点同时也是缺点,丧失了很大的灵活性和可控性,完全没法把控 Consumer 端的位移管理。
很多与 Kafka 集成的大数据框架都是禁用自动提交位移的,如 Spark、Flink 等。

两种方式维护offset:

  • 自动提交,设置enable.auto.commit=true,更新的频率根据参数【auto.commit.interval.ms】来定。这种方式也被称为【at
    most once】,fetch到消息后就可以更新offset,无论是否消费成功。默认true。
  • 手动提交,设置enable.auto.commit=false,这种方式称为【at least once】。fetch到消息后,等消费完成再调用方法【consumer.commitSync()】,手动更新offset。

consumer在消费消息后,向broker中有个专门维护每个consumer的offset的topic(__consumer_offsets)生产一条消息,记录自己当前已读的消息的offset+1的值作为新的offset的消息。当然在旧版本的实现是在zookeeper上有个节点存放这个offset,当时后面考虑性能问题,kafka改到了topic里,同时可以自由配置使用zookeeper还是使用topic。而在kafka存放topic数据的目录中,存有一个我们创建的test主题的目类(因为没有别的分区,所以是分区0),以及存放__consumer_offsets的50个分区目录。
0.9.0版本以前.这些数值维护在zookeeper中,但是zk不适合大量写入.后来做了改动;
0.9.0 版本以后,数据维护在kafka的_consumer_offsets主题下.
内部结构包括:groupid:topicName_partition offset。

在这里插入图片描述

_consumer_offsets 的每条消息格式:

  • key :group.id+topic+分区号
  • value: offset 的值 一个 kafka 生成环境中可能有很多 consumer 和 consumer group,如果这些 consumer 同时提交位移,则必将加重 _consumer_offsets 的写入负载,因此 kafka 默认为该 topic
    创建了50个分区,并且对每个 group.id 做哈希求模运算,从而将负载分散到不同的 __consumer_offsets
    分区上。Math.abs(groupID.hashCode()) % numPartitions 例如
    “zsl-group”.hashCode()%50=32; 那我们就知道 szz-group消费组的偏移量信息存放在__consumer_offsets_32中;
  • 客户端提交消费位移是使用 OffsetCommitRequest请求实现的;
  • 在处理完消费位移之后,Kafka 返回 OffsetCommitResponse 给客户端
  • Kafka 使用Compact 策略来删除位移主题中的过期消息。对于同一个 Key 的两条消息 M1 和 M2,如果 M1 的发送时间早于 M2,那么 M1 就是过期消息。Compact 的过程就是扫描日志的所有消息,剔除那些过期的消息,然后把剩下的消息整理在一起。

  • Kafka 提供后台线程定期地巡检待 Compact 的主题,看看是否存在满足条件的可删除数据。这个后台线程叫 Log Cleaner。如果位移主题无限膨胀占用过多磁盘空间的问题,可以去检查一下 Log Cleaner线程的状态,通常都是这个线程挂掉了导致的。

在这里插入图片描述

每次consumer消费消息时,kafka都会根据__consumer_offsets下对于该consumer记录的offset,传递对应消息,当offset不存在时,根据auto.offset.reset配置的值,会有几种不同策略:

  • earliest:无指定的offset时,从头开始消费
  • latest:无提交的offset时,消费该分区下最新产生的消息
  • none:topic不存在指定的offset,则抛出异常
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

偷偷学习被我发现

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值