Kafka如何加载日志段

kafka日志作为日志段的容器,重点分析kafka日志是如何加载日志段。

Log源码结构

  Log源码位于kakfa core工程的log包下,对应的文件名为Log.scala。文件中中包含了与log有关的10个class或者object,见下图所示。

  

 

 

  模块概述

  LogAppendInfo(class)

    保存了一组待写入消息的各种元数据信息,包含位移值或者最大消息的时间戳等,后续会进行详细介绍

  LogAppendInfo(object)

    我们可以理解为定义了一些工厂方法,用来创建LogAppendInfo对象

  Log(class)

    Log源码中最最核心的代码

  Log(object)

    Log伴生类的工厂方法,里面有很多的辅助方法

  RollParams(C)

    定义了日志段是否需要切分的数据结构

  RollParams(object)

    RollParams的伴生类

  LogMetricNames

    定义了Log对象的监控指标

  LogOffsetSnapshot

    封装分区所有位移元数据的容器类

  LogReadInfo

    封装读取日志返回的数据和元数据

  CompletedTxn

    记录已完成事务的元数据,用来构建事务索引

  Log Class&Log Object

    下面我会一一介绍他们,我们都知道Scala的派生类一般存储的是静态变量或者静态工厂方法等,考虑到派生类的阅读比较容易,我们先分析下Log Object相关信息。我们先看下里面都定义了那些常量,见下图所示

    

object Log {

  /** a log file */
  val LogFileSuffix = ".log"

  /** an index file */
  val IndexFileSuffix = ".index"

  /** a time index file */
  val TimeIndexFileSuffix = ".timeindex"

  val ProducerSnapshotFileSuffix = ".snapshot"

  /** an (aborted) txn index */
  val TxnIndexFileSuffix = ".txnindex"

  /** a file that is scheduled to be deleted */
  val DeletedFileSuffix = ".deleted"

  /** A temporary file that is being used for log cleaning */
  val CleanedFileSuffix = ".cleaned"

  /** A temporary file used when swapping files into the log */
  val SwapFileSuffix = ".swap"

  /** Clean shutdown file that indicates the broker was cleanly shutdown in 0.8 and higher.
   * This is used to avoid unnecessary recovery after a clean shutdown. In theory this could be
   * avoided by passing in the recovery point, however finding the correct position to do this
   * requires accessing the offset index which may not be safe in an unclean shutdown.
   * For more information see the discussion in PR#2104
   */
  val CleanShutdownFile = ".kafka_cleanshutdown"

  /** a directory that is scheduled to be deleted */
  val DeleteDirSuffix = "-delete"

  /** a directory that is used for future partition */
  val FutureDirSuffix = "-future"
}

  我们发现这些常量 中包含了很多种的文件类型,除了大家熟知的index、timeindex、txnindex、log等,还有不认识的其他文件类型,我们对这些不认识的进行汇总说明。

  snapshot:是kafka对幂等型或者事务型producer所生成的快照文件。事务型幂等先不做介绍。

  deleted:删除日志段操作时所创建的文件,目前删除日志段文件的操作是异步的,

  cleaned和swarp是compaction操作的产物,后续会进行解释

  delete 是应用于文件夹的,当我们删除一个主题的时候,主题的分区文件夹会被加上这个后缀

  当然Log object中还定义了很多的工具类方法,比如下图,基于偏移量计算出日志段的文件名,kafak日志段的固定长度是20位。

  

/**
   * Make log segment file name from offset bytes. All this does is pad out the offset number with zeros
   * so that ls sorts the files numerically.
   *
   * @param offset The offset to use in the file name
   * @return The filename
   */
  def filenamePrefixFromOffset(offset: Long): String = {
    val nf = NumberFormat.getInstance()
    nf.setMinimumIntegerDigits(20)
    nf.setMaximumFractionDigits(0)
    nf.setGroupingUsed(false)
    nf.format(offset)
  }

  Log class 详细介绍

   Log源码中最重要的就是这个Log class了,代码量还是比较大的,我们先从这个类定义的入参开始讲起,见下图所示。

  

class Log(@volatile private var _dir: File,
          @volatile var config: LogConfig,
          @volatile var logStartOffset: Long,
          @volatile var recoveryPoint: Long,
          scheduler: Scheduler,
          brokerTopicStats: BrokerTopicStats,
          val time: Time,
          val maxProducerIdExpirationMs: Int,
          val producerIdExpirationCheckIntervalMs: Int,
          val topicPartition: TopicPartition,
          val producerStateManager: ProducerStateManager,
          logDirFailureChannel: LogDirFailureChannel) extends Logging with KafkaMetricsGroup {
        .......
}    

  我们发现这里面的字段比较多,重点关注以下两个字段,分别是dir和logStartOffset。

  dir是主题分区的路径

  logStartOffset是日志的最早的位移

  此外我们还需要关注一下几个属性

  nextOffsetmetadata:封装了下一条待插入消息的位移值

  highWatermarkMetadata:用来区分日志的高水位值,即已提交事务和未提交事务的分界

  segment:保存了分区日志下所有的日志段信息,Map结构,key是日志段的起始位移,value是日志段本身对象

  大概了解了上文之后,我们一起看看Log类是如何初始化的。

 

posted @ 2020-04-19 15:08  cnxieyang  阅读(846)  评论(0编辑  收藏  举报
联系邮箱:cnxieyang@163.com