Kafka消费者手动提交消息偏移
生产者每次调用poll()方法时,它总是返回由生产者写入Kafka但还没有消费的消息,如果消费者一致处于运行状态,那么分区消息偏移量就没什么用处,但是如果消费者发生崩溃或者有新的消费者加入群组,就会触发再均衡,完成再均衡之后,每个消费可能分配到新的分区,而不是之前处理的那个,为了能够继续之前的工作,消费者需要读取每个分区最后一次提交的偏移量,然后从偏移量制定的地方开始工作。消费者会往一个__consumer_offser的主题发送消息,消息里包含每个分区的偏移量。
1.同步提交
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer; import java.util.Collections;
import java.util.Properties; /**
* Created by zhangpeiran on 2018/10/9.
*/
public class MyConsumer { public static void main(String[] args){
Properties properties = new Properties();
properties.put("bootstrap.servers","ip:9092");
properties.put("key.deserializer","org.apache.kafka.common.serialization.StringDeserializer");
properties.put("value.deserializer","org.apache.kafka.common.serialization.StringDeserializer");
properties.put("group.id","DemoConsumerGroup"); //默认值为latest,当消费者读取的分区没有偏移量或偏移量无效时,消费者将从最新的记录开始读
//当一个消费group第一次订阅主题时,符合这种情况,在Consumer启动之前,Producer生产的数据不会被读取
//置为earliest,表示从分区起始位置读取消息
properties.put("auto.offset.reset","earliest"); //设置手动提交消息偏移
properties.put("enable.auto.commit","false"); //一次拉取的最大消息条数
properties.put("max.poll.records",10); KafkaConsumer<String,String> consumer = new KafkaConsumer<String, String>(properties); consumer.subscribe(Collections.singletonList("Demo3")); int count = 0;
try {
while (true){
ConsumerRecords<String,String> records = consumer.poll(10);
for(ConsumerRecord<String ,String> record : records){
count ++;
if(count == 50)
consumer.commitSync();
System.out.println(record.topic() + "," + record.partition() + "," + record.offset() + "," + record.key() + "," + record.value());
}
System.out.println(count);
}
} finally {
consumer.close();
}
}
}
说明:在上述例子中,主题Demo3中已经有100条消息,第一次远行Consumer时,在读取到50条消息时,提交一次偏移量,输出的count值为100;第二次不改变消费group,会从51条开始读取,所以输出的count值为50
2. 异步提交,同步提交时,在broker回应指,会一直阻塞、重试,限制应用的吞吐量,因此可以采用异步提交,异步提交失败时不会重试,因为如果提交失败时因为临时的问题导致的,那么后续的提交总户有成功的。
consumer.commitAsync();
3. 同步、异步组合提交,确保消费者在关闭或者再均衡之前提交成功
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer; import java.util.Collections;
import java.util.Properties; /**
* Created by zhangpeiran on 2018/10/9.
*/
public class MyConsumer { public static void main(String[] args){
Properties properties = new Properties();
properties.put("bootstrap.servers","ip:9092");
properties.put("key.deserializer","org.apache.kafka.common.serialization.StringDeserializer");
properties.put("value.deserializer","org.apache.kafka.common.serialization.StringDeserializer");
properties.put("group.id","DemoConsumerGroup"); //默认值为latest,当消费者读取的分区没有偏移量或偏移量无效时,消费者将从最新的记录开始读
//当一个消费group第一次订阅主题时,符合这种情况,在Consumer启动之前,Producer生产的数据不会被读取
//置为earliest,表示从分区起始位置读取消息
properties.put("auto.offset.reset","earliest"); //设置手动提交消息偏移
properties.put("enable.auto.commit","false"); //一次拉取的最大消息条数
properties.put("max.poll.records",10); KafkaConsumer<String,String> consumer = new KafkaConsumer<String, String>(properties); consumer.subscribe(Collections.singletonList("Demo3")); int count = 0;
try {
while (true){
ConsumerRecords<String,String> records = consumer.poll(10);
for(ConsumerRecord<String ,String> record : records){
count ++;
//if(count == 50)
//consumer.commitAsync();
//consumer.commitSync();
System.out.println(record.topic() + "," + record.partition() + "," + record.offset() + "," + record.key() + "," + record.value());
}
consumer.commitAsync();
//System.out.println(count);
}
} finally {
try {
consumer.commitSync();
} finally {
consumer.close();
}
//consumer.close();
}
}
}
5. 提交特定的偏移量。前面提交的是最后一个偏移量,poll可能返回了大批数据,这样在再均衡时,可能重复处理的消息比较多。消费者API提供了指定分区和偏移量来提交
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 java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* Created by zhangpeiran on 2018/10/9.
*/
public class MyConsumer {
public static void main(String[] args){
Properties properties = new Properties();
properties.put("bootstrap.servers","ip:9092");
properties.put("key.deserializer","org.apache.kafka.common.serialization.StringDeserializer");
properties.put("value.deserializer","org.apache.kafka.common.serialization.StringDeserializer");
properties.put("group.id","DemoConsumerGroup");
//默认值为latest,当消费者读取的分区没有偏移量或偏移量无效时,消费者将从最新的记录开始读
//当一个消费group第一次订阅主题时,符合这种情况,在Consumer启动之前,Producer生产的数据不会被读取
//置为earliest,表示从分区起始位置读取消息
properties.put("auto.offset.reset","earliest");
//设置手动提交消息偏移
properties.put("enable.auto.commit","false");
//一次拉取的最大消息条数
properties.put("max.poll.records",1000);
KafkaConsumer<String,String> consumer = new KafkaConsumer<String, String>(properties);
consumer.subscribe(Collections.singletonList("Demo5"));
int cnt = 0;
int count = 0;
Map<TopicPartition,OffsetAndMetadata> currentOffsets = new HashMap<TopicPartition,OffsetAndMetadata>();
try {
while (true){
ConsumerRecords<String,String> records = consumer.poll(10);
for(ConsumerRecord<String ,String> record : records){
count ++;
//if(count == 50)
//consumer.commitAsync();
//consumer.commitSync();
//offset + 1,下次消费者从该偏移量开始拉取消息
currentOffsets.put(new TopicPartition(record.topic(),record.partition()),new OffsetAndMetadata(record.offset()+1,"no"));
if ((count / 10 == 1) && (count % 10 == 0)){
System.out.println(count);
consumer.commitSync(currentOffsets);
}
System.out.println(record.topic() + "," + record.partition() + "," + record.offset() + "," + record.key() + "," + record.value());
}
//consumer.commitAsync();
cnt ++;
}
} finally {
try {
//consumer.commitSync();
} finally {
consumer.close();
}
//consumer.close();
}
}
}
生产者生产了100条消息,上述代码的结果是:依次启动-暂停消费者10次,每次读取100,90,80,...10条消息,原因是每次消费者读取前10条的时候提交一次偏移量
Kafka消费者手动提交消息偏移的更多相关文章
- kafka 消费者拉取消息
本文只跟踪消费者拉取消息的流程.对于 java 客户端, kafka 的生产者和消费者复用同一个网络 io 类 NetworkClient. 入口在 KafkaConsumer#pollOnce 中, ...
- Kafka学习笔记(7)----Kafka使用Cosumer接收消息
1. 什么是KafkaConsumer? 应用程序使用KafkaConsul'le 「向Kafka 订阅主题,并从订阅的主题上接收消息.Kafka的消息读取不同于从其他消息系统读取数据,它涉及了一些独 ...
- 关于SpringKafka消费者的几个监听器:[一次处理单条消息和一次处理一批消息]以及[自动提交offset和手动提交offset]
自己在使用Spring Kafka 的消费者消费消息的时候的实践总结: 接口 KafkaDataListener 是spring-kafka提供的一个供消费者接受消息的顶层接口,也是一个空接口; pu ...
- kafka多线程消费及处理和手动提交处理方案设计[转]
转自:http://blog.csdn.net/haoyifen/article/details/54692503 kafka与其他消息队列不同的是, kafka的消费者状态由外部( 消费者本身或者类 ...
- kafka 0.10.2 消息消费者
package cn.xiaojf.kafka.consumer; import org.apache.kafka.clients.consumer.ConsumerConfig; import or ...
- RocketMQ消息丢失解决方案:同步刷盘+手动提交
前言 之前我们一起了解了使用RocketMQ事务消息解决生产者发送消息时消息丢失的问题,但使用了事务消息后消息就一定不会丢失了吗,肯定是不能保证的. 因为虽然我们解决了生产者发送消息时候的消息丢失问题 ...
- kafka消费者客户端(0.9.0.1API)
转自:http://orchome.com/203 kafka客户端从kafka集群消费消息(记录).它会透明地处理kafka集群中服务器的故障.它获取集群内数据的分区,也和服务器进行交互,允许消费者 ...
- Kafka权威指南 读书笔记之(四)Kafka 消费者一一从 Kafka读取数据
KafkaConsumer概念 消费者和消费者群组 Kafka 消费者从属于消费者群组.一个群组里的消费者订阅的是同一个主题,每个消费者接收主题一部分分区的消息. 往群组里增加消费者是横向伸缩消费能力 ...
- Kafka(分布式发布-订阅消息系统)工作流程说明
Kafka系统架构Apache Kafka是分布式发布-订阅消息系统.它最初由LinkedIn公司开发,之后成为Apache项目的一部分.Kafka是一种快速.可扩展的.设计内在就是分布式的,分区的和 ...
随机推荐
- 安恒DASCTF 四月战 WP
web1 打开提就是源码审计 考点:反序列化POP链.反序列化字符串逃逸 show_source("index.php"); function write($data) { ret ...
- 阿里技术专家深入讲解,SpringMVC入门到进阶,看这一篇就够了
前言 SpringMVC是一个实现了Web MVC设计模式的轻量级Web框架.它与前辈Struts 2框架一样,都属于MVC框架,因为其使用和性能等方面比Struts 2更加优异,所以Spring M ...
- 如何用pdfFactory新建打印机并设置属性
今天我们来讲一讲,在pdfFactory中如何去修改PDF文件打印页面的页边距.页面大小.页面清晰度等属性参数. pdfFactory是一款Windows平台上的虚拟打印机,在没有打印机可以安装的情况 ...
- 《SpringBoot第一篇:HelloWorld启蒙》
每篇一律 云对雨,雪对风,晚照对晴空. 来鸿对去雁,宿鸟对鸣虫. --<声律启蒙·一东> 什么是Spring Boot SpringBoot 是为了简化 Spring 应用的创建.运行.调 ...
- nginx学习http_access_module模块
location ~ ^/1.html { root /opt/app/code; deny XXXXX; #这个ip不能访问1.html allow all; #其他的可以访问这个页面1.html ...
- python菜鸟教程学习9:函数
函数的定义 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段.python提供了很多内建函数,但我们依然可以自己创建函数,叫做用户自定义函数. 自定义函数 你可以定义一个由自己想要功能 ...
- 精尽MyBatis源码分析 - 文章导读
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- Java多线程中的虚假唤醒和如何避免
先来看一个例子 一个卖面的面馆,有一个做面的厨师和一个吃面的食客,需要保证,厨师做一碗面,食客吃一碗面,不能一次性多做几碗面,更不能没有面的时候吃面:按照上述操作,进行十轮做面吃面的操作. 用代码说话 ...
- 深度学习基础 Probabilistic Graphical Models | Statistical and Algorithmic Foundations of Deep Learning
目录 Probabilistic Graphical Models Statistical and Algorithmic Foundations of Deep Learning 01 An ove ...
- 在html页中添加视频的几种方式
1.avi格式代码片断如下: <object id="video" width="400" height="200" border=& ...