SparkStreaming直连方式读取kafka数据,使用MySQL保存偏移量
SparkStreaming直连方式读取kafka数据,使用MySQL保存偏移量
通过MySQL保存kafka的偏移量,完成直连方式读取数据
使用scalikeJDBC,访问数据库。
1. ScalikeJDBC
ScalikeJDBC 是一款Scala 开发者使用的简洁 DB 访问类库,它是基于 SQL 的,使用者只需要关注 SQL 逻辑的编写,所有的数据库操作都交给 ScalikeJDBC。这个类库内置包含了JDBC API,并且给用户提供了简单易用并且非常灵活的 API。并且,QueryDSL(通用查询查询框架)使你的代码类型安全的并且可重复使用。我们可以在生产环境大胆地使用这款 DB 访问类库。
2.配置文件
//配置数据库信息
//使用IDEA,在resources文件夹下新建文件File文件名为application.conf
db.default.driver="com.mysql.jdbc.Driver"
db.default.url="jdbc:mysql://hadoop01:3306/kafkaOffset?characterEncodeing=utf-8"
db.default.user="root"
db.default.password="root"
3.导入依赖的jar包
<!--Maven依赖-->
<!--通过mysql保存偏移量-->
<dependency>
<groupId>com.typesafe</groupId>
<artifactId>config</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.scalikejdbc</groupId>
<artifactId>scalikejdbc_2.11</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.scalikejdbc</groupId>
<artifactId>scalikejdbc-core_2.11</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.scalikejdbc</groupId>
<artifactId>scalikejdbc-config_2.11</artifactId>
<version>2.5.0</version>
</dependency>
4.源码测试
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.KafkaCluster.Err
import org.apache.spark.streaming.kafka.{HasOffsetRanges, KafkaCluster, KafkaUtils, OffsetRange}
import org.apache.spark.streaming.{Duration, StreamingContext}
import scalikejdbc.{DB, SQL}
import scalikejdbc.config.DBs
/*
将偏移量保存到MySQL中
*/
object SparkStreamingOffsetMySql {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("medd").setMaster("local[2]")
val ssc = new StreamingContext(conf,Duration(5000))
//配置一系列基本配置
val groupid = "GPMMCC"
val topic = "mysqlDemo"
val brokerList = "hadoop01:9092,hadoop02:9092,hadoop03:9092"
// val zkQuorum = "hadoop01:2181,hadoop02:2181,hadoop03:2181"
val topics = Set(topic)
//设置kafka的参数
val kafkaParams = Map(
"metadata.broker.list"->brokerList,
"group.id"->groupid,
"auto.offset.reset"->kafka.api.OffsetRequest.SmallestTimeString
)
//加载配置 application.conf
DBs.setup()
//不需要查询zk中的offset啦,直接查询MySQL中的offset
val fromdbOffset:Map[TopicAndPartition,Long]=
DB.readOnly{
implicit session=>{
//查询每个分组下面的所有消息
SQL(s"select * from offset where groupId = '${groupid}'" +
//将MySQL中的数据赋值给元组
s"").map(m=>(TopicAndPartition(m.string("topic"),m.string("partitions").toInt),m.string("untilOffset").toLong))
.toList().apply()
}.toMap //最后toMap ,应为前面的返回值已经给定
}
//创建一个DStream,用来获取数据
var kafkaDStream : InputDStream[(String,String)] = null
//从MySql中获取数据进行判断
if(fromdbOffset.isEmpty){
kafkaDStream = KafkaUtils.createDirectStream[String,String,StringDecoder,
StringDecoder](ssc,kafkaParams,topics)
}else{
//1\ 不能重复消费
//2\ 保证偏移量
var checkOffset = Map[TopicAndPartition,Long]()
//加载kafka的配置
val kafkaCluster = new KafkaCluster(kafkaParams)
//首先获得kafka中的所有的topic和partition Offset
val earliesOffset: Either[Err, Map[TopicAndPartition, KafkaCluster.LeaderOffset]
] = kafkaCluster.getEarliestLeaderOffsets(fromdbOffset.keySet)
//然后开始比较大小,用mysql中的offset和kafka中的offset进行比较
if(earliesOffset.isRight){
//去到需要的 大Map
//物取值
val tap: Map[TopicAndPartition, KafkaCluster.LeaderOffset] =
earliesOffset.right.get
//比较,直接进行比较大小
val checkOffset = fromdbOffset.map(f => {
//取kafka中的offset
//进行比较,不需要重复消费,取最大的
val KafkatopicOffset = tap.get(f._1).get.offset
if (f._2 > KafkatopicOffset) {
f
} else {
(f._1, KafkatopicOffset)
}
})
checkOffset
}
val messageHandler=(mmd:MessageAndMetadata[String,String])=>{
(mmd.key(),mmd.message())
}
//不是第一次启动的话 ,按照之前的偏移量取数据的偏移量
kafkaDStream = KafkaUtils.createDirectStream[String,String,StringDecoder
,StringDecoder,(String,String)](ssc,kafkaParams,checkOffset
,messageHandler)
}
var offsetRanges = Array[OffsetRange]()
kafkaDStream.foreachRDD(kafkaRDD=>{
offsetRanges = kafkaRDD.asInstanceOf[HasOffsetRanges].offsetRanges
val map: RDD[String] = kafkaRDD.map(_._2)
map.foreach(println)
//更新偏移量
DB.localTx(implicit session =>{
//去到所有的topic partition offset
for (o<- offsetRanges){
/*SQL("update offset set groupId=? topic=?,partition=?," +
"untilsOffset=?").bind(groupid,o.topic,o.partition,o.untilOffset).update().apply()*/
SQL("replace into offset(groupId,topic,partitions,untilOffset) values(?,?,?,?)").bind(
groupid,o.topic,o.partition.toString,o.untilOffset.toString
).update().apply()
}
})
})
ssc.start()
ssc.awaitTermination()
}
}
SparkStreaming直连方式读取kafka数据,使用MySQL保存偏移量的更多相关文章
- Java基础知识强化之网络编程笔记16:Android网络通信之 使用Http的Get方式读取网络数据(基于HTTP通信技术)
使用Http的Get方式读取网络数据,使用Get方式与网络通信是最常见的Http通信,建立链接之后就可以通过输入流读取网络数据. 详见:Android(java)学习笔记209:采用get请求提交数据 ...
- flume 读取kafka 数据
本文介绍flume读取kafka数据的方法 代码: /************************************************************************* ...
- spark读取kafka数据 createStream和createDirectStream的区别
1.KafkaUtils.createDstream 构造函数为KafkaUtils.createDstream(ssc, [zk], [consumer group id], [per-topic, ...
- 使用 Http 的 Get 方式读取网络数据
作为移动平台的应用,一定避免不了与网络交换数据,不论是读取网页数据,还是调用API接口,都必须掌握Http通信技术 代码如下: package zw1; import java.io.Buffered ...
- flink 读取kafka 数据,partition分配
每个并发有个编号,只会读取kafka partition % 总并发数 == 编号 的分区 如: 6 分区, 4个并发 分区: p0 p1 p2 p3 p4 p5 并发: 0 1 2 3 ...
- jxl读写excel, poi读写excel,word, 读取Excel数据到MySQL
这篇blog是介绍: 1. java中的poi技术读取Excel数据,然后保存到MySQL数据中. 2. jxl读写excel 你也可以在 : java的poi技术读取和导入Excel了解到写入Exc ...
- 关于mapreducer 读取hbase数据 存入mysql的实现过程
mapreducer编程模型是一种八股文的代码逻辑,就以用户行为分析求流存率的作为例子 1.map端来说:必须继承hadoop规定好的mapper类:在读取hbase数据时,已经有现成的接口 Tabl ...
- java的poi技术读取Excel数据到MySQL
这篇blog是介绍java中的poi技术读取Excel数据,然后保存到MySQL数据中. 你也可以在 : java的poi技术读取和导入Excel了解到写入Excel的方法信息 使用JXL技术可以在 ...
- php+phpspreadsheet读取Excel数据存入mysql
先生成Excel模板,然后导入Excel数据到mysql,每条数据对应图片上传到阿里云 <?php /** * Created by PhpStorm. * User: Administrato ...
随机推荐
- 常用的Git命令清单
目录 名词解释 开卷必读 一. 新建代码库 二.配置 三. 忽略某个文件的改动 四. 增加/删除文件 五. 代码提交 六. 分支 七. 标签 八. 查看信息 九. 远程同步 十. 撤销 十一. Git ...
- Sqoop(四)增量导入、全量导入、减量导入
增量导入 一.说明 当在生产环境中,我们可能会定期从与业务相关的关系型数据库向Hadoop导入数据,导入数仓后进行后续离线分析.这种情况下我们不可能将所有数据重新再导入一遍,所以此时需要数据增量导入. ...
- SpringCloud 源码系列(6)—— 声明式服务调用 Feign
SpringCloud 源码系列(1)-- 注册中心 Eureka(上) SpringCloud 源码系列(2)-- 注册中心 Eureka(中) SpringCloud 源码系列(3)-- 注册中心 ...
- 关于c语言的知识点不足的地方
在最近的一次c语言考试之前,自己根据老师说的会出原题的卷子的总结 关于代码的自动对齐,dev c++ CTRL+shift+A/a 关于运算顺序的csdn上有,常考的有/ %等 上地址 https:/ ...
- Netty学习之IO模型
目录 1.1 同步.异步.阻塞.非阻塞 同步 VS 异步 同步 异步 阻塞 VS 非阻塞 阻塞 非阻塞 举例 ...
- MP(MyBatis-Plus)的自动填充功能
什么是自动填充 有些表中会有更新时间.创建时间.更新人或者创建人这些字段. 每次对数据进行新增.删除.修改时都需要对这些字段进行设置.传统的做法是在进行这些操作前,对Entity的字段进行set设置, ...
- thinkphp3.2框架运行原理
thinkphp3.2是使用率非常普遍的国产php框架,以简单易于上手闻名,那么它框架结构是怎样的? tp3.2设计简单来说就是CBD,core(框架核心文件),bebavior(行为,tp3.2一大 ...
- 常见大中型网络WLAN基本业务实例
组网图形 大中型WLAN网络简介 本文介绍的WLAN网络是指利用频率为2.4GHz或5GHz的射频信号作为传输介质的无线局域网,相对于有线网络的铺设成本高,不便于网络调整和扩展.位置固定,移动性差等缺 ...
- web渗透之常见shell反弹姿势
常见反弹shell总结: 原文链接请点击:https://ruoli-s.github.io/posts/b956.html 一.bash反弹 通用 ① 在kali机里面开启端口监听: nc -lvv ...
- Java开发手册之异常日志
1.捕获异常的时候,有一种特殊情况,就是方法体内部所抛出的并不是Exception而是Error,这个时候,上层方法捕获Exception就会失败.所以在某些场合需要捕获更高一级别的Throwable ...