前言
我在很早之前用spark读取本地文件然后使用如下代码将数据写入到mysql
df.write.format("jdbc")
.mode(SaveMode.Append)
.option("url", "jdbc:mysql://localhost:3306/spark")
.option("dbtable", "unisk")
.option("user", "root")
.option("password", "root")
.save()
现在需要打包后提交到集群,本以为依然可以使用这个代码提交,没想到…
几个问题
- 需不需要给每个节点上传驱动
并不需要给每个节点上传,只需要给提交代码的节点上传即可
- 提交spark需不需要加:–jars /var/lib/hadoop-hdfs/mysql-connector-java-5.1.32-bin.jar \
需要
不然报错:
Exception in thread “main” java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
- 可不可以在代码中不加 .option(“driver”, “com.mysql.jdbc.Driver”)配置
不可以
不然报错:
Exception in thread “main” java.sql.SQLException: No suitable driver
- 可不可以不在maven中配置驱动
不可以
不然报错:
Exception in thread “main” java.sql.SQLException: No suitable driver
- maven中驱动版本需要和本地驱动版本一致吗
不需要
如何写提交到集群的入库代码
df.write.format(source = "jdbc")
.mode(SaveMode.Append)
.option("url", "jdbc:mysql://xxx.xx.x.xx:3306/app_als")
.option("dbtable", s"ads_bsn_corr_di")
.option("user", "root")
.option("password", "root")
.option("driver", "com.mysql.jdbc.Driver")
.save()
dbtable表名可以不用预先在mysql创建
不过,字段类型就是默认的text和bigint了,如下:
+--------------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+------------+------+-----+---------+-------+
| prod_id | text | YES | | NULL | |
| statis_month | text | YES | | NULL | |
| app_ctg | text | NO | | NULL | |
| ct_user | bigint(20) | NO | | NULL | |
| s_flow | bigint(20) | YES | | NULL | |
+--------------+------------+------+-----+---------+-------+
如何提交代码
spark-submit \
--class cn.unisk.mysql.Test\
--master yarn \
--deploy-mode cluster \
--jars /var/lib/hadoop-hdfs/mysql-connector-java-5.1.32-bin.jar \
/path/Jar.jar
上面提交主要是想显示出–jars参数,并没有其他详细的参数配置
读取配置文件的方式
比如我们一个代码中,有很多dataframe入库的需求,这个时候最好是把mysql的需要的配置信息写到一个配置文件中,这样方便后续维护,比如可以方便统一修改配置信息等
- 在resources目录下创建一个比如名叫mysql.properties的文件,写入:
url=jdbc:mysql://localhost:3306/test
dbtable=user
user=root
password=root
driver=com.mysql.jdbc.Driver
- 加载配置文件
val prop = new Properties()
prop.load(this.getClass.getClassLoader.getResourceAsStream("mysql.properties"))
val url = prop.getProperty("url")
val dbtable = prop.getProperty("dbtable")
val user = prop.getProperty("user")
val password = prop.getProperty("password")
val driver = prop.getProperty("driver")
- 使用配置信息
df.write.format(source = "jdbc")
.mode(SaveMode.Append)
.option("url", url)
.option("dbtable", dbtable)
.option("user", user)
.option("password",password)
.option("driver",driver)
.save()
很显然,如果以后要修改配置信息,只要在配置文件中修改一次即可
后记
这种方式入mysql库非常方便,这里需要注意一个问题:如果mysql中有三个字段名字为id,name,age,那么spark入库的时候必须与mysql表结构的字段名称完全一致不然报错:
Exception in thread "main" org.apache.spark.sql.AnalysisException: Column "x" not found in schema Some(StructType(StructField(id,IntegerType,true), StructField(name,StringType,true), StructField(age,IntegerType,true)));
我们完全可以指定某几个字段,入mysql库,这样也非常的方便咯.