kafka的auto.offset.reset详解与测试
1. 取值及定义
auto.offset.reset有以下三个可选值:
- latest (默认)
- earliest
- none
三者均有共同定义:
对于同一个消费者组,若已有提交的offset,则从提交的offset开始接着消费
意思就是,只要这个消费者组消费过了,不管
auto.offset.reset
指定成什么值,效果都一样,每次启动都是已有的最新的offset开始接着往后消费
不同的点为:
- latest(默认):对于同一个消费者组,若没有提交过offset,则只消费
消费者连接topic后,新产生的数据
就是说如果这个topic有历史消息,现在新启动了一个消费者组,且
auto.offset.reset=latest
,此时已存在的历史消息无法消费到,那保持消费者组运行,如果此时topic有新消息进来了,这时新消息才会被消费到。而一旦有消费,则必然会提交offset
这时候如果该消费者组
意外下线了,topic仍然有消息进来,接着该消费者组
在后面恢复上线了,它仍然可以从下线时的offset处开始接着消费,此时走的就是共同定义
- earliest:对于同一个消费者组,若没有提交过offset,则从头开始消费
就是说如果这个topic有历史消息存在,现在新启动了一个消费者组,且
auto.offset.reset=earliest
,那将会从头开始消费,这就是与latest
不同之处。
一旦该消费者组
消费过topic后,此时就有该消费者组
的offset了,这种情况下即使指定了auto.offset.reset=earliest
,再重新启动该消费者组
,效果是与latest
一样的,也就是此时走的是共同的定义
- none:对于同一个消费者组,若没有提交过offset,会抛异常
一般生产环境基本用不到该参数
2. 新建全新topic
./kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --topic TestOffsetResetTopic --partitions 1 --replication-factor 1 --create
3. 往新建的topic发送消息
便于测试,用Java代码发送5
条消息
public class TestProducer {
public static void main(String[] args) throws InterruptedException {
Properties properties = new Properties();
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.123.124:9092");
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
KafkaProducer<String, String> producer = new KafkaProducer<>(properties);
String topic = "TestOffsetResetTopic";
for (int i = 0; i < 5; i++) {
String value = "message_" + i + "_" + LocalDateTime.now();
System.out.println("Send value: " + value);
producer.send(new ProducerRecord<>(topic, value), (metadata, exception) -> {
if (exception == null) {
String str = MessageFormat.format("Send success! topic: {0}, partition: {1}, offset: {2}", metadata.topic(), metadata.partition(), metadata.offset());
System.out.println(str);
}
});
Thread.sleep(500);
}
producer.close();
}
}
发送消息成功:
Send value: message_0_2022-09-16T18:26:15.943749600
Send success! topic: TestOffsetResetTopic, partition: 0, offset: 0
Send value: message_1_2022-09-16T18:26:17.066608900
Send success! topic: TestOffsetResetTopic, partition: 0, offset: 1
Send value: message_2_2022-09-16T18:26:17.568667200
Send success! topic: TestOffsetResetTopic, partition: 0, offset: 2
Send value: message_3_2022-09-16T18:26:18.069093600
Send success! topic: TestOffsetResetTopic, partition: 0, offset: 3
Send value: message_4_2022-09-16T18:26:18.583288100
Send success! topic: TestOffsetResetTopic, partition: 0, offset: 4
现在TestOffsetResetTopic
这个topic有5条消息,且还没有任何消费者组对其进行消费过,也就是没有任何offset
4. 测试latest
已知topic已经存在5条历史消息,此时启动一个消费者
public class TestConsumerLatest {
public static void main(String[] args) {
Properties properties = new Properties();
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.123.124:9092");
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
// 指定消费者组
properties.put(ConsumerConfig.GROUP_ID_CONFIG, "group1");
// 设置 auto.offset.reset
properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest");
String topic = "TestOffsetResetTopic";
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(properties);
consumer.subscribe(Collections.singletonList(topic));
// 消费数据
while (true) {
ConsumerRecords<String, String> consumerRecords = consumer.poll(Duration.ofSeconds(1));
for (ConsumerRecord<String, String> consumerRecord : consumerRecords) {
System.out.println(consumerRecord);
}
}
}
}
发现如上面所述,历史已存在的5条消息不会消费到,消费者没有任何动静,现在保持消费者在线
启动TestProducer
再发5条消息,会发现这后面新发的,offset
从5
开始的消息就被消费了
ConsumerRecord(topic = TestOffsetResetTopic, partition = 0, leaderEpoch = 0, offset = 5, CreateTime = 1663329725731, serialized key size = -1, serialized value size = 39, headers = RecordHeaders(headers = [], isReadOnly = false), key = null, value = message_0_2022-09-16T20:02:05.523581500)
ConsumerRecord(topic = TestOffsetResetTopic, partition = 0, leaderEpoch = 0, offset = 6, CreateTime = 1663329726251, serialized key size = -1, serialized value size = 39, headers = RecordHeaders(headers = [], isReadOnly = false), key = null, value = message_1_2022-09-16T20:02:06.251399400)
ConsumerRecord(topic = TestOffsetResetTopic, partition = 0, leaderEpoch = 0, offset = 7, CreateTime = 1663329726764, serialized key size = -1, serialized value size = 39, headers = RecordHeaders(headers = [], isReadOnly = false), key = null, value = message_2_2022-09-16T20:02:06.764186200)
ConsumerRecord(topic = TestOffsetResetTopic, partition = 0, leaderEpoch = 0, offset = 8, CreateTime = 1663329727264, serialized key size = -1, serialized value size = 39, headers = RecordHeaders(headers = [], isReadOnly = false), key = null, value = message_3_2022-09-16T20:02:07.264268500)
ConsumerRecord(topic = TestOffsetResetTopic, partition = 0, leaderEpoch = 0, offset = 9, CreateTime = 1663329727778, serialized key size = -1, serialized value size = 39, headers = RecordHeaders(headers = [], isReadOnly = false), key = null, value = message_4_2022-09-16T20:02:07.778469700)
此时该消费者组对于这个topic的offset
已经为9
了,现在停掉这个消费者(下线),再启动TestProducer
发5条消息,接着再启动TestConsumerLatest
,会发现紧接上一次的offset之后开始,即从10
继续消费
如果测试发现没动静,请多等一会,估计机器性能太差...
5. 测试earliest
新建一个测试消费者,设置auto.offset.reset
为earliest
,注意groupid
为新的group2
,表示对于topic来说是全新的消费者组
public class TestConsumerEarliest {
public static void main(String[] args) {
Properties properties = new Properties();
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.123.124:9092");
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
// 指定消费者组
properties.put(ConsumerConfig.GROUP_ID_CONFIG, "group2");
// 设置 auto.offset.reset
properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
String topic = "TestOffsetResetTopic";
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(properties);
consumer.subscribe(Collections.singletonList(topic));
// 消费数据
while (true) {
ConsumerRecords<String, String> consumerRecords = consumer.poll(Duration.ofSeconds(1));
for (ConsumerRecord<String, String> consumerRecord : consumerRecords) {
System.out.println(consumerRecord);
}
}
}
}
一运行发现已有的10条消息(最开始5条加上面一次测试又发了5条,一共10条)是可以被消费到的,且消费完后,对于这个topic就已经有了group2
这个组的offset
了,无论之后启停,只要groupid
不变,都会从最新的offset
往后开始消费
6. 测试none
新建一个测试消费者,设置auto.offset.reset
为none
,注意groupid
为新的group3
,表示对于topic来说是全新的消费者组
public class TestConsumerNone {
public static void main(String[] args) {
Properties properties = new Properties();
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.123.124:9092");
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
// 指定消费者组
properties.put(ConsumerConfig.GROUP_ID_CONFIG, "group3");
// 设置 auto.offset.reset
properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "none");
String topic = "TestOffsetResetTopic";
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(properties);
consumer.subscribe(Collections.singletonList(topic));
// 消费数据
while (true) {
ConsumerRecords<String, String> consumerRecords = consumer.poll(Duration.ofSeconds(1));
for (ConsumerRecord<String, String> consumerRecord : consumerRecords) {
System.out.println(consumerRecord);
}
}
}
}
一运行,程序报错,因为对于topic来说是全新的消费者组,且又指定了auto.offset.reset
为none
,直接抛异常,程序退出
Exception in thread "main" org.apache.kafka.clients.consumer.NoOffsetForPartitionException: Undefined offset with no reset policy for partitions: [TestOffsetResetTopic-0]
at org.apache.kafka.clients.consumer.internals.SubscriptionState.resetInitializingPositions(SubscriptionState.java:706)
at org.apache.kafka.clients.consumer.KafkaConsumer.updateFetchPositions(KafkaConsumer.java:2434)
at org.apache.kafka.clients.consumer.KafkaConsumer.updateAssignmentMetadataIfNeeded(KafkaConsumer.java:1266)
at org.apache.kafka.clients.consumer.KafkaConsumer.poll(KafkaConsumer.java:1231)
at org.apache.kafka.clients.consumer.KafkaConsumer.poll(KafkaConsumer.java:1211)
at kakfa.TestConsumerNone.main(TestConsumerNone.java:31)
7. 总结
- 如果
topic
已经有历史消息了,又需要消费这些历史消息,则必须要指定一个从未消费过的消费者组
,同时指定auto.offset.reset
为earliest
,才可以消费到历史数据,之后就有提交offset
。有了offset
,无论是earliest
还是latest
,效果都是一样的了。 - 如果
topic
没有历史消息,或者不需要处理历史消息,那按照默认latest
即可。
kafka的auto.offset.reset详解与测试的更多相关文章
- kafka之consumer参数auto.offset.reset 0.10+
https://blog.csdn.net/dingding_ting/article/details/84862776 https://blog.csdn.net/xianpanjia4616/ar ...
- Kafka auto.offset.reset
要从头消费kafka的数据,可以通过以下参数: Kafka auto.offset.reset = earliest
- kafka auto.offset.reset参数解析
kafka auto.offset.reset参数解析 1.latest和earliest区别 2.创建topic 3.生产数据和接收生产数据 4.测试代码 auto.offset.reset关乎ka ...
- Kafka单线程Consumer及参数详解
请使用0.9以后的版本: 示例代码 Properties props = new Properties(); props.put("bootstrap.servers", &quo ...
- 基于Confluent.Kafka实现的Kafka客户端操作类使用详解
一.引言 有段时间没有写东西了,当然不是没得写,还有MongoDB的系列没有写完呢,那个系列还要继续.今天正好是周末,有点时间,来写新东西吧.最近公司用了Kafka做为消息的中间件,最开始写的那个版本 ...
- kafka_2.11-0.10.2.1中的auto.offset.reset
在使用spark连接kafka消费topic时,发现无论怎么设置,也无法从头开始消费. 查看配置得出auto.offset.reset的以下3种设置及含义: earliest 当各分区下有已提交的of ...
- linux下getsockopt和setsockopt详解及测试
linux下getsockopt和setsockopt详解及测试 NAME 名字 getsockopt, setsockopt - get and set options on sockets 获取或 ...
- 【Kafka】Kafka-配置参数详解-参数调优
Kafka-配置参数详解-参数调优 kafka 目录_百度搜索 为什么kafka使用磁盘而不是内存 - CSDN博客 Kafka 配置说明 - 風吹云动 - 博客园 kafka生产服务器配置 - Or ...
- TextCNN 代码详解(附测试数据集以及GitHub 地址)
前言:本篇是TextCNN系列的第三篇,分享TextCNN的优化经验 前两篇可见: 文本分类算法TextCNN原理详解(一) 一.textCNN 整体框架 1. 模型架构 图一:textCNN 模型结 ...
随机推荐
- Python:27行代码实现将多个Excel表格内容批量汇总合并到一个表格
序言 (https://jq.qq.com/?_wv=1027&k=GmeRhIX0) 老板最近越来越过分了,快下班了发给我几百个表格让我把内容合并到一个表格内去.还好我会Python,分分钟 ...
- Linux安装fastdfs集群部署
过程问题: make: gcc:命令未找到 解决: yum -y install gcc 一.环境和版本: Linux环境:CentOS 7.6 libfastcommon版本:1.0.39 Fast ...
- vue在Docker上运行
Dockerfile # 设置基础镜像 FROM nginx:latest # 定义作者 MAINTAINER test # 将dist文件中的内容复制到 /etc/nginx/html/ 这个目录下 ...
- NC50965 Largest Rectangle in a Histogram
NC50965 Largest Rectangle in a Histogram 题目 题目描述 A histogram is a polygon composed of a sequence of ...
- java中的变量及命名
变量 变量顾名思义就是可以变化的量 因为java是强类型语言,所以每个变量都必须声明其类型 java变量是最基本的存储单元,要素包括变量名称,变量类型和作用域. 目录 变量 1.常用的变量创建 2.变 ...
- 霍普菲尔得神经网络(Hopfield Neural Network)
设计一个反馈网络存储下列目标平衡点: T = [ 1 -1; -1 1 ]; 并用6组任意随机初始列矢量,包括一组在目标平衡点连线的垂直平分线上的一点作为输入矢量对所设计的网络的平衡点进行测试,观 ...
- 各大厂的语音识别Speech To Text API使用体验
最近发现有声读物能极大促进我的睡眠,但每个前面都有一段开场语,想把它剪掉,但是有多个开场语,所以就要用到语音识别判断一下再剪. 前两年在本地搭建过识别的环境,奈何识别准确率不行,只能找找API了,后面 ...
- SpringBoot:Redis中的zset
zset被描述为有序集合,但RedisTemplate的OpsForZSet().range方法的返回值是set,那么: 这样直接查询zset返回set的操作会使得元素失去顺序吗? 先明确:Set是什 ...
- word段落前的小点·
原因是因为修改论文时,要求在论文的标题前加上 '·' 类似: 在网上搜索了半天,都是加符号,特此记录 解决: 1.文件---选项---显示--勾选段落标记 2.修改样式 至此,设置完毕,章节前的小点已 ...
- 苹果手机和Windows之间互传文件
参考链接:https://jingyan.baidu.com/article/a378c960c46804f229283064.html 实现原理:就是使用Samba服务,windows共享一个文件夹 ...