spark streaming中维护kafka偏移量到外部介质

以kafka偏移量维护到redis为例。

redis存储格式

使用的数据结构为string,其中key为topic:partition,value为offset

例如bobo这个topic下有3个分区,则key-value结构如下:

  • bobo:0的偏移量为x
  • bobo:1的偏移量为y
  • bobo:2的偏移量为z

消费时指定offset

主要是如下两个方法:

  • createKafkaStream()创建kakfa流
  • getOffsets()从redis中获取offsets
/**
* kakfa参数
*/
private val kafkaParams = Map[String, Object](
"bootstrap.servers" -> "crpprdap25:6667,crpprdap26:6667,crpprdap27:6667",
"key.deserializer" -> classOf[StringDeserializer],
"value.deserializer" -> classOf[StringDeserializer],
"group.id" -> "use_a_separate_group_id_for_each_stream",
// 注意这里是none。
"auto.offset.reset" -> "none",
"enable.auto.commit" -> (false: java.lang.Boolean)
) // `bobo`topic下有3个分区
private val topicPartitions = Map[String, Int]("bobo" -> 3) // 从redis中获取offsets
def getOffsets: Map[TopicPartition, Long] = {
val jedis = InternalRedisClient.getResource // 设置每个分区起始的offset
val offsets = mutable.Map[TopicPartition, Long]() topicPartitions.foreach { it =>
val topic = it._1
val partitions = it._2
// 遍历分区,设置每个topic下对应partition的offset
for (partition <- 0 until partitions) {
val topicPartitionKey = topic + ":" + partition
var lastOffset = 0L
val lastSavedOffset = jedis.get(topicPartitionKey) if (null != lastSavedOffset) {
try {
lastOffset = lastSavedOffset.toLong
} catch {
case e: Exception =>
log.error("get lastSavedOffset error", e)
System.exit(1)
}
}
log.info("from redis topic: {}, partition: {}, lastOffset: {}", topic, partition, lastOffset) // 添加
offsets += (new TopicPartition(topic, partition) -> lastOffset)
}
} InternalRedisClient.returnResource(jedis) offsets.toMap
} /**
* 创建kakfa流
*
* @param ssc StreamingContext
* @return InputDStream
*/
def createKafkaStream(ssc: StreamingContext): InputDStream[ConsumerRecord[String, String]] = {
val offsets = getOffsets // 创建kafka stream
val stream = KafkaUtils.createDirectStream[String, String](
ssc,
LocationStrategies.PreferConsistent,
ConsumerStrategies.Assign[String, String](offsets.keys.toList, kafkaParams, offsets)
)
stream
}

其中:核心是通过ConsumerStrategies.Assign方法来指定topic下对应partitionoffset信息。

更新offset到redis

最后将offset信息维护到redis即可。

/**
* 消费
*
* @param stream InputDStream
*/
def consume(stream: InputDStream[ConsumerRecord[String, String]]): Unit = {
stream.foreachRDD { rdd =>
// 获取offset信息
val offsetRanges = rdd.asInstanceOf[HasOffsetRanges].offsetRanges // 计算相关指标,这里就统计下条数了
val total = rdd.count() val jedis = InternalRedisClient.getResource
val pipeline = jedis.pipelined()
// 会阻塞redis
pipeline.multi() // 更新相关指标
pipeline.incrBy("totalRecords", total) // 更新offset
offsetRanges.foreach { offsetRange =>
log.info("save offsets, topic: {}, partition: {}, offset: {}", offsetRange.topic, offsetRange.partition, offsetRange.untilOffset)
val topicPartitionKey = offsetRange.topic + ":" + offsetRange.partition
pipeline.set(topicPartitionKey, offsetRange.untilOffset + "")
} // 执行,释放
pipeline.exec()
pipeline.sync()
pipeline.close()
InternalRedisClient.returnResource(jedis)
}
}

参考

spark代码

顺便贴一下自己整理的spark相关的代码。

Github地址:spark-programming

主要包括:

  • RDD的基本使用
  • SQL
    • jdbc(读、写)
    • hive(读、写、动态分区)
  • Streaming
    • 消费kafka(手动提交、手动维护offset)
    • 写入HBase
    • 写入Hive

spark streaming中维护kafka偏移量到外部介质的更多相关文章

  1. Spark Streaming中的操作函数分析

    根据Spark官方文档中的描述,在Spark Streaming应用中,一个DStream对象可以调用多种操作,主要分为以下几类 Transformations Window Operations J ...

  2. Spark Streaming中的操作函数讲解

    Spark Streaming中的操作函数讲解 根据根据Spark官方文档中的描述,在Spark Streaming应用中,一个DStream对象可以调用多种操作,主要分为以下几类 Transform ...

  3. flink⼿手动维护kafka偏移量量

    flink对接kafka,官方模式方式是自动维护偏移量 但并没有考虑到flink消费kafka过程中,如果出现进程中断后的事情! 如果此时,进程中段: 1:数据可能丢失 从获取了了数据,但是在执⾏行行 ...

  4. Spark Streaming中向flume拉取数据

    在这里看到的解决方法 https://issues.apache.org/jira/browse/SPARK-1729 请是个人理解,有问题请大家留言. 其实本身flume是不支持像KAFKA一样的发 ...

  5. flink和spark Streaming中的Back Pressure

    Spark Streaming的back pressure 在讲flink的back pressure之前,我们先讲讲Spark Streaming的back pressure.Spark Strea ...

  6. Flink与Spark Streaming在与kafka结合的区别!

    本文主要是想聊聊flink与kafka结合.当然,单纯的介绍flink与kafka的结合呢,比较单调,也没有可对比性,所以的准备顺便帮大家简单回顾一下Spark Streaming与kafka的结合. ...

  7. Spark Streaming中动态Batch Size实现初探

    本期内容 : BatchDuration与 Process Time 动态Batch Size Spark Streaming中有很多算子,是否每一个算子都是预期中的类似线性规律的时间消耗呢? 例如: ...

  8. spark streaming中使用flume数据源

    有两种方式,一种是sparkstreaming中的driver起监听,flume来推数据:另一种是sparkstreaming按照时间策略轮训的向flume拉数据. 最开始我以为只有第一种方法,但是尼 ...

  9. Spark Streaming 实现读取Kafka 生产数据

    在kafka 目录下执行生产消息命令: ./kafka-console-producer  --broker-list nodexx:9092 --topic  201609 在spark bin 目 ...

随机推荐

  1. js下载后台返回的docx(返回格式:文档流)文件

    原文地址: https://www.jianshu.com/p/a81c68c15fbd PS需要指定responseType类型,不然文件内容会乱码哦 咦?文件名乱码?需要手动设置文件名哦↓ 呀,文 ...

  2. 入坑DL CV 一些基础技能学习

    进入实验室学习了一个月左右,记录一下新手入门所学的基本知识,都是入门级别的教程 1.Python 快速入门:廖雪峰Python教程--> https://www.liaoxuefeng.com/ ...

  3. redis集群伸缩【转】

    一:实验介绍 在不影响集群对外服务的情况下,可以为集群添加节点进行扩容,也可以下线部分节点进行缩容. 原理可以抽象为槽和对应数据在不同节点之间灵活移动. 如果希望加入一个节点来实现集群扩容时,需要通过 ...

  4. Mac 与 windows eclipse 快捷键对照

      Mac windows 方法注释 option+command+j alt+shift+j 在方法里上右击,source -> Generate Element Comment 删除当前行 ...

  5. luoguP1373 小a和uim之大逃离

    DP专题 题目链接 思路 \(f[i][j][a][b][0/1]\)表示在\((i,j)\)这个格子,小a有a滴魔液,他的伙伴有b滴,上一步是小a(0)或者他的伙伴(1)吸取的魔液. (显然)数组开 ...

  6. MTV 和 MVC

    MTV:(Django中用) M:models T:templates V:views MVC M:models V:views C:control(urls+views)

  7. vertx的NetServer模块

    启动 public synchronized void listen(Handler<NetSocket> handler, SocketAddress socketAddress, Ha ...

  8. SpringBoot 动态切换多数据源

    1. 配置文件application-dev.properties 2. 动态切换数据源核心 A. 数据源注册器 B. 动态数据源适配器 C. 自定义注解 D. 动态数据源切面     E. 数据源路 ...

  9. git增加子模块

    要拉取GIT代码时,有时候需要拉取多个GIT模块,一起配合使用: 1.下载主模块: git clone -b master http://username:passwd@git.wondershare ...

  10. python-初识python

    一.计算机的初步认识 硬件:内存,主板,CPU,硬盘,显卡,显示器等 内存: 优点:存取速度快 缺点:断电后数据会全部丢失 硬盘: 优点:断电后数据也会永久保存 缺点:存取速度远远慢于内存 1.操作系 ...