Kafka是一个用来实现异步消息通讯的一个中间件,它的整个架构是由Producer、consumer和broker来组成。对于Kafka如何去保证消息不丢失问题,可以从三个方面来考虑和实现。
首先Producer端需要去确保消息能够到达Broker,并且实现消息的存储。这个过程可能会出现网络问题导致消息发送失败,所以针对Producer端可以通过两种方式来避免消息丢失。由于Producer默认是异步发送消息的,这种情况下需要确保消息是发送成功的,可以使用以下两个方法
1、把异步发送改成同步发送,这样producer就能实时知道消息发送结果
2、添加异步回调函数来监听消息发送的结果,如果发送失败,可以在回调中重试
Producer本身提供了一个重试参数retries,如果因为网络问题或者broker故障导致发送失败,那么Producer会自动重试。
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,但是即便是出现这种情况,我们也可以通过重新调整offset的值来实现重新消费。