SparkStream写入数据到mysql
在https://blog.csdn.net/qq_35885488/article/details/103185724基础上进行修改
建表语句
create table wordcount(
word varchar(50) default null
wordcount int (10) default null
);
使用foreachRDD的设计模式
dstream.foreachRDD
是一个强大的语句,可以将数据发送到外部系统。但是,重要的是要了解如何正确有效地使用此语句。应避免的一些常见错误如下。
通常,将数据写入外部系统需要创建一个连接对象(例如,到远程服务器的TCP连接),并使用该对象将数据发送到远程系统。为此,开发人员可能会无意间尝试在Spark驱动程序中创建连接对象,然后尝试在Spark worker中使用该对象以将记录保存在RDD中。
例如(在Scala中)
//将结果写到mysql
result.foreachRDD { rdd =>
val connection = createConn() // executed at the driver
rdd.foreach { record =>
val sql = "insert into wordcount(word,wordcount) values ('"+ record._1 +"',"+record._2+")" // executed at the worker
connection.createStatement().execute(sql)
}
}
/**
* 获取mysql连接
*连接池实现
*/
def createConn() = {
Class.forName("com.mysql.jdbc.Driver")
DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","admin")
}
这是不正确的,因为这要求将连接对象序列化并从驱动程序发送给工作程序。这样的连接对象很少能在机器之间转移。此错误可能表现为序列化错误(连接对象不可序列化),初始化错误(连接对象需要在工作程序中初始化)等。正确的解决方案是在工作程序中创建连接对象。
报错信息
org.apache.spark.SparkException: Task not serializable
at org.apache.spark.util.ClosureCleaner$.ensureSerializable(ClosureCleaner.scala:298)
at org.apache.spark.util.ClosureCleaner$.org$apache$spark$util$ClosureCleaner$$clean(ClosureCleaner.scala:288)
at org.apache.spark.util.ClosureCleaner$.clean(ClosureCleaner.scala:108)
at org.apache.spark.SparkContext.clean(SparkContext.scala:2287)
at org.apache.spark.rdd.RDD$$anonfun$foreach$1.apply(RDD.scala:917)
at org.apache.spark.rdd.RDD$$anonfun$foreach$1.