kafka 副本同步-Leader处理fetch请求

KafkaApi.handleFetchRequest
//拉取数据
      replicaManager.fetchMessages
    //  从本地的磁盘里面去读取日志信息
    val logReadResults = readFromLocalLog
  def readFromLocalLog(fetchOnlyFromLeader: Boolean,
                       readOnlyCommitted: Boolean,
                       fetchMaxBytes: Int,
                       hardMaxBytesLimit: Boolean,
                       readPartitionInfo: Seq[(TopicAndPartition, PartitionFetchInfo)],
                       quota: ReplicaQuota): Seq[(TopicAndPartition, LogReadResult)] = {

    //一个分区一个分区去读取的
    readPartitionInfo.foreach { case (tp, fetchInfo) =>
      //TODO 调用read方法
      val readResult = read(tp, fetchInfo, limitBytes, minOneMessage)
      val messageSetSize = readResult.info.messageSet.sizeInBytes
      // Once we read from a non-empty partition, we stop ignoring request and partition level size limits
      if (messageSetSize > 0)
        minOneMessage = false
      limitBytes = math.max(0, limitBytes - messageSetSize)
      result += (tp -> readResult)
    }

   // 调用read方法
-> val readResult = read(tp, fetchInfo, limitBytes, minOneMessage)
    def read(tp: TopicAndPartition, fetchInfo: PartitionFetchInfo, limitBytes: Int, minOneMessage: Boolean): LogReadResult = {
      val TopicAndPartition(topic, partition) = tp
      val PartitionFetchInfo(offset, fetchSize) = fetchInfo

      BrokerTopicStats.getBrokerTopicStats(topic).totalFetchRequestRate.mark()
      BrokerTopicStats.getBrokerAllTopicsStats().totalFetchRequestRate.mark()

      try {
        trace(s"Fetching log segment for partition $tp, offset ${offset}, partition fetch size ${fetchSize}, " +
          s"remaining response limit ${limitBytes}" +
          (if (minOneMessage) s", ignoring response/partition size limits" else ""))

        // decide whether to only fetch from leader
        //获取到leader partition
        val localReplica = if (fetchOnlyFromLeader)
          getLeaderReplicaIfLocal(topic, partition)
        else
          getReplicaOrException(topic, partition)

        // decide whether to only fetch committed data (i.e. messages below high watermark)
        val maxOffsetOpt = if (readOnlyCommitted)
          Some(localReplica.highWatermark.messageOffset)
        else
          None

        /* Read the LogOffsetMetadata prior to performing the read from the log.
         * We use the LogOffsetMetadata to determine if a particular replica is in-sync or not.
         * Using the log end offset after performing the read can lead to a race condition
         * where data gets appended to the log immediately after the replica has consumed from it
         * This can cause a replica to always be out of sync.
         */
        val initialLogEndOffset = localReplica.logEndOffset
        val logReadInfo = localReplica.log match {
          case Some(log) =>
            val adjustedFetchSize = math.min(fetchSize, limitBytes)

            // Try the read first, this tells us whether we need all of adjustedFetchSize for this partition
            //TODO 通过log对象去读取数据
            val fetch = log.read(offset, adjustedFetchSize, maxOffsetOpt, minOneMessage)

//TODO 通过log对象去读取数据
--> val fetch = log.read(offset, adjustedFetchSize, maxOffsetOpt, minOneMessage)
     //TODO 核心代码,通过segment读取磁盘上面的数据
      val fetchInfo = entry.getValue.read(startOffset, maxOffset, maxLength, maxPosition, minOneMessage)
      
--->     //TODO log.read
    FetchDataInfo(offsetMetadata, log.read(startPosition.position, length),
      firstMessageSetIncomplete = adjustedMaxSize < messageSetSize)
        def read(position: Int, size: Int): FileMessageSet = {
    if(position < 0)
      throw new IllegalArgumentException("Invalid position: " + position)
    if(size < 0)
      throw new IllegalArgumentException("Invalid size: " + size)

    //最后返回的就是这样的一个对象,FileMessageSet,里面封装的就是我们要读取的信息
    //要抓去的信息。
    new FileMessageSet(file,
                       channel,
                       //拉取数据的时候,起始位置
                       start = this.start + position,
                       //结束位置
                       end = {
                         // Handle the integer overflow
                         if (this.start + position + size < 0)
                           sizeInBytes()
                         else
                           math.min(this.start + position + size, sizeInBytes())
                       })
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
kafka是一个分布式的流处理平台,它可以处理和存储大规模的实时数据流。kafka-run-class是kafka提供的一个脚本工具,用于在命令行中执行指定的类。kafka.tools.GetOffsetShell是用于获取指定topic在指定时间点的偏移量信息的工具。 具体来说,kafka.tools.GetOffsetShell通过指定topic、时间点和broker列表来获取该topic在指定时间点的偏移量。它的用法类似于以下命令: ``` bin/kafka-run-class.sh kafka.tools.GetOffsetShell --topic <topic> --time <timestamp> --broker-list <broker-list> --partitions <partitions> ``` 其中,<topic>是要查询的topic名称,<timestamp>是要查询的时间点,<broker-list>是broker的地址列表,<partitions>是要查询的分区编号。该命令会返回指定topic在指定时间点的偏移量信息。 另外,kafka.tools.ConsumerOffsetChecker是kafka提供的另一个工具,用于检查消费者的偏移量信息。它可以通过指定zookeeper连接、消费者组和topic来获取消费者的偏移量信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [kafka监控命令kafka-run-class.sh查看消费了多少条数据](https://blog.csdn.net/m0_37739193/article/details/73849523)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [kafka_2.9.2-0.8.2.1.tgz](https://download.csdn.net/download/shy_snow/9372309)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值