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. Redis代码——Python篇

    需要安装的库:redis import redis # 连接数据库 r = redis.StrictRedis(host="localhost", port=6379, passw ...

  2. Spring AOP获取方法的参数名称和参数值

    aop配置: <aop:aspectj-autoproxy expose-proxy="true" /> @Before(value = "execution ...

  3. Python爬虫从入门到进阶(3)之requests的使用

    快速上手(官网地址:http://www.python-requests.org/en/master/user/quickstart/) 发送请求 首先导入Requests模块 import requ ...

  4. Spring Cloud 2-Hystrix DashBoard仪表盘(五)

    Spring Cloud  Hystrix DashBoard  1.监控系统配置 pom.xml application.yml Application.java 2.被监控服务配置 pom.xml ...

  5. 【medium】4. Median of Two Sorted Arrays 两个有序数组中第k小的数

    There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...

  6. 具体分析UGUI中RectTransform

    一:RectTransform 组件 1.Transform 组件是所有的游戏物体必备的一个组件,且不可删除,不可隐藏.就算是一个空物体,也是具备 Transform 组件的. Unity3D4.6 ...

  7. OpenStack—nova组件计算服务

    nova介绍: Nova 是 OpenStack 最核心的服务,负责维护和管理云环境的计算资源.OpenStack 作为 IaaS 的云操作系统,虚拟机生命周期管理也就是通过 Nova 来实现的. 用 ...

  8. thymleaf th:text="|第${user.courseSort}课|" 对于不知道的真的是解渴了

    简单描述:最近再做一个课程管理,列表显示第几课,但是后台传递过来的只是数字0~9,意味着,我得自己拼了ヾ(◍°∇°◍)ノ゙  我最烦的就是这种拼,各种难调,果真和我想的一样,4.5遍了还没出来. 我的 ...

  9. mybatis的xml中sql语句中in的写法(迭代遍历)

    这里使用 foreach标签 <foreach  item="item" collection="listTag" index="index&q ...

  10. 客户端和浏览器都不能连接SVN服务器

    错误提示 1.在对话框中提示 2.在As上提示 Error:svn: E731001: Unable to connect to a repository at URL 'https://XXX/sv ...