首先我们需要知道什么情况下kafka会丢失消息,下面我们来分析kafka丢失消息的情况
情况一:auto.commit.enable=true时,消息处理时间过长,导致位移先于程序完成前提交
auto.commit.enable=true,即消费端自动提交offersets设置为true,当消费者拉到消息之后,还没处理完auto.commit.interval.ms提交时间间隔就到了。提交了offerssets。下次消费是,是从新的offsets开始消## 标题费。部分没处理完的数据,就出现了消息丢失。
相关配置说明:
enable.auto.commit
Consumer 在commit offset时有两种模式:自动提交,手动提交。手动提交在前面已经说过。自动提交:是Kafka Consumer会在后台周期性的去commit。
默认值是true。
auto.commit.interval.ms
自动提交间隔。范围:[0,Integer.MAX],默认值是 5000 (5 s)
解决方案:(1) 设置为手动提交,在消息处理完毕之后手动提交位移offerset。即auto.commit.enable=false,程序中消费时,带处理完毕后手动提交。(最佳方案)
(2) 根据消息处理时间,设置更长时间间隔(不建议采取此种方案)
情况二:PageCache上的数据由于断电或机器故障导致为来的及刷新到磁盘,造成消息丢失。
kafka数据一开时存储在PageCache上的,定期刷新到磁盘上。也就是说,在还没到刷新到磁盘上时间间隔时,系统故障或者断电,PageCache数据丢失。
配置说明:
log.flush.interval.messages
例如:log.flush.interval.messages=10000
每当producer写入10000条消息时,刷数据到磁盘
log.flush.interval.ms
例如:log.flush.interval.ms=1000
每间隔1秒钟时间,刷数据到磁盘
解决方案:
设置 log.flush.interval.messages, 默认值Long.MAX_VALUE
log.flush.interval.ms(默认null) 两个参数的值,提高消息刷新到磁盘的速度。
但是不建议设置这两个参数,刷盘任务应该交由操作系统调配。
3、磁盘爆满,导致消息丢失。
当kafka server的被写入海量消息后,会生成很多数据文件,且占用大量磁盘空间,如果不及时清理,可能磁盘空间不够用,kafka默认是保留7天。
解决方案,设置更短的保存时间。
1、 # 保留三天,也可以更短
log.retention.hours=72(默认值168)
2、 段文件配置1GB,有利于快速回收磁盘空间,重启kafka加载也会加快(如果文件过小,则文件数量比较多,
kafka启动时是单线程扫描目录(log.dir)下所有数据文件)
log.segment.bytes=1073741824 (默认值1G)
acks参数消息丢失情况
acks这个参数用来指定分区中必须要多少个副本收到这条消息,之后生产者才会认为这条消息是成功写入的。
(1)
acks=1 默认值为1。生产者发送消息之后,只要分区的leader副本成功写入消息,那么它就会收到来自服务端的成功响应。如果消息无法写入leader副本,比如在leader副本奔溃的时候、重新选举leader副本的过程中,那么生产者就会收到一个错误的消息,为避免消息丢失,生产者可以选择重新发送消息。
消息丢失出现的情况:
消息成功写入leader副本,且在被其他follower副本拉取前leader副本奔溃,那么消息还是会出现丢失,因为新选举的leader副本没有这条消息。
(2)
acks=0,生产者发送消息后不需要等待任何服务端的响应。如果消息从发送到写入kafka的过程中出现异常,导致Kafka没有收到这条消息,消息也就丢失了。