定义
消息堆积顾名思义就是Kafka中消息太多,在Kafka中准确来说是日志太多,但其实我认为日志堆积主要想说明的是日志没有被及时消费,而且Kafka中日志本来就一直被保存,除非被日志清理策略清理掉。
原因
核心原因是:生产者生产消息的速度大于消费者的消费速度
具体来说,有下面几种原因:
- 消费者消费速度慢
- 消费者宕机
造成的问题
- 消息丢失
因为Kafka会设置日志清理策略,例如:按照时间清理或按照日志大小清理,所以如果消费者来不及消费,日志就会被清理掉,造成数据丢失。
下面是我测试日志清理策略的过程:
我自己测试的配置文件内容如下:
# 代表某个Topic的某个分区的日志保存大小是2048KB,超过该大小,日志就会被清理(删除或压缩)
log.retention.bytes=2048
# 代表每个日志段的大小,大于该大小就会新创建一个日志文件
log.segment.bytes=1024
接着,我用Kafka工具:kafka-producer-perf-test.bat想主题发送消息,命令如下:
.\kafka-producer-perf-test.bat --topic test --num-records 5 --throughput 1 --record-size 500 --producer-props bootstrap.servers=localhost:9092
发现旧的日志会被删除,只会保存4个日志文件,总大小和2048KB差不多,日志文件如下:
# 其中每个日志文件大小约570KB
00000000000000000031.log
00000000000000000032.log
00000000000000000033.log
00000000000000000034.log
实验结果和想象中一致。所以如果消费者来不及消费,日志就会被清理掉,造成数据丢失。
解决方案
- 生产者:一般生产者生产消息速度不好控制,只能从其他部分解决。
- Broker:增加集群数量,增大存储空间,防止数据丢失。
- 消费者:增加消费速度,例如:增加消费者实例,并行消费;消费者多线程处理,增加消费速度;消费者端可以异步处理,接收到消息就提交,但容易造成消息丢失,例如提交后消费者宕机,这是另一个话题了,也有对应的解决方案,例如消费完后记录提交偏移量到数据库,如果消费者提交偏移量到Broker但是宕机,下次启动从数据库中获取真正的偏移量,再从该偏移量重新消费消息。