7 偏移量
代码地址:https://github.com/luslin1711/kafka_demo/tree/master/kafka_demo_07
一、同步与异步组合提交偏移量
一般情况下,针对偶尔出现的提交失败,不进行重试不会有太大问题,因为如果提交失败是因为临时原因导致的,那么后续的提交总会有成功的。但如果这是在关闭消费者前的最后一次提交,就要确保能够提交成功
因此,在消费者关闭前一般会组合使用commitAsync() 与commitSync()
public void run() {
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(properties, new StringDeserializer(), new StringDeserializer());
try {
consumer.subscribe(Collections.singletonList(topic));
while (true) {
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
if (records.isEmpty()) continue;
System.out.println("recordsLen: " + records.count());
for ( ConsumerRecord <String, String> record : records ) {
System.out.println("threadId: " + Thread.currentThread().getName() +" ,groupId: " + groupId +", partition: " + record.partition());
}
consumer.commitAsync();
}
} catch (WakeupException E) {
// 忽略异常,关闭消费者
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
consumer.commitSync();
} finally {
consumer.close();
}
}
}
如果一切正常,我们使用consumer.commitAsync()方法来提交。这样速度更快,而且即使这次提交失败,下次提交也可能会成功
如果直接关闭消费者,那就没有所谓的“下一次提交”了。使用consumer.commitSync()方法会一直重试,直到提交成功或者发生无法恢复的错误
二、提交特定的偏移量
提交偏移量的频率与处理消息批次的频率是一样的。但如果想要更频繁地提交该怎么办?如果poll方法返回了一大批数据,为了避免再均衡导致重复处理整批消息,想要在批次中间提交该怎么办?这种情况无法通过commitAsync()进行提交,因为它只会提交 最后一个偏移量,而此时该批次里的消息还没有处理完。
可以在commitAsync()时传入希望提交的分区和偏移量的map
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.consumer.OffsetAndMetadata;
import org.apache.kafka.common.TopicPartition;
import org.apache.kafka.common.errors.WakeupException;
import org.apache.kafka.common.serialization.StringDeserializer;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class Consumer implements Runnable{
protected String groupId;
protected String topic;
protected Properties properties;
private Map<TopicPartition, OffsetAndMetadata> currentOffsets = new HashMap<>