一位工作了5年的小伙伴去美团面试以后,跟我反馈说,被问到一个“如何保证Kafka消息不丢失?”的问题,不知道如何回答。其实,这道题真的很基础。
很多小伙伴可能只会回答说,消息要持久化,添加消息确认机制。如果,你只是这样回答,那就和普通的程序员没什么区别。要想让面试官感觉你确实有不一样的理解,就应该从多个方面更全面地来分析和回答这个问题。今天,我来给大家讲明白。
首先第一个是服务器端。设置broker中的配置项unclean.leader.election.enable = false,保证所有副本同步。同时,Producer将消息投递到服务器的时候,我们需要将消息持久化,也就是说会同步到磁盘。注意,同步到硬盘的过程中,会有同步刷盘和异步刷盘。如果选择的是同步刷盘,那是一定会保证消息不丢失的。就算刷盘失败,也可以即时补偿。但如果选择的是异步刷盘的话,这个时候,消息有一定概率会丢失。网上有一种说法,说Kafka不支持同步刷盘,这种说法也不能说是错的。但是可以通过参数的配置变成同步刷盘,比如,这样的配置:
# 当达到下面的消息数量时,会将数据flush到日志文件中。默认10000
#log.flush.interval.messages=10000
# 当达到下面的时间(ms)时,执行一次强制的flush操作。interval.ms和interval.messages无论哪个达到,都会flush。默认3000ms
#log.flush.interval.ms=1000
# 检查是否需要将日志flush的时间间隔
log.flush.scheduler.interval.ms = 3000
同样可以达到同步刷盘的效果。
第二个,就是生产者Producer,使用带回调通知的send(msg,callback)方法,并且设置acks = all 。它的消息投递要采用同步的方式。Producer要保证消息到达服务器,就需要使用到消息确认机制,也就是说,必须要确保消息投递到服务端,并且得到投递成功的响应,确认服务器已接收,才会继续往下执行。那如果,Producer将消息投递到服务器端,服务器来没来得及接收就已经宕机了,那投递过来的消息岂不是丢失了,怎么办呢?大家不要慌,在Producer投递消息时,都会记录日志,然后再将消息投递到服务器端,就算服务器宕机了,等服务器重启之后,也可以根据日志信息完成消息补偿,确保消息不丢失。
第三个,就是消费者Consume。设置enable.auto.commit为false。在Kafka中,消息消费完成之后,它不会立即删除,而是使用定时清除策略,也就是说,我们消费者要确保消费成功之后,手动ACK提交。如果消费失败的情况下,我们要不断地进行重试。所以,消费端不要设置自动提交,一定设置为手动提交才能保证消息不丢失。
Kafka要严格意义上保证消息不丢失,需要从三个方面来设置,
第一个服务器端持久化设置为同步刷盘、第二个生产者设置为同步投递,第三个消费端设置为手动提交。
以上就是对Kafka保证消息不丢失的解决方案。