本文適用有入門spark基礎的同窗,一些最基礎知識再也不贅述數據庫
經過閱讀本文便可掌握使用Spark跨集羣同步Hive數據的技巧!app
衆所周知,業界比較成熟的同步數據工具是Sqoop,它是鏈接關係型數據庫和Hadoop的橋樑框架
比較經常使用的場景是從MySQL等RDB同步到Hive、Hbase或者將Hive、Hbase的數據導出到MySQL工具
可是在公司項目技術選型時選用了用Spark來從一個集羣同步數據到另外一個集羣oop
下面來比較一下這兩種方式:學習
①Sqoop使用配置化,Spark須要代碼開發spa
學習成本上使用Spark稍微高一些,可是同步數據複雜一些Sqoop的配置也不見得很簡單日誌
②Sqoop在同步數據進行存儲時仍須要啓動MapReduce任務,Spark使用自身框架進行內存計算對象
在效率上Spark比Sqoop要高生命週期
③Sqoop1和Sqoop2不能徹底兼容,且網上在不一樣集羣的Hive間同步數據的資料也比較少,出現問題時不保證能解決
因此選用了Spark做爲天池的數據同步方式
其實當時選用Spark最重要的緣由是本人使用Spark比較熟!
下面就來介紹如何使用Spark進行數據同步
1. 抽取數據文件
1.1 建立Spark入口對象指定源數據的Hive元數據服務
擴展:在遠程鏈接Hive時Hive有兩種服務Hive Metastore Server和HiveServer2
HiveServer2是JDBC鏈接,使用這種方式會佔用數據本地集羣的計算資源(經常使用默認端口10000的那種)
Spark鏈接Hive可使用Hive Metastore Server,這樣只需鏈接Hive的元數據,經過元數據記錄的數據路徑拉取數據使用Spark對數據進行計算(經常使用默認端口9083的那種)
在建立SparkSession對象時動態傳參傳入源數據集羣的Hive Metastore Server地址
1.2 將Spark的hadoopConfiguration對象切換到源數據集羣
鏈接了數據源集羣的Hive Metastore Server元數據服務,Spark會根據裏面記錄的元數據信息去拉取數據,而其它集羣記錄的是其它HDFS集羣的路徑
默認根據配置文件本集羣跑Spark程序時鏈接的是本集羣的HDFS地址,因此根據元數據獲取的數據路徑會找不到
而MetaServer元數據服務地址屬於在Spark建立時指定的,在這個對象生命週期內沒法被改變,可是Hadoop相關配置是能夠在運行時切換的
因此須要在取數時切換Hadoop配置
1.3 經過SQL指定須要獲取的數據將數據加載到目標集羣的HDFS文件中
上例中是抽取APP埋點日誌表,這個表中源數據是根據site和year, month, day進行分區的
咱們須要天天同步每日的增量數據,Spark在拉取數據時會根據分區去拉取對應的數據而不是全量數據
同時在SQL中能夠看到我在同步過來數據時將year, month, day字段拼成dt字段做爲日期新字段,且原表數據中字段比這裏多得多,只取了須要的字段以節省時間空間
而且在寫出成HDFS文件的時候經過.partitionBy("site", "dt")也指定了目標表的分區
寫出的文件路徑就是這種格式的:/tianchi/data/ods_app_burial_log/site=zz/dt=2019-06-11
另外$HDFS_ADDR是經過API動態獲取的目標集羣active nameNode的ip:port
防止寫死後NN主備切換
因爲這裏是鏈接spark本地集羣的hadoop集羣,只須要建立Configuration對象讀取集羣默認配置,若是是獲取其它集羣的還須要把鏈接信息賦入
2.將導入的數據文件加載到本集羣的Hive表中
因爲上面說過的緣由,鏈接的MetaServer沒法在運行時改變,因此抽取數據文件和加載數據進目標集羣的Hive表沒法放在同一個任務中進行,要另起一個任務進行加載
2.1 新的任務中建立SparkSession對象指定本集羣的Hive Metastore Server元數據服務地址
2.2 使用HiveSQL的語法加載數據LOAD DATA INPATH '/datapath/' OVERWRITE INTO TABLE tableName PARTITION (par='xxx')