使用Spark跨集群同步Hive数据

1

本文适用有入门spark基础的同学,一些最基础知识不再赘述

通过阅读本文即可掌握使用Spark跨集群同步Hive数据的技巧!

众所周知,业界比较成熟的同步数据工具是Sqoop,它是连接关系型数据库和Hadoop的桥梁

比较常用的场景是从MySQL等RDB同步到Hive、Hbase或者将Hive、Hbase的数据导出到MySQL

但是在公司项目技术选型时选用了用Spark来从一个集群同步数据到另一个集群

下面来比较一下这两种方式:

①Sqoop使用配置化,Spark需要代码开发

学习成本上使用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的那种)

clipboard.png
在创建SparkSession对象时动态传参传入源数据集群的Hive Metastore Server地址

1.2 将Spark的hadoopConfiguration对象切换到源数据集群
连接了数据源集群的Hive Metastore Server元数据服务,Spark会根据里面记录的元数据信息去拉取数据,而其它集群记录的是其它HDFS集群的路径
默认根据配置文件本集群跑Spark程序时连接的是本集群的HDFS地址,所以根据元数据获取的数据路径会找不到
而MetaServer元数据服务地址属于在Spark创建时指定的,在这个对象生命周期内无法被改变,但是Hadoop相关配置是可以在运行时切换的
所以需要在取数时切换Hadoop配置
clipboard.png

clipboard.png
1.3 通过SQL指定需要获取的数据将数据加载到目标集群的HDFS文件中

clipboard.png

上例中是抽取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主备切换

clipboard.png
由于这里是连接spark本地集群的hadoop集群,只需要创建Configuration对象读取集群默认配置,如果是获取其它集群的还需要把连接信息赋入

2.将导入的数据文件加载到本集群的Hive表中

由于上面说过的原因,连接的MetaServer无法在运行时改变,所以抽取数据文件和加载数据进目标集群的Hive表无法放在同一个任务中进行,要另起一个任务进行加载

2.1 新的任务中创建SparkSession对象指定本集群的Hive Metastore Server元数据服务地址

clipboard.png

2.2 使用HiveSQL的语法加载数据
LOAD DATA INPATH '/datapath/' OVERWRITE INTO TABLE tableName PARTITION (par='xxx')

你可能感兴趣的

载入中...