为什么要重设消费组位移
Kafka的消费者读取消息是可以重演的。
RabbitMQ ActiveMQ 这样传统的消息中间件,处理和响应消息的方式,一旦消息被成功处理就会从Broker上删除
kafka是基于日志结构的消息引擎,消费者在消费消息时,仅仅是从磁盘上读取数据而已,只是读的操作,因此消费者不会删除消息数据。同时,由于位移数据是由消费者控制的,因此它能够很容易地修改位移的值,实现重复消费历史数据的功能
选择Kafka 如果你的场景时较高的通吐量,每条消息的处理时间都很短,同时很在意消息的顺序
重设位移策略
1位移维度 根据位移值重设,直接吧消费者的位移值重设成我们给定的位移值
2时间维度 给定一个时间维度,让消费者把位移调整成大于该时间的最小位移;也可以给出一段时间比如30分钟前,然后让消费者直接将位移调回到30分钟之前的位移值
Current策略表示将位移调整到消费者当前提交的最新位移。
你修改了消费者程序代码,并重启了消费者,结果发现代码有问题,需要回滚之前的代码变更,同时也要把位移重设到消费者重启时的位置。
Specified-Offset 消费者程序在处理某条错误消息时,可以手动跳过此消息。在实际使用过程中,可能会出现corrupted消息无法被消费的情形,此时情绪会抛出异常,无法继续工作
Shift-By-N策略制定位移的相对数值 可以向前跳也可以向后跳
DateTime允许制定一个时间 然后将位移重置到该时间之后的最早位移处。常见的使用场景是,你想重新消费昨天的而数据,可以使用该策略将位移移到昨天0点
Duration策略是指给定的时间间隔
如果想将位移调回到15分钟之前,那么指定PT0H15M0S
重设消费者组位移的方式有两种
通过消费者API来实现
void seek(TopicPartition partition, long offset);
void seek(TopicPartition partition, OffsetAndMetadata offsetAndMetadata);
调整多个主题分区
void seekToBeginning(Collection
void seekToEnd(Collection
Earliest策略
Properties consumerProperties = new Properties();
consumerProperties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
consumerProperties.put(ConsumerConfig.GROUP_ID_CONFIG, groupID);
consumerProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
consumerProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
consumerProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
consumerProperties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, brokerList);
String topic = "test"; // 要重设位移的 Kafka 主题
try (final KafkaConsumer
new KafkaConsumer<>(consumerProperties)) {
consumer.subscribe(Collections.singleton(topic));
consumer.poll(0);
consumer.seekToBeginning(
consumer.partitionsFor(topic).stream().map(partitionInfo ->
new TopicPartition(topic, partitionInfo.partition()))
.collect(Collectors.toList()));
}
1创建的消费者程序,禁止自动提交位移
Latest 策略
consumer.seekToEnd(
consumer.partitionsFor(topic).stream().map(partitionInfo ->
new TopicPartition(topic, partitionInfo.partition()))
.collect(Collectors.toList()));
Current策略
consumer.partitionsFor(topic).stream().map(info ->
new TopicPartition(topic, info.partition()))
.forEach(tp -> {
long committedOffset = consumer.committed(tp).offset();
consumer.seek(tp, committedOffset);
});
Specified-Offset策略
long targetOffset = 1234L;
for (PartitionInfo info : consumer.partitionsFor(topic)) {
TopicPartition tp = new TopicPartition(topic, info.partition());
consumer.seek(tp, targetOffset);
}
Shift-By-N策略
for (PartitionInfo info : consumer.partitionsFor(topic)) {
TopicPartition tp = new TopicPartition(topic, info.partition());
// 假设向前跳 123 条消息
long targetOffset = consumer.committed(tp).offset() + 123L;
consumer.seek(tp, targetOffset);
}
DateTime策略
long ts = LocalDateTime.of(
2019, 6, 20, 20, 0).toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
Map
consumer.partitionsFor(topic).stream().map(info ->
new TopicPartition(topic, info.partition()))
.collect(Collectors.toMap(Function.identity(), tp -> ts));
for (Map.Entry
consumer.offsetsForTimes(timeToSearch).entrySet()) {
consumer.seek(entry.getKey(), entry.getValue().offset());
}
Duration策略代码
Map
.map(info -> new TopicPartition(topic, info.partition()))
.collect(Collectors.toMap(Function.identity(), tp -> System.currentTimeMillis() - 30 * 1000 * 60));
for (Map.Entry
consumer.offsetsForTimes(timeToSearch).entrySet()) {
consumer.seek(entry.getKey(), entry.getValue().offset());
}
通过Kafka-consumer-groups命令行脚本来实现
Earliest 策略直接指定–to-earliest
bin/kafka-consumer-groups.sh --bootstrap-server kafka-host:port --group test-group --reset-offsets --all-topics --to-earliest –execute
Latest 策略直接指定–to-latest。
bin/kafka-consumer-groups.sh --bootstrap-server kafka-host:port --group test-group --reset-offsets --all-topics --to-latest --execute
Current 策略直接指定–to-current。
bin/kafka-consumer-groups.sh --bootstrap-server kafka-host:port --group test-group --reset-offsets --all-topics --to-current --execute
Specified-Offset 策略直接指定–to-offset
bin/kafka-consumer-groups.sh --bootstrap-server kafka-host:port --group test-group --reset-offsets --all-topics --to-offset
Shift-By-N 策略直接指定–shift-by N。
bin/kafka-consumer-groups.sh --bootstrap-server kafka-host:port --group test-group --reset-offsets --shift-by
DateTime 策略直接指定–to-datetime。
bin/kafka-consumer-groups.sh --bootstrap-server kafka-host:port --group test-group --reset-offsets --to-datetime 2019-06-20T20:00:00.000 --execute
Duration 策略,我们直接指定–by-duratio
bin/kafka-consumer-groups.sh --bootstrap-server kafka-host:port --group test-group --reset-offsets --by-duration PT0H30M0S --execute