问题解答
(如图)kafka是一个用来实现异步消息通信的中间件,它的整个架构由Producer、Consumer、Broker组成。
所以,对于kafka如何保证消息不丢失这个问题,可以从三个方面来考虑和实现:
首先是Producer端,需要确保消息能够到达Broker并实现消息存储,在这个层面,有可能出现网络问题,导致消息发送失败,所以,针对Producer端,可以通过2种方式来避免消息丢失:
- Producer默认是异步发送消息,这种情况下要确保消息发送成功,有两个方法:
a.把异步发送改成同步发送,这样producer就能实时知道消息发送的结果。
b.添加异步回调函数来监听消息发送的结果,如果发送失败,可以在回调中重试。
- Producer本身提供了一个重试参数retries,如果因为网络问题或者Broker故障导致发送失败,Producer会自动重试。
然后是Broker端,Broker需要确保Producer发送过来的消息不会丢失,也就是只需要把消息持久化到磁盘就可以了。
(如图)但是,Kafka为了提升性能,采用了异步批量刷盘的实现机制,也就是说按照一定的消息量和时间间隔来刷盘,而最终刷新到磁盘的这个动作,是由操作系统来调度的,所以如果在刷盘之前系统崩溃,就会导致数据丢失。
(如图)Kafka并没有提供同步刷盘的实现,所以针对这个问题,需要通过Partition的副本机制和acks机制来一起解决。
“我简单说一下Partition副本机制,它是针对每个数据分区的高可用策略,每个partition副本集包含唯一的一个Leader和多个Follower,Leader专门处理事务类的请求,Follower负责同步Leader的数据”。
在这样的一种机制的基础上,kafka提供了一个acks的参数,Producer可以设置acks参数再结合Broker的副本机制来个共同保障数据的可靠性。
acks有几个值的选择:
acks=0,表示producer不需要等Broker的响应,就认为消息发送成功,这种情况会存在消息丢失。
acks=1,表示Broker中的Leader Partition收到消息以后,不等待其他Follower Partition同步完,就给Producer返回确认,这种情况下Leader Partition挂了,会存在数据丢失。
acks=-1,表示Broker中的Leader Partition收到消息后,并且等待ISR列表中的follower同步完成,再给Producer返回确认,这个配置可以保证数据的可靠性。
最后,就是Consumer必须要能消费到这个消息,实际上,只要producer和broker的消息可靠的到了保障,那么消费端是不太可能出现消息无法消费的问题,除非是Consumer没有消费完这个消息就直接提交了,但是即便是这个情况,也可以通过调整offset的值来重新消费。
面试点评
从高手的回答可以发现,任何的技术问题,是可以按照请求的顺序,或者调用关系来逐层推导去回答的。
当然,技术的底子要足够厚,至少像kafka里面这些副本、数据同步、分区、刷盘等功能,至少都要有深度的思考和研究。
版权归原作者 似来 所有, 如有侵权,请联系我们删除。