分区器:
要么生产者制定分区,要么生产者带了key,进行hash计算
如果消费者一直运行,位移量的提交并不会产生任何影响。但是如果有消费者发生崩溃,或者有新的消费者加入消费者群组的时候,会触发 Kafka 的再均衡。这使得 Kafka 完成再均衡之后,每个消费者可能被会分到新分区中。为了能够继续之前的工作,消费者就需要读取每一个分区的最后一次提交的位移量,然后从位移量指定的地方继续处理。就好像书签一样,需要书签你才可以快速找到你上次读书的位置。
如果提交的偏移量大于客户端处理的最后一个消息的偏移量,那么处于两个偏移量之间的消息将会丢失。
如果提交的位移(offset)量小于消费者实际处理的最后一个消息的位移(offset)量,处于两个位移(offset)之间的消息会被重复处理。
自动提交:
Consumer自动提交机制是根据一定的时间间隔,将收到的消息进行commit。commit的过程和消费过程是异步的,也就是说可能存在消费过程未成功,但是commit已经提交了。此时消息就丢失了。
**问题:**导致消息丢失||导致重复消息
导致重复消息:消费端也是正常消费了offset的数据,但是在2s内消费的数据没有提交offset,消费者重启之后就会重复消费
Kafka消息丢失的情况:
Kafka重复消息的情况:
提交offset失败将导致重复消息
2. 消费端也是正常消费了offset的数据,但是在2s内消费的数据没有提交offset,消费者重启之后就会重复消费
————解决:设置auto.commit.enable=false,每次处理完手动提交。
3. 虽然是手动提交,但可能处理消息时间过长,部分处理成功,但挂了(或因为处理时间太长导致了rebalance,即认为这个消费者挂了,就把他负责的分区交给其他消费者了、或心跳检测出现问题),就没有提交,那么此时重启之后又会重复消费
——————解决:1.比如某个数据要写库,你先根据主键查一下,如果数据有了,就别插入了,update一下好吧
2.比如你是写redis,那没问题了,反正每次都是set,天然幂等性
3.对于消息,我们可以建个表(专门存储消息消费记录)
生产者,发送消息前判断库中是否有记录(有记录说明已发送),没有记录,先入库,状态为待消费,然后发送消息并把主键id带上。
消费者,接收消息,通过主键ID查询记录表,判断消息状态是否已消费。若没消费过,则处理消息,处理完后,更新消息记录的状态为已消费。
4.处理时间太长,其他消费者重复处理,无限循环。
问题:
要么是发送变快了,要么是消费变慢了。
(1) 指明 partition 的情况下,直接将指明的值直接作为 partiton 值;
(2)没有指明 partition 值但有 key 的情况下,将 key 的 hash 值与 topic 的 partition 数进行取余得到 partition 值;
(3) 既没有 partition 值又没有 key 值的情况下, kafka采用Sticky Partition(黏性分区器),会随机选择一个分区,并尽可能一直使用该分区,待该分区的batch已满或者已完成,kafka再随机一个分区进行使用.(以前是一条条的轮询,现在是一批次的轮询)
分区的原因
(1)方便在集群中扩展,每个Partition可以通过调整以适应它所在的机器,而一个topic又可以有多个Partition组成,因此整个集群就可以适应任意大小的数据了;
(2)可以提高并发,因为可以以Partition为单位读写了
什么情况下发生分区再均衡操作
当主题分区发生变化时、
或有新消费者加入群组时、
或群组中有消费者挂掉时
那分区再均衡有哪些优缺点呢?
分区再平衡的优势在于能为消费者群组带来高可用性与伸缩性;
但其缺点在于在发生再均衡这一期间内,消费者是无法读取信息的,所以这将会造成消费者群组会出现一小段时间不可用的情形。所以在应用Kafka的过程中,需要避免无用的分区再均衡发生。
RoundRobinAssignor:
针对的是所有的topic,
缺点:如果同一个消费者组内所有消费者订阅的主题都是相同的,那么策略的分区分配也是均匀的,否则就不均匀了。
RangeAssignor:
针对的是单个topic:
缺点:
StickyAssignor:
一是分区要尽可能的均衡,二是在发生分区再平衡时,分区的分配会尽可能的与上次的分配结果保持相同。
优点:防止再平衡导致的重复消费。
1.push(推)模式很难适应消费速率不同的消费者,因为消息发送速率是由broker决定的。它的目标是尽可能以最快速度传递消息,但是这样很容易造成consumer来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。
2.而pull模式则可以根据consumer的消费能力以适当的速率消费消息。consumer采用pull(拉)模式从broker中读取数据。
pull模式不足之处是,如果kafka没有数据,消费者可能会陷入循环中,一直等待数据到达。——解决:为了避免这种情况,我们在我们的拉请求中有参数,允许消费者请求在等待数据到达的“长轮询”中进行阻塞(并且可选地等待到给定的字节数,以确保大的传输大小)