Kakfa_消费者问题
消费者消费数据的三种方式
指定topic 读取的是指定topic下所有分区的数据
指定topic partition 读取的是指定topic下的某个分区的数据
指定topic partition offset 读取的是指定topic下 指定分区的 某个offset开始
订阅主题 subscribe 消费该主题的所有分区数据
订阅主题指定分区 assign 消费指定主题分区的数据
精准消费 定位消费 seek 消费指定主题分区 指定偏移量消费
需要先订阅topic 和 分区,然后才能seek 偏移量
消费者开始消费数据时,从哪里开始消费
- step1: 第一次消费规则 由属性决定
lastest 从0开始
earliest 从最新的开始(默认)
//设置消费的位置 从哪里开始消费 合法参数:latest | earliest
props.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,"earliest");
-
step2:第二次及以后 从上一次消费完的offset +1位置开始消费
-
以上成为消费记录,那么kafka如何保存消费记录的呢?
消费者内存中 自己维护 程序不断 不重启的情况下 【优先使用】。
持久化存储在磁盘、存储介质: 【重启程序的依据】
存储kafka中(默认) 自创了主题_consumer_offsets
存储zk/mysql/redis
内存消费记录:kafka自己记录的非常标准,但是程序重启之后就没有了,需要从文件当中读
文件消费记录:kafka自己有一个topic 专门用来存储每个消费者消费的offset
image.png
offset偏移量管理
消费者消费完的记录需要提交,怎样提交?
- 自动提交
- 根据时间周期提交下一下的消费的offset,默认每五秒提交一次
-
风险:
数据丢失
数据重复
image.png
为了防止数据丢失,或者重复消费我们选择手动提交
- 手动提交offset
先消费数据,然后再提交offset
风险:如果此时我已经消费了两个分区的数据,第三个分区还没有消费完,程序崩溃了,offset没有提交,就会导致,下次程序启动的时候 重复消费数据 - 手动提交--基于分区提交offset
offsets.put(partition,new OffsetAndMetadata(consumerOffset+1));
把当前分区消费的最后一条日志的offset +1,提交上去。 -
手动提交分区offset探秘
image.png
消费者消费数据分配策略
问题:Kafka 消费组Consumer Group中多个消费者Consumer如何消费Topic队列中数据?
前提-kafka中消费规则:
一个分区只能被一个消费者消费
一个消费者可以消费多个分区
最理想的状态:消费者和分区 一对一
策略:
范围分配
轮询分配
粘性分配
1_RangeAssignor 分配策略-范围分配
- Kafka中默认的分配规则
- 一个topic中所有的分区按照消费者的个数平均分,多的就分配给编号小的消费者
优点:适用于消费topic比较少的情况,分配会比较平均
ex: 一个topic内有七个分区 有三个消费者c1 c2 c3
c1 (0,1,2) c2(3,4) c3(56)
缺点: 不适应于多个消费者消费多个topic,会造成编号小的负载压力大的情况
列如:三个消费者 消费三个topic 每个topic有7个分区会导致
c1 -t1(0,1,2) t2(0,1,2) t3(0,1,2)
c2 -t1(3,4) t2(3,4) t3(3,4)
c3 t1(5,6) t2(5,6) t3(5,6)
2_RoundRobinAssignor 分配策略-轮询策略
- 给每个Topic和其分区编号,轮询分配给消费者
一个消费者分配一个 轮询分配
适合:所有消费者都订阅相同的主题。
缺点:如果有消费者故障 或者加入新的消费者 之前全推倒 重新分配
缺点: c1、c2消费第一个topic,c2、c3消费第二个Topic、c3消费第三个Topic,指定消费者消费Topic
会导致c3 (t2-p2,t3-p1-p2-p3)负载过大
3_StickyAssignor 分配策略-粘性策略(推荐)
粘性策略注意针对的是消费过程者,如果有消费者挂掉了.该如何分配其正在消费的分区.
不出故障的时候跟轮询一样,出故障之后正常的都不动,轮询的分配故障后的分区