Kafka Ack应答机制理解

背景

最近李哥做了kafka的调研,我看了他做的kafka与rabbitmq的对比与性能分析,打算深入了解一下kafka的ack应答机制

1.kafka基础大家可自行学习

2.这里我直接分析下ack应答机制,李哥的压测全部都是用的默认配置,ack应答用的all (-1) 即等leader与isr里的follower里都落盘后再给producer回应,我们来盘点一下这种机制的优缺点。

 

什么是ack应答机制?

简单点理解就是:

  1. producer发送消息到leader收到消息之后发送ack
  2. leader和follower之间同步完成数据会发送ack

实际上ack可以看做一种信号,用于消费者来确认消息是否落盘

 

ISR是什么?

实际上它是副本同步机制,具体介绍,请走传送门http://objcoding.com/2019/11/05/kafka-isr/

 

ack应答机制有哪些模式以及各种模式的优缺点?

为了更好的适应用户需求,ack应答机制有三种可靠级别设置

  1. 级别0 , 通俗上讲就是,producer发送消息到broker(可以理解为机器), 不等待broker的ack回应,直接返回,这一种操作提供了最低的延迟,毕竟没有经过leader与follower确认,所以存在一种情况是,broker一接收到数据还没有写入到磁盘就已经返回,这时候broker发生故障,就造成了丢失数据(相当于异步发送,消息发送到broker后就给producer返回true了,后续数据落盘就靠玄学了,producer无法知道消息是否真的落库),所以它的优点是快,缺点是不可靠。
     
  2. 级别1, 这个比级别0可靠些,producer发送消息到broker后,会等待leader落盘后再给producer返回信号,告诉producer数据已经收到了,但是也存在一种情况,那就是follower没有确认数据是否落盘,如果存在leader于follower数据不一致的情况,又碰巧leader挂了,选举了一个数据不健全的follower为新的leader,这就造成了数据丢失。所以它可靠性中等,性能不如0级。
     
  3. 级别-1, 这个级别可靠性算是最高的了,至少比前两种高,他要等leader与isr(可以看做一些比较活跃的follower集合)中follower确认全部落盘后在给producer回应,这种方式可靠,但是牺牲了性能,所以它是三种模式里最慢的。

 

kafka与rabbitmq性能、使用场景比较

先上图,下面是性能测试,其中kafka应答机制用的-1,即最慢、可靠的模式

Kafka Ack应答机制理解_第1张图片

光看这个压测结果,我们不难看出,kafka性能更高,看是算上可靠性呢?

这就引出一个问题,kafka存在数据重复写入或者重复消费问题,可靠性上不如rabbitmq, 所以建议的是,数据严谨场景(关于钱的、奖励的、容易引发客户愤怒的),我们使用rabbitmq, 虽然慢,但是人家可靠,数据不严谨场景,比如数据上报、日志啥的,多一条少一条无伤大雅的,我们引入kafka,毕竟它快。

 

kafka的数据重复写入、消费问题

1.重复写入场景,主要出现在我们我们ack应答机制用的-1的时候, 举个栗子,producer发送消息到broker, broker里leader、follower已经落盘,准备回应producer的时候,突然间这个leader挂了,ack没发出去,producer没收到确认收到的消息,这个时候,会重新选举出一个leader, producer会重新发消息到新的leader并落库, 这就造成了数据重复,试想如果kafka应用在给用户发奖励的场景, 给用户多发一份奖励,会怎么样呢?

这种的问题出现场景不多,解决方案目前来说我能想到的就只能是架构、运维层面优化,保持服务稳定。

 

2.重复消费场景,这种问题大多出现在ack应答机制设置为0或者1的情况,举个1的例子,某一个consume因消费过慢、网络问题或者无法消费,触发rebalanced(kafka集群的一个保护设定,用于剔除掉无法消费或者过慢的消费者

), 此时数据会重新发到一个新的consume里消费,这时候就会出现重复消费的问题,根本上就是记录消费位置的offset因某种情况没有改变,消费进入死循环或者多次从同一个offset消费。试想,kafka应用在扣除用户金币的场景,多扣一次,又会怎么样呢?

重复消费问题的解决方案我们可以从下面的角度入手:

  1. 确认consume的消费速度,过慢是不行滴
  2. 幂等性,0.11版本及之后版本的kafka引入幂等,即无论向server发送多少次一样的数据,都会持久化一次,0.11版本之前的需要consume自己去做幂等逻辑,但幂等性也只能解决单次会话,单个分区数据重复问题,因为假如0.11版本之后你开启了幂等性,那么如果producer挂了,新起了一个producer时,会重新分配一个新的pid,之前的去重数据集合就会失效。这一点实际上也解决了,就是由消费组、主题、分区组成的唯一一个id, 重启之后这个凭借这个id可以找回pid,这里不详述,有需要自行搜索资料学习。
  3. 通过kafka配置来尽可能的避免重复消费,这点网上有介绍,如果配置调优,有兴趣可以继续深入
  4. 做好监控,无论是消息积压还是consume的消费速度等,如果可以,最好也能监控到offset的位置信息

 

 

以上只是我个人观点,如有问题请指明,感谢

你可能感兴趣的:(Kafka,kafka-ack)