Uploaded image for project: 'Kafka'
  1. Kafka
  2. KAFKA-881

Kafka broker not respecting log.roll.hours

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Major
    • Resolution: Won't Fix
    • 0.7.2
    • None
    • log
    • None

    Description

      We are running Kafka 0.7.2. We set log.roll.hours=1. I hoped that meant logs would be rolled every hour, or more. Only, sometimes logs that are many hours (sometimes days) old have more data added to them. This perturbs our systems for reasons I won't get in to.

      I don't know Scala or Kafka well, but I have proposal for why this might happen: upon restart, a broker forgets when its log files have been appended to ("firstAppendTime"). Then a potentially infinite amount of time later, the restarted broker receives another message for the particular (topic, partition), and starts the clock again. It will then roll over that log after an hour.

      https://svn.apache.org/repos/asf/kafka/branches/0.7/core/src/main/scala/kafka/server/KafkaConfig.scala says:

      /* the maximum time before a new log segment is rolled out */
      val logRollHours = Utils.getIntInRange(props, "log.roll.hours", 24*7, (1, Int.MaxValue))

      https://svn.apache.org/repos/asf/kafka/branches/0.7/core/src/main/scala/kafka/log/Log.scala has maybeRoll, which needs segment.firstAppendTime defined. It also has updateFirstAppendTime() which says if it's empty, then set it.

      If my hypothesis is correct about why it is happening, here is a case where rolling is longer than an hour, even on a high volume topic:

      • write to a topic for 20 minutes
      • restart the broker
      • wait for 5 days
      • write to a topic for 20 minutes
      • restart the broker
      • write to a topic for an hour

      The rollover time was now 5 days, 1 hour, 40 minutes. You can make it as long as you want.

      Proposed solution:

      The very easiest thing to do would be to have Kafka re-initialized firstAppendTime with the file creation time. Unfortunately, there is no file creation time in UNIX. There is ctime, change time, updated when a file's inode information is changed.

      One solution is to embed the firstAppendTime in the filename (say, seconds since epoch). Then when you open it you could reset firstAppendTime to exactly what it really was. This ignores clock drift or resetting. One could set firstAppendTime to min(filename-based time, current time).

      A second solution is to make the Kafka log roll over at specific times, regardless of when the file was created. Conceptually, time can be divided into windows of size log.rollover.hours since epoch (UNIX time 0, 1970). So, when firstAppendTime is empty, compute the next rollover time (say, next = (hours since epoch) % (log.rollover.hours) + log.rollover.hours). If the file mtime (last modified) is before the current rollover window ( (next-log.rollover.hours) .. next ), roll it over right away. Otherwise, roll over when you cross next, and reset next.

      A third solution (not perfect, but an approximation at least) would be to not to write to a segment if firstAppendTime is not defined and the timestamp on the file is more than log.roll.hours old.

      There are probably other solutions.

      Attachments

        1. kafka-roll-0.8.patch
          21 kB
          Sam Meder
        2. kafka-roll.again.patch
          5 kB
          Dan F
        3. kafka_roll.patch
          6 kB
          Dan F

        Activity

          People

            jkreps Jay Kreps
            dfrankow1 Dan F
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: