有很多小伙伴不知道Kafka的偏移量说的到底是什么,导致使用它的时候迷迷糊糊的,现在我给大家用最简单的方式说说这个东西到底是什么
首先偏移量是一个比较官方的说法,其实它就是两个数字,一个表示这当前数据消费的位置,另一个代表着数据量最大位置,我在网上随便找了一个kafka0.10以后自带的偏移量维护脚本所展示的信息,大家看一下,让大家先从最源头的kafka端看一下偏移量到底长的是什么样的字

如上图展示的信息当中详细的展示了消费者组对应一个主题下所有分区的偏移量,以及对应的消费者线程,其中我们重点看CURRENT-OFFSET和LOG-END-OFFSET
CURRENT-OFFSET指的就是现在对应的消费者线程消费到了多少条数据,而LOG-END-OFFSET是该分区总计有多少条数据
而我们通常在使用kafka的时候,要关注偏移量常常出现在要手动维护的时候,如果是自动维护那么根本不用我们操行,kafka自己和其他框架融合的时候早就把一切考虑好了,那么我们现在的问题来了,自己手动维护说的底维护的是什么,我写了一个spark代码大家看一下
import org.apache.kafka.common.serialization.StringDeserializer
import org.apache.spark.{SparkConf, TaskContext}
import org.apache.spark.streaming.kafka010.{CanCommitOffsets, HasOffsetRanges, KafkaUtils}
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.streaming.kafka010.LocationStrategies.PreferConsistent
import org.apache.spark.streaming.kafka010.ConsumerStrategies.Subscribe
object StreamFromKafka {
def main(args: Array[String]): Unit = {
//前面的可以不用看,就是正常的流计算
val conf = new SparkConf().setAppName("StreamWordCount").setMaster("local[2]")
val sc = new StreamingContext(conf,Seconds(10))
sc.sparkContext.setLogLevel("ERROR")
val kafkaParams = Map[String, Object](
"bootstrap.servers" -> "192.168.182.149:9092,192.168.182.147:9092,192.168.182.148:9092",
"key.deserializer" -> classOf[StringDeserializer],
"value.deserializer" -> classOf[StringDeserializer],
"group.id" -> "group1",
"enable.auto.commit" -> (false: java.lang.Boolean) //将提交设置成手动提交false,默认true,自动提交到kafka,如果你想手动提交,这里一定要false,不然下面的自动提交代码不会生效的
)
/**
* LocationStrategies.PreferBrokers() 仅仅在你 spark 的 executor 在相同的节点上,优先分配到存在 kafka broker 的机器上;
* LocationStrategies.PreferConsistent(); 大多数情况下使用,一致性的方式分配分区所有 executor 上。(主要是为了分布均匀)
* 新的Kafka使用者API将预先获取消息到缓冲区。因此,出于性能原因,Spark集成将缓存的消费者保留在执行程序上(而不是为每个批处理重新创建它们),并且更喜欢在具有适当使用者的主机位置上安排分区,这一点很重要。
*在大多数情况下,您应该使用LocationStrategies.PreferConsistent,如上所示。这将在可用执行程序之间均匀分配分区。如果您的执行程序与Kafka代理在同一主机上,请使用PreferBrokers,它更愿意为该分区安排Kafka领导者的分区。
*/
val topics = Array("test")
val stream = KafkaUtils.createDirectStream[String, String](
sc,
PreferConsistent,
Subscribe[String, String](topics, kafkaParams)
)
val kafkaStream = stream.map(record => (record.key, record.value))
stream.foreachRDD(rdd =>{
//此处获取当前rdd中分区的offset值
val offsetRanges = rdd.asInstanceOf[HasOffsetRanges].offsetRanges
rdd.foreachPartition(partitions =>{
//此处将的遍历分区,通过TaskContext类得到每个分区的标识从而获取fromOffset和untilOffset
val o = offsetRanges(TaskContext.get().partitionId())
//打印到控制台可以明了的查看offset值
println(o.fromOffset+"- - - 偏移量- - - - - - - "+o.untilOffset)
//这里就是业务中怎么处理offset了,也可以处理数据
partitions.foreach(line =>{
//将分区中数据的key,value值打印到控制台,注意这里是从kafka中刚拿到的数据所以是key value形式
println("key"+line.key()+"...........value"+line.value())
})
})
//手动提交处理后的offset值到kafka
stream.asInstanceOf[CanCommitOffsets].commitAsync(offsetRanges)
})
val words = kafkaStream.flatMap(_._2.split(" "))
val pairs = words.map { x => (x,1) }
val wordCounts = pairs.reduceByKey(_+_)
wordCounts.print()
sc.start()
sc.awaitTermination()
}
}
我在代码运行之后在kafka生产者端输入了如下的数据,数字是测试通信的不用管,主要是后面输入的字母

结果如下

不难发现,在程序开始的时候先打印出了当前偏移量状态,消费数据量和最大数据量都在343,而我输入数据之后,下一次计算时明显偏移量增加了3个,之所以我哪里还有显示的343,是因为343-346那条打印数据,我打印的是拉取到的数据在kafka中的偏移量范围,也可以说是拉取到的数据的数据边界,之后打印的就是我在代码中的读取初步拉取到的数据,以及计算的结果,在最后偏移量又展示了最新的状态346
而我们手动维护时最核心的是维护分区以及和分区对应的当前消费量,当然这两个是最重要的,因为手动维护偏移量核心就是这两个数据,要靠这两个数据决定读取的起点,有的地方可能也会还会多维护其他的
现在普遍的手段是维护在zookeeper或者mysql里面,想了解如何操作的可以看我之前发的博文SparkStreaming消费Kafka数据手动提交偏移量维护在自定义环境的方式
我在此最后想要告诉大家的是,之所以我在开头给大家展示的是kafka自身源头的偏移量信息,是因为我想让大家知道,kafka自身保存的偏移量信息是最全最方便维护的,这也是kafka0.10之后把偏移量改成自己维护的原因,因为0.10之前偏移量信息没有一个全面的维护平台,比如最大数据量那个时候只能靠消费完成为止来等价的猜测
说的有些远了,回归正题,我想告诉大家的就是你在其他渠道读取到的偏移量,有超级大的可能只有重要信息,比如zookeeper中只是保留了当前消费量,分区还是用文件名来代替的,如下图

所以大家在自己手动维护的时候一定要知道自己能拿到什么,维护的又是什么
Kafka的偏移量是记录消费者数据消费位置的关键指标。CURRENT-OFFSET表示当前消费的位置,LOG-END-OFFSET是分区总数据量。手动维护偏移量通常涉及分区和消费量的跟踪,常见于Spark等框架与Kafka集成时。维护可在Zookeeper或MySQL中进行,但Kafka自身保存的偏移量信息更全面。手动维护时需明确可获取信息,如Zookeeper仅保存当前消费量,分区信息可能简化。

5480

被折叠的 条评论
为什么被折叠?



