consumer group

consumer instance

一个消费组可能有一个或者多个消费者。同一个消费组可以订阅一个或者多个主题。主题的某一个分区只能被消费组的某一个消费者消费。那么分区和消费者之间是如何对应的呢?

假设消费组cg1(group.id=cg1)订阅了topic1,cg1有3个消费者c1、c2、c3,topic1有5个分区p1、p2、p3、p4、p5。那么c1消费topic1的哪个或者哪些分区呢?p1要被cg1的哪个消费者消费呢?

kafka2.2.0源码中有一个PartitionAssignor接口(在kafka-client.jar的org.apache.kafka.clients.consumer.internals包中),该接口有2个实现类:AbstractPartitionAssignor(在kafka-client.jar的org.apache.kafka.clients.consumer.internals包中)和StreamsPartitionAssignor(在kafka-stream.jar的org.apache.kafka.streams.processor.internals包中)。AbstractPartitionAssignor有3个子类:RangeAssignor(在kafka-client.jar的org.apache.kafka.clients.consumer包中)、RoundRobinAssignor(在kafka-client.jar的org.apache.kafka.clients.consumer包中)、StickyAssignor(在kafka-client.jar的org.apache.kafka.clients.consumer包中)。这些非抽象类分别实现了不同的策略:

记录在消费者这边用ConsumerRecord表示,成员变量有:

String topic、int partition、long offset、long timestamp、TimestampType timestampType、int serializedKeySize、int serializedValueSize、Headers headers、K key、V value、Optional<Integer> leaderEpoch

其中leaderEpoch最不好理解,其意思是???

KafkaConsumer实例就是一个kafka消费者客户端,从kafka集群消费记录。消费者客户端透明地处理kafka代理的故障,透明地适应主题分区。同一消费组的各消费者会负载均衡消息的消费。消费者维护与kafka代理的TCP连接,以取数据(fetch data)。消费者客户端在使用完之后要close,否则就会有资源泄露。和生产者客户端不同,消费者客户端不是线程安全的。

Offsets and Consumer Position
Kafka maintains a numerical offset for each record in a partition. This offset acts as a unique identifier of a record within that partition, and also denotes the position of the consumer in the partition. For example, a consumer which is at position 5 has consumed records with offsets 0 through 4 and will next receive the record with offset 5. There are actually two notions of position relevant to the user of the consumer:
The {@link #position(TopicPartition) position} of the consumer gives the offset of the next record that will be given out. It will be one larger than the highest offset the consumer has seen in that partition. It automatically advances every time the consumer receives messages in a call to {@link #poll(Duration)}.
The {@link #commitSync() committed position} is the last offset that has been stored securely. Should the process fail and restart, this is the offset that the consumer will recover to. The consumer can either automatically commit offsets periodically; or it can choose to control this committed position manually by calling one of the commit APIs (e.g. {@link #commitSync() commitSync} and {@link #commitAsync(OffsetCommitCallback) commitAsync}).
This distinction gives the consumer control over when a record is considered consumed. It is discussed in further detail below.

简单用例:

    public static void main(String[] args) {
Properties props = new Properties();
props.setProperty("bootstrap.servers", "127.0.0.1:9092");
props.setProperty("group.id", "my-test-consumer-group2");
props.setProperty("enable.auto.commit", "true");
props.setProperty("auto.commit.interval.ms", "500");
props.setProperty("auto.offset.reset", "earliest");
props.setProperty("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.setProperty("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Collections.singletonList("test"));
while (true) {
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(10000));
System.out.println(System.currentTimeMillis());
for (ConsumerRecord<String, String> record : records) {
System.out.println(record);
}
}
}

消费者客户端从kafka集群拉数据的方式是poll(Duration timeout),返回ConsumerRecords类型。ConsumerRecords类实现了Iterable<ConsumerRecord<K, V>>接口。在消费者这里,记录用ConsumerRecord实例表示。ConsumerRecords表示记录的集合。上例中,poll方法会最多阻塞1000ms。在fetch不到数据的时候才会阻塞,比如先启动了消费者,但是还没启动生产者的情况。

enable.auto.commit,这个值默认为true,即自动向kafka提交消费者偏移量。消费者必须向kafka提交消费偏移量,否则会一直重复消费同一条消息。除了默认的自动提交外,还可以设置为手动提交,手动提交需要我们显式地调用KafkaConsumer实例的commitXXX方法,如无参的commitSync()方法。auto.commit.interval.ms默认值是5000,即每5000ms才提交一次消费偏移量,时间太长了,设为500ms左右比较合适。

实测,真不提交偏移量的话,随着生产者往topic中生产数据,通过命令查看kafka-consumer-groups --describe --group my-test-consumer-group2 --bootstrap-server 127.0.0.1:9092,发现log-end-offset一直在增大,但是current-offset一直不变,lag也一直在变大。log-end-offset是分区消息偏移量,current-offset是消费偏移量,lag是消费延迟。当重启消费者后,消费者又从上一次启动后消费的起始位置即current-offset开始消费,这就重复消费了。

auto.offset.reset,这个默认为latest,即消费者第一次消费时从最大偏移量开始消费。假如先往topic中放了一些消息,然后才启动了消费者,那么消费者消费不了这些消息,只能消费之后放入topic中的消息。

我们可以显式地把auto.offset.reset设置为earliest,这样子,第一次启动消费者后就可以消费到启动之前topic已有的消息。

注意,这个只会影响消费者第一次的消费情况,只要不是第一次启动,即已经有了消费记录的消费者再次启动后都会接着上次的消费偏移量消费,不管auto.offset.reset的值是latest还是earliest。

每次poll多少条记录呢?或者说每次poll多少数据量呢?

由以下几个参数控制:

fetch.min.bytes,每次poll最小数据量,默认值为1byte

fetch.max.bytes,每次poll最大数据量,默认值为50MB

max.partition.fetch.bytes,每次poll每个分区最大数据量,默认值为1MB

max.poll.records,每次poll最大记录个数,默认值为1048676。

js几种基本数据类型及之间转换与java的不同、js数组一些常见操作的更多相关文章

  1. js五种基本数据类型:string, number, boolean, null, undefined

    /** * 五种基本数据类型:string, number, boolean, null, undefined */ // undefined // 声明变量foo,未声明变量bar var foo; ...

  2. JS四种判断数据类型的方法:typeof、instanceof、constructor、Object.prototype.toString.call()

    1.typeof 1 console.log(typeof ""); //string 2 console.log(typeof 1); //number 3 console.lo ...

  3. java和js中JSONObject,JSONArray,Map,String之间转换

    --------------------------------------------------Java中--------------------------------------------- ...

  4. js数组的常见操作( push、pop、unshift、shift、splice、concat、 join)的用法

    1.数组添加删除 头部或尾部( push().pop().unshift().shift() ) 例2.数组尾部添加 push()方法可向数组的末尾添加一个或多个元素,并返回新的长度 语法:array ...

  5. java 八种基本数据类型之与对应的封装类之间的相互转化

      迁移时间--2017年5月26日17:47:37 Author:Marydon 一.java数据类型之基本数据类型 UpdateTime--2017年1月9日17:31:14 (三)格式转换 1. ...

  6. 5、前端--js常量、变量、5种基本数据类型(number string boolean undefined object)、运算符、流程控制、三元运算符、函数、自定义对象、内置对象、BOM操作

    变量与常量 在JS中声明变量需要使用关键字 老版本 var(全部都是全局变量) 新版本 let(可以声明局部变量) # 推荐使用let(其实问题不大) 在JS中声明常量也需要使用关键字 const # ...

  7. JS中的六大数据类型

    js中有六种数据类型,包括五种基本数据类型(Number,String,Boolean,Undefined,Null),和一种复杂数据类型(Object). typeof 操作符 由于js中的变量是松 ...

  8. Java基础学习(一) -- Java环境搭建、数据类型、分支循环等控制结构、简单一维数组详解

    一:java概述: 1982年,SUN公司诞生于美国斯坦福大学校园,并于1986年上市,在NASDAQ(纳斯达克:是全美证券商协会自动报价系统)的标识为SUNW,2007年改为JAVA. 2009年4 ...

  9. Java中几种常用数据类型之间转换的方法

    Java中几种常用的数据类型之间转换方法: 1. short-->int 转换 exp: short shortvar=0; int intvar=0; shortvar= (short) in ...

随机推荐

  1. VB ListBox 添加横向滚动条

    Private Declare Function SendMessage Lib "user32 " Alias "SendMessageA" (ByVal h ...

  2. js便利关联数组 及数组定义方式 分类

    "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv=& ...

  3. java变量和数据类型总结

  4. 关于css3的fixed布局

    理解CSS3里的Flex布局用法 2016-10-21 阮一峰 web前端开发 web前端开发 web前端开发 微信号 web_qdkf 功能介绍 我们专注web前端开发技术的学习(html,css, ...

  5. laravel利用subquery使左连接查询右表数据唯一查询

    如:表a,连接表b,b中有多条符合查询的记录 1.建立需要的子查询 $sub = DB::table('b')->select(['aid'])->selectRaw('max(id) a ...

  6. ZeroMQ中PUB-SUB模式测试

    因为公司有需求,对程序模块之间通信效率有较高的需求.之前公司用的通信组件是ActiveMQ,根据网上公布的测试结果显示其效率比较低, 后来考虑准备在新的项目中开始使用ZeroMQ.看了几天发现用起来比 ...

  7. Activity设置singleTask无法通过Intent获取值的问题

    AActivity跳转BActivity ,AActivity设置lauchmode = "SingleTask"的话,在getIntent无法获取BActivity里面的内容,无 ...

  8. iOS开发讯飞语音的集成

    1.进入官网注册账号,登陆,注册,应用. 2,下载sdk  导入系统库. 3,关闭bitcode 4,初始化讯飞语音. NSString * initString = [[NSString alloc ...

  9. nodejs url方法

    ulrl方法 url.format(urlObj)   //将对象装换成url url.parse(urlStr[, parseQueryString][, slashesDenoteHost]) / ...

  10. POJ 2413 How many Fibs?#二分+大数加法

    http://poj.org/problem?id=2413 #include<iostream> #include<cstdio> #include<cstring&g ...