kafka lag 空洞问题

之前使用 kafka 的时候突然发现一个诡异的问题,位于一个 kafka topic 上的消费者的 lag 突然无法下降了,即使重启消费者进程既依然不起作用。初步分析感觉是 kafka 服务器端返回的 offset 数据不对,于是乎对于集群中的所有消费者机器进行抓包,然后重启有问题的 partition 对应的消费者服务。rebalance 完成后,将有问题的那个 partition 对应服务器的网络数据包导出来,在本地进行分析。

但是这个包太大了,载入 wireshark 后机器内存不足会打开失败,需要对原始文件进行拆分(命令:editcap -c <packets-per-file> <input-pcap-file> <output-prefix> ),具体参见这里。然后一次打开每个拆分后的文件,筛选的时候输入 kafka.partition_id==15 , 15 就是出问题的那个 partition 。拆分后的文件每个文件都按照这个筛选条件搜索,找到第一个出现问题的分片文件,如果这个命令的关键 TCP 包被截断,可以再和上一个分片做合并(命令格式: mergecap -w output.pcap input.pcap input2.pcap [input3.pcap . . .])。

前方高能预警,下面的图片个数比较多

图 1

首先看第一个 OffsetFetch 请求,请求 partition 15 的当前消费进度。

图 2

返回的是 255921

图 3

客户端就按照 255921 这个 offset 去消费队列中的数据。

图 4

没有想到服务器端告诉客户端当前 offset 超出正常范围了。

图 5

客户端只好重新请求partition 15 的 offset。

图 6

最终客户端给返回的是 272734,前后两者相差 16813

图 7

客户端又按照 272734 去取数据。

图 8

由于当前已经到队列末尾了,所以不会得到任何数据。但是在 kafka manager 上显示的 LAG 数目,确是雷打不动的 16813,给大家的错觉就是这个消费者程序出 bug 了,不消费数据了。最终大家回忆了一下,应该是凌晨的时候打压,产生了大量的积压数据,但是我们的 kafka 12 小时候就会自动清理,然后恰好到了 12 小时还有 16813 条数据没有被消费,就被 kafka 清理线程干掉了,但是 kakfa 记录的消费者的 offset 又确实是 255921,所以就带来了如上错觉。

用一张图来总结一下上述问题:

图 9

由于消费者消费能力不足,导致队列中数据超期被 kafka 清除,进而出现消费进度和队列最大 offset 之间产生了一个比较大的空缺。所以从表象上看,消费者不消费数据了,其实仅仅是数据显示问题,只要你往这个出问题的 partition 中写入一条数据,消费者消费出来就会恢复正常,当前 partition 的 lag 就会变为 0。