一、offset的基本概述
offset定义:消费者再消费的过程中通过offset来记录消费数据的具体位置
offset存放的位置:从0.9版本开始,consumer默认将offset保存在Kafka一个内置的topic(系统主题)中,名为__consumer_offsets,即offset维护在系统主题中
说明:__consumer_offsets 主题里面采用 key 和 value 的方式存储数据。key 是 group.id+topic+分区号,value 就是当前 offset 的值。每隔一段时间,kafka 内部会对这个 topic 进行compact(压缩存储),也就是每个 group.id+topic+分区号就保留最新数据
1.面试题☆☆☆
问:消费者的offset维护在什么位置
答:在0.9版本之前维护在zookeeper当中,0.9版本之后维护在系统主题当中
二、自动提交offset
为了使我们能够专注于自己的业务逻辑,Kafka提供了自动提交offset的功能
自动提交offset的相关参数如下:
- enable.auto.commit:是否开启自动提交offset功能,默认是true
- auto.commit.interval.ms:自动提交offset的时间间隔,默认是5s
package com.kafka.consumer;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Properties;
/**
* @author wangbo
* @version 1.0
*/
/**
* 自动提交offset
*/
public class CustomConsumer_03 {
public static void main(String[] args) {
//配置
Properties properties = new Properties();
//连接集群
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"hadoop100:9092,hadoop102:9092"); //多写一个,避免其中一台挂掉,保证数据的可靠性
//反序列化
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
//配置消费者组ID 可以任意起
properties.put(ConsumerConfig.GROUP_ID_CONFIG,"test");
//自动提交,默认为true采用自动提交,为false则为手动提交
properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,true);
//提交时间间隔,默认为5000毫秒,即5s。我们修改为2秒
properties.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG,2000);
//1.创建一个消费者 "","hello"
KafkaConsumer<String, String> kafkaConsumer = new KafkaConsumer<>(properties);
//2.订阅主题 first3
ArrayList<String> topics = new ArrayList<String>();
topics.add("first3");
kafkaConsumer.subscribe(topics);
//3.消费数据
while (true){
ConsumerRecords<String, String> consumerRecords = kafkaConsumer.poll(Duration.ofSeconds(1));//每1秒拉取一批数据
//循环打印消费的数据 consumerRecords.for
for (