sparkStreaming 与fafka直接方式 进行消费者偏移量的保存如redis 里面 避免代码改变与节点重启后的数据丢失与序列化问题
import java.util import kafka.common.TopicAndPartition
import kafka.message.MessageAndMetadata
import kafka.serializer.StringDecoder
import org.apache.spark.SparkConf
import org.apache.spark.rdd.RDD
import org.apache.spark.streaming.dstream.InputDStream
import org.apache.spark.streaming.kafka.{HasOffsetRanges, KafkaUtils, OffsetRange}
import org.apache.spark.streaming.{Duration, StreamingContext}
import redis.clients.jedis.{Jedis, JedisPool, JedisPoolConfig} object KafkaDricteRedis {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("redis").setMaster("local[*]")
val ssc = new StreamingContext(conf,new Duration(5000)) val groupid = "GB01" //组名
val topic = "topic_bc"//topic 名
//在redis中以 groupid/topic作为唯一标识 ,存储分区偏移量
//在Reids 使用的时hash类型来存储
val gtKey = groupid+"/"+topic
//topic
val topics = Set(topic)
//zk地址
val zkQuorum = "hadoop01:2181,hadoop02:2181,hadoop03:2181"
//brokerList
val brokerList = "hadoop04:9092,hadoop05:9092,hadoop06:9092" val kafkaParams = Map(
// metadata.broker.list
"metadata.broker.list"->brokerList,
"group.id"->groupid,
"auto.offset.reset"->kafka.api.OffsetRequest.SmallestTimeString
//从头开始消费
)
//记录topic 、分区对应的偏移量偏移量,在创建InputDStream时作为参数传如
//从这个偏移量开始读取
var fromOffset = Map[TopicAndPartition,Long]()
var kafkaDStream :InputDStream[(String,String)] = null
// 获取一个jedis连接
val conn = getConnection()
// conn.flushDB()
//jd.hget(groupid+topic,"")
//获取全部的keys
val values: util.Set[String] = conn.keys("*")
//println(values)
// [GB01/wordcount3] 分区数 偏移量
//如果keys中包含 GB01/wordcount3这样的key,则表示以前读取过
if(values.contains(gtKey)){
//获取key 为GB01/wordcount3 下面所对应的(k,v) /** conn.hgetAll(gtKey) GB01/wordcount3:
* 1 888
* 2 888
* 3 888
* 4 888
*/
var allKey: util.Map[String, String] = conn.hgetAll(gtKey)
//导入后,可以把Java中的集合转换为Scala中的集合
import scala.collection.JavaConversions._
var list: List[(String, String)] = allKey.toList
//循环得到的(k,v)
//这里面的 k 对应的是分区, v对应的是偏移量
for (key <- list){ //这里的key是一个tuple类型
//new一个TopicAndPartition 把 topic 和分区数传入
val tp = new TopicAndPartition(topic,key._1.toInt)
//把每个topic 分区 对应的偏移量传入
fromOffset += tp -> key._2.toLong
println("分区"+key._1+"偏移量为"+key._2)
}
//这里的是把数据(key ,value)是kafka 的key默认是null,
//value 是kafka中的value
val messageHandler =(mmd:MessageAndMetadata[String,String])=>{
( mmd.key(),mmd.message())
}
//创建一个InputDStream
kafkaDStream= KafkaUtils.createDirectStream[String,String,StringDecoder,StringDecoder,(String,String)](ssc,
kafkaParams,fromOffset,messageHandler)
}else{
//如果以前没有读取过,创建一个新的InputDStream
kafkaDStream= KafkaUtils.createDirectStream[String,String,StringDecoder,StringDecoder](
ssc,kafkaParams,topics
) }
//用来更新偏移量,OffsetRange中可以获取分区及偏移量
var OffsetRangs = Array[OffsetRange]()
//
kafkaDStream.foreachRDD(kafkaRDD=> {
//这里面的RDD是kafkaRDD ,可以转换为HasOffsetRange
val ranges = kafkaRDD.asInstanceOf[HasOffsetRanges]
// 获取分区信息的集合
OffsetRangs = ranges.offsetRanges
//获取value,(key 默认是null,没有用)
val map: RDD[String] = kafkaRDD.map(_._2)
map.foreach(x=>print("")) //更新偏移量
for (o <- OffsetRangs){
//取出偏移量
val offset = o.untilOffset
//取出分区
val partition = o.partition
println("partition: "+partition)
println("offset: "+offset)
//把通过hset,把对应的partition和offset写入到redis中
conn.hset(gtKey,partition.toString,offset.toString)
}
}) ssc.start()
ssc.awaitTermination() }
//Jedis连接池
def getConnection(): Jedis ={
//new 一个JedisPoolConfig,用来设定参数
val conf = new JedisPoolConfig()
val pool = new JedisPool(conf,"192.168.121.12",6379)
//最大连接数
conf.setMaxTotal(20)
//最大空闲数
conf.setMaxIdle(20) val jedis = pool.getResource()
//密码
jedis.auth("test123")
jedis }
sparkStreaming 与fafka直接方式 进行消费者偏移量的保存如redis 里面 避免代码改变与节点重启后的数据丢失与序列化问题的更多相关文章
- UserView--第二种方式(避免第一种方式Set饱和),基于Spark算子的java代码实现
UserView--第二种方式(避免第一种方式Set饱和),基于Spark算子的java代码实现 测试数据 java代码 package com.hzf.spark.study; import ...
- -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中
本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait( ...
- Linux服务器重启后IP变掉的处理方式
工作中有一台服务器为物理机,重启后IP就变掉了,影响到了使用,于是将服务器上的IP配置为静态方式,问题得以解决,具体如下: 1.登陆Linux服务器,cd /etc/sysconfig/network ...
- sparkStreaming消费kafka-0.8方式:direct方式(存储offset到zookeeper)
生产中,为了保证kafka的offset的安全性,并且防止丢失数据现象,会手动维护偏移量(offset) 版本:kafka:0.8 其中需要注意的点: 1:获取zookeeper记录的分区偏移量 2: ...
- Kafka连接SparkStreaming的两种方式
第一种方式代码: import org.apache.spark.storage.StorageLevel import org.apache.spark.{HashPartitioner, Spar ...
- rocketmq 以广播方式实现消费者消费消息
package com.bfxy.rocketmq.model; import java.util.List; import org.apache.rocketmq.client.consumer.D ...
- 利用反射快速给Model实体赋值 使用 Task 简化异步编程 Guid ToString 格式知多少?(GUID 格式) Parallel Programming-实现并行操作的流水线(生产者、消费者) c# 无损高质量压缩图片代码 8种主要排序算法的C#实现 (一) 8种主要排序算法的C#实现 (二)
试想这样一个业务需求:有一张合同表,由于合同涉及内容比较多所以此表比较庞大,大概有120多个字段.现在合同每一次变更时都需要对合同原始信息进行归档一次,版本号依次递增.那么我们就要新建一张合同历史表, ...
- session 加入redis的实现代码方式
session,中文经常翻译为会话,其本来的含义是 指有始有终的一系列动作/消息,比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session.有时候我们可以看到这样的话&quo ...
- 初探内联方式的 onload="doSomething()"为何要加"()"?而js代码的 onload="doSomething" 和 addEventListener 为何不加"()"?
问题引入:在看<Jquery基础教程>第四版的时,P34页有这样一段话 引用函数与调用函数 这里在将函数指定为处理程序时,省略了后面的圆括号,只使用了函数名.如果带着圆括号,函数会被立即调 ...
随机推荐
- ganglia-gmond.conf配置文件
运行下列命令可以生成gmond默认配置文件: User@host:$ gmond -t 配置文件由大括弧括起来的几个section组成.这些section可以粗略划分为两个逻辑分类.第一类中的sect ...
- Java编程常见缺陷汇总(一)
[案例1] public boolean equalNode(JudgeNode a, JudgeNode b) { return a.getId() == b.getId(); } [点评] 应在 ...
- Spring Security http标签的use-expressions="true"属性
如果声明为true,那么在access属性要用hasRole()这样写: <intercept-url pattern="/secure/extreme/**" access ...
- Skip the Class
BestCoder Round #92 Skip the Class Accepts: 678 Submissions: 1285 Time Limit: 2000/1000 MS (Java/ ...
- mac shell 获取ip,自动启动文件http服务
因为工作原因,时常有文件传输需求. rz.nc.rsync都用过,各有各的好处. 但相对的,向别处推文件时总有各种麻烦,尤其是在给同事发送文件时. 然后就想到了提供http服务. 在环境变量中定义别名 ...
- 三、CSS语言
CSS语言 1.概述:CSS (Cascading Style Sheets)是层叠样式表用来定义网页的显示效果.可以解决html代码对样式定义的重复,提高了后期样式代码的可维护性,并增强了网页的显示 ...
- 有关apk打包的东西最近正在整理
下周将会呈现给大家完整的一套打包流程. {‘敬请期待’,}
- javascript的数组之sort()
sort()方法用in-place的算法对原数组进行排序,但不会产生新的数组.这个方法不是一个稳定的排序,默认采用的是安字符串Unicode码点进行排序的. let fruit = ['cherri ...
- Intellij IDEA 生成返回值对象快捷键
在编写一行JAVA语句时,有返回值的方法已经决定了返回对象的类型和泛型类型,我们只需要给这个对象起个名字就行. 如果使用快捷键生成这个返回值,我们就可以减少不必要的打字和思考,专注于过程的实现. 步骤 ...
- Java 实现 AES 加解密
毕业课题中需要使用加解密算法,要求加解密前后的数据长度不会变化,查了一些资料,发现可以采用AES加密的CFB跟OFB模式是无填充的模式,可以保持加解密前后数据的长度相等.下面上代码: import j ...