kafka日志清理引发的core dump问题

​ 团队开发了kafka on hdfs的功能,用以将kafka数据存储在hdfs上,但是在使用的过程中发现,有机器出现core dump现象。

本文基于kafka版本0.10.2

排查过程

一、排查core dump文件

由于出现了多次core dump问题,所以首先需要从core dump文件中进行分析。从core dump文件可以看出,以下几个问题:

  1. 挂掉的线程名称都是hdfs相关的,所以推测与hdfs相关功能有关
  2. 挂掉的代码位置都与index读取逻辑有关,所以推测和index清理逻辑有关

case1

case2

二、分析代码

​ 分析kafka本地日志删除的代码发现,本地日志删除通过asyncDeleteSegment进行,asyncDeleteSegment进行删除时首先会rename本地日志文件和索引文件,然后延迟一定时间进行删除。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/** a file that is scheduled to be deleted */
val DeletedFileSuffix = ".deleted"


/**
* Perform an asynchronous delete on the given file if it exists (otherwise do nothing)
*
* @throws KafkaStorageException if the file can't be renamed and still exists
*/
private def asyncDeleteSegment(segment: LogSegment) {
segment.changeFileSuffixes("", Log.DeletedFileSuffix)
def deleteSeg() {
info("Deleting segment %d from log %s.".format(segment.baseOffset, name))
segment.delete()
}
scheduler.schedule("delete-file", deleteSeg, delay = config.fileDeleteDelayMs)
}


/**
* Change the suffix for the index and log file for this log segment
*/
def changeFileSuffixes(oldSuffix: String, newSuffix: String) {

def kafkaStorageException(fileType: String, e: IOException) =
new KafkaStorageException(s"Failed to change the $fileType file suffix from $oldSuffix to $newSuffix for log segment $baseOffset", e)

try log.renameTo(new File(CoreUtils.replaceSuffix(log.file.getPath, oldSuffix, newSuffix)))
catch {
case e: IOException => throw kafkaStorageException("log", e)
}
try index.renameTo(new File(CoreUtils.replaceSuffix(index.file.getPath, oldSuffix, newSuffix)))
catch {
case e: IOException => throw kafkaStorageException("index", e)
}
try timeIndex.renameTo(new File(CoreUtils.replaceSuffix(timeIndex.file.getPath, oldSuffix, newSuffix)))
catch {
case e: IOException => throw kafkaStorageException("timeindex", e)
}
}

​ 但是在hdfs相关的清理功能中,直接进行的日志清理而没有rename和delay操作,所以推测清理日志和索引时,如果文件仍被读取,强行删除会导致core dump。

三、测试结论

编写单测,本地索引lookup过程中强行删除索引文件,确实出现了core dump现象。

解决方案

仿照本地日志的清理策略,在hdfs相关的逻辑中,不直接删除文件,而是先rename文件,然后再延迟一定时间进行删除。

总结

  1. 本次问题的出现属于偶发现象,只有在kafka consumer消费lag,读取即将被删除的日志时才有可能会发生。
  2. core dump问题分析的过程中需要通过多个case的相似点来分析问题。