解惑 | 为什么我根据时间戳获得的offset为空呢?

本文探讨了使用kafka.tools.GetOffsetShell命令根据时间戳获取offset时遇到的问题,解释了这与Kafka的日志段(log segments)机制有关。作者指出,该命令只能匹配大概的offset,无法精确对应。为了解决这个问题,文章介绍了如何使用Kafka的Java API封装一个工具脚本来获取时间戳对应的精准offset,并提供了相关代码示例。

点击上方蓝色“大数据实战演练”,选择“设为星标”或“置顶”

回复“资源”领取独家整理的学习资料!

每一个成功人士的背后,必定曾经做出过勇敢而又孤独的决定。

放弃不难,但坚持很酷~

kafka_2.11-1.1.0

一、前言

最近有一个需求,要查询某一时间戳对应的offset值,于是就想到了使用 ./bin/kafka-run-class.sh kafka.tools.GetOffsetShell --time <timestamp> ,但是我在测试的时候,发现有的时间戳会获取不到offset,是空。但是明明指定的时间戳有上报数据,肯定有对应的 offset 的。于是就谷歌,找到了这篇帖子:

https://stackoverflow.com/questions/30030393/strange-behavior-of-kafka-tool-kafka-tools-getoffsetshell

其中已经有大佬给出了答案,但是我还是不求甚解,但起码知道了和 kafka log segments 有关系。

经过研究实践,明白了其中缘由,所以就有了这篇文章。

二、解惑

./bin/kafka-run-class.sh kafka.tools.GetOffsetShell --broker-list message-1:9092 -topic test --time 后面的参数可以是 -1、-2、时间戳,其中 -1 会输出最新的 offset ;-2 会输出未过期最小的 offset ;时间戳这里具有迷惑性,它不能根据时间戳获取到精准匹配的 offset 。

Kafka 将数据存储在 “log segments” 里面,log segments 文件的大小受 log.segment.bytes 影响,默认为 1073741824 字节,也就是 1G 。当数据文件累积到 log.segment.bytes 的值以后,就会创建出新的日志文件,文件名称以分段时的那个 offset 命名,如下图所示:

每一个 xxx.log 文件都算作一个 segment,kafka.tools.GetOffsetShell --time 参数匹配的是 xxx.log 文件本身最后的修改时间,而不是偏移量本身的时间戳。

根据上面图片,举几个例子:

  • 当 time 为 2020-09-16 11:59:20 时,获取的 offset 值为空。

  • 当 time 大于等于 2020-09-16 12:00:20 并且 time 小于 2020-09-16 14:09:24 时,获取的 offset 值为 0,匹配的是 xxx.log 文件名称的那个 offset 。

  • 当 time 大于等于 2020-09-16 14:09:24 时,获取的 offset 值为 1049942,匹配的是 xxx.log 文件名称的那个 offset 。

  • 当 time 远大于 2020-09-16 14:09:24 时,获取的 offset 值为最新的 offset 值。

根据以上实践结果得知,一组时间戳均对应着同一个 offset 。所以这个命令 --time <timestamp> 只能匹配个大概的 offset 而已,无法精确。如果精确,可以调用 java api 来封装成接口或工具使用。

三、调用 kafka java api 获取时间戳对应的 offset,并封装成工具脚本

很纳闷,为什么官方不提供获取时间戳对应的精准的 offset 呢?既然官网没有,那我就用 java api 封装一个工具脚本吧。

先展示下效果:

./bin/getoffsetts --broker-list message-1:9092 --topic hiacloud-ts-v3 --time 1600222353353

脚本选项:

其实上面的 getoffsetts 脚本是执行的一个 java 类,java main() 方法。利用了 JCommander 。JCommander 是一个用于解析命令行参数的 Java 框架,利用 @Parameter 来接收命令参数。

在 main() 函数里面,创建 JCommander 对象,将 args 加载进去,

然后使用 consumer.offsetsForTimes(MaptimestampsToSearch) 来通过时间戳获取各分区对应的 offset 。

具体的代码已经上传到了 

https://github.com/841809077/spring-boot-model/blob/master/src/main/java/com/example/main/OffsetTimestamp.java 

可以直接粘贴到自己的项目中使用这个类查询 offset 。

这个项目算是一个快速可复用项目,支持自定义打包、统一异常处理等,感兴趣的可以下载下来看看。

欢迎大家留言讨论

???? ???? ????

往期推荐

两种实现方式 | 如何查看消费者组的消费情况

Kafka消费者 之 指定位移消费

Kafka消费者 之 如何订阅主题或分区

Kafka消费者 之 如何进行消息消费

Kafka消费者 之 如何提交消息的偏移量

Kafka基础(二):生产者相关知识汇总

Kafka基础(一):基本概念及生产者、消费者示例

扫一扫,我们的故事就开始了。

如果这篇文章对你有所启发,点赞、转发都是一种支持!

让我知道你在看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

create17

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

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

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

打赏作者

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

抵扣说明:

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

余额充值