使KafKa每次读取消息到最新发送消息的解决方案(使用版本0.10.1.1)
情景是使KafKa每次读取消息到最新发送消息,查了很多资料,对kafka的消费组和偏移量也有些研究,但本地与集群,不同版本都有不少不同之处。即使目前解决了该问题,仍有不少坑待填(之前想在这边放下关于消费组和偏移量的东西,但比较多比较杂,就开了一个新坑:https://blog.csdn.net/jyj1100/article/details/81068245)
第一个方案:去掉偏移量
考虑直接去掉偏移量,但清空偏移量想要reset一个group的offset,但没找到相应的操作的方法。于是就考虑是在创建group的时候就使Brokers不要记录它的offset:
在代码里实现是设置参数enable_auto_commit=false
。
但在程序中使用就有问题,创建和提交时自动监测,程序没有偏移量就会报错。
第二个方案:通过不断新增group,使每个group获取最新偏移量
因为没法去掉偏移量,准备通过不断新增groupid,使每个group获取最新偏移量。
代码实现方法是在groupid后加时间戳,代码每次启动使用新的group。此时初始偏移量offset的配置为kafka.auto.offset.reset=latest,可以做到每次都只读最新数据。
但不断新建,topic下的group迅速增加,偏移量___consumer_offsets 多次保存。且没找到有效在topic下删除group_id的方法,也没办法做到定期清理,会对性能产生影响。
第三个方案,采用 simple consumer api
就是调用官方提供的api,但这个api是简单消费者api,具体讲解在前面的链接里。
在代码里就是seekTond
方法(需要注意的是,如果你是初始化KafkaConsumer
的时候指定的topic(high-level consumer 的 api),即使用subscribe
方法,然后执行seekTond
方法会报错。这是没有指定分区而自动分区,同后面提交分区冲突。
必须在初始化之后调用assign()
方法来指定抓哪个topic的哪个partition里的数据,然后再调用seekTond
方法)。示例代码如下:
List<TopicPartition> topicPartitionList= new ArrayList<>();
topicPartitionList.add(new TopicPartition(this.consumer_kafka_topic,0));
this.consumer.assign(topicPartitionList);
this.consumer.seekToEnd(topicPartitionList);
因为当前集群指定分区编号为零。且仅有一个分区,所以可以较好的满足需求,实现目标。但对于需要多个分区的问题,这方面的设置就会比较复杂。
记录些问题
1.___consumer_offsets的产生速度很快,在集群其他topic没有接入数据时,仍不断刷新消费者的偏移量,从不间断。如此高频次的记录是为了什么?
2.Kafka权威指南 有一句话:如果消费者发生崩溃或者有新的消费者加入群组,就会触发再均衡,完成再均衡之后,每个消费者可能分配到新的分区... 消费者加入,再均衡,分区 三者之间的关系是什么。
更新7.16(没错,就是发布当天)
刚看了篇官方文档,应该是给出了一个新的配置,不过还没去尝试。有兴趣的可以去看看。https://cwiki.apache.org/confluence/display/KAFKA/KIP-171+-+Extend+Consumer+Group+Reset+Offset+for+Stream+Application
更新7.23
重新修改了叙述的问题(还好没被很多人看到)。提出一个当初忽略的问题:
3.如何删除topic下的group_id,(之前版本group_id都是放在zookeeper下的,操作比较简单),现在(0.10.1.1)放在boorker中,不知道如何操作,删除。