- 前言
在之前的学习中我们已经学习了如何用Structured Streaming处理Socket数据,文本数据以及kafka数据,但是在真实的业务场景中不可能只让我们把数据只写入控制台让我们观看,所以今天我们来学习从kafka读取数据,将数据写入到MySQL中。
- 扩展
我们开发中经常需要将流的运算结果输出到外部数据库,例如MySQL中,但是比较遗憾Structured Streaming API不支持外部数据库作为接收器,但是目前我们只能自己自定义一个类,继承ForeachWriter并实现其方法
- 参考网站
- 代码
需求:将数据进行wordCount计算,并且将计算后的数据写入到MySQL中
def main(args: Array[String]): Unit = {
//创建SparkSession
val spark = SparkSession.builder().master("local[*]").appName("test01").getOrCreate()
//设置日志级别
spark.sparkContext.setLogLevel("WARN")
//读取数据
//kafka.bootstrap.servers:设置kafka集群服务器
//subscribe:需要订阅的主题
//load:加载
val kafkaDatas: DataFrame = spark.readStream.format("kafka")
.option("kafka.bootstrap.servers", "node01:9092,node02:9092,node03:9092")
.option("subscribe", "test01")
.load()
//根据业务逻辑进行数据处理
//因为kafkaDatas的数据类型为Row我们需要把它转为String类型进行数据处理
import spark.implicits._
val datas: Dataset[(String, String)] = kafkaDatas.selectExpr("CAST(key As string)", "CAST(value As string)").as[(String, String)]
//处理数据 求出单词数量(WordCount)
//数据为一个元组 第二个元素才是我们想要到的数据
val words: Dataset[String] = datas.flatMap(x => x._2.split(" "))
val wordsDatas: Dataset[Row] = words.groupBy("value").count().sort($"count".desc)
var intoMySql = new IntoMySql("jdbc:mysql://localhost:3306/test03?characterEncoding=UTF-8", "root", "root")
//计算结果输出
//foreach:遍历数据 我们在代码中遍历数据写入到mysql中
//outputMode:表示输出哪些数据
//trigger:触发器
//start:开启任务
//awaitTermination:等待关闭
wordsDatas.writeStream
.foreach(intoMySql)
.outputMode("complete")
.trigger(Trigger.ProcessingTime(0))
.start()
.awaitTermination()
}
//定义intoMySql,继承ForeachWriter并实现其方法
//编写将数据插入到mysql数据库的代码
class IntoMySql(url: String, username: String, password: String) extends ForeachWriter[Row] with Serializable {
//_表示占位符,后面会给变量赋值
//连接对象
var connection: Connection = _
var preparedStatement: PreparedStatement = _
//打开数据库连接
override def open(partitionId: Long, version: Long): Boolean = {
//获取连接
connection = DriverManager.getConnection(url, username, password)
//获取连接无误则返回true
true
}
//建表语句
/*
CREATE TABLE `words` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`word` varchar(255) NOT NULL,
`count` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `word` (`word`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8;
*/
//用于插入/更新数据到mysql
override def process(value: Row): Unit = {
//获取数据
//下标为0的数据为单词名
var word = value.get(0).toString
//下标为1的数据为总数
var count = value.get(1).toString.toInt
println(word + " " + count)
//编写数据插入语句
//REPLACE INTO:表示如果表中没有数据就插入,如果有数据则替换
//注意:REPLACE INTO要求表有主键或唯一索引
var sql = "REPLACE into words (id,word,count) values (Null,?,?)"
preparedStatement = connection.prepareStatement(sql)
//设置第一个占位符(?)的数据
preparedStatement.setString(1, word)
//设置第二个占位符(?)的数据
preparedStatement.setInt(2, count)
//执行更新数据
preparedStatement.executeUpdate()
}
//关闭数据库连接
override def close(errorOrNull: Throwable): Unit = {
if (connection != null) {
connection.close()
}
if (preparedStatement != null) {
preparedStatement.close()
}
}
}
上面代码已经写好了从kafka读取数据并且把数据写入MySQL中的代码,接下来你只需要开启kafka将数据写入指定主题,并且创建好指定mysql表进行结果查看即可
- 结果
如上从代码到结果小编已经全部展示了,如果有需要的小伙伴可以拿去跑跑看哦,如果还有什么疑问可以私聊小编哦!!!