第3.8章:StarRocks数据导入--Spark Load

Spark Load是通过外部的Spark资源实现对导入数据的预处理,进而提高StarRocks大数据量的导入性能,同时也可以节省StarRocks集群的计算资源。Spark Load的操作本身不复杂,但涉及的技术栈比较多,架构相对较重,所以主要用于初次迁移、大数据量导入等场景(数据量可到TB级别)。

Spark Load的特点在于其引入了外部Spark集群,让我们可以方便的使用Spark 执行 ETL 完成对导入数据的预处理,包括全局字典构建(BITMAP类型)、分区、排序、聚合等。

StarRocks官网文档对Spark Load的介绍地址如下:

Spark Load @ SparkLoad @ StarRocks DocsSpark Loadhttps://docs.starrocks.com/zh-cn/main/loading/SparkLoad通常来说,Spark Load的整体逻辑是:读Hadoop数据源中的数据文件-->使用Spark自己的计算资源进行ETL-->将ETL后的文件保存到计算资源中配置的Hadoop中-->自动使用Broker Load导入上一步的中间文件到StarRocks。

一、集群准备

演示需要用到的服务器及其上部署的主要服务见下表:

节点IP

部署服务

端口

版本

说明

192.168.110.11

[node01]

NameNode

9000

hadoop-3.3.0

core-site.xml中fs.defaultFS参数的端口

DataNode

Hadoop所用端口均为默认

NodeManager

192.168.110.12

[node02]

DataNode

hadoop-3.3.0

ResourceManager

8032

RM的applications manager(ASM)端口

NodeManager

Spark

spark-2.4.8-bin-hadoop2.7

作为计算资源

Scala

scala-2.11.12

192.168.110.13

[node03]

SecondaryNameNode

hadoop-3.3.0

DataNode

NodeManager

192.168.110.98

[starrocks]

FE

9030

StarRocks 1.19.0

StarRocks所用端口均为默认端口

BE

Broker

Broker名称:hdfs_broker

mysql-client

mysql-client-5.7.35

Spark客户端

每个FE节点都需要配置

spark-2.4.8-bin-hadoop2.7

无需启动,可简单理解为是使用Spark Load时FE的依赖包

Yarn客户端

hadoop-2.10.0

本次演示,我们模拟从任意Hadoop中读取数据,Spark对数据预处理后会将中间文件保存在配置的Hadoop中,然后自动通过Broker Load的方式完成导入。整个操作其实涉及到个两套Hadoop集群,一套是用来做数据源的,另一套是用来存储Spark预处理的数据的,这两套Hadoop集群可以相同也可以不相同,咱们上面使用的是相同的,其版本没有什么要求。对于上表中的服务配置还有一些需要说明的地方:

1、为方便演示,我们在starrocks节点单机部署了StarRocks;

2、starrocks节点的Spark客户端需要使用Spark 2.4.5或以上的Spark2官方版本(不支持Spark3);

3、node02节点用来作为计算资源的Spark版本建议与starrocks节点的“Spark客户端”版本保持一致,同时需要以spark on yarn的模式运行;

4、starrocks节点的Yarn客户端需要使用Hadoop 2.5.2或以上的hadoop官方版本,支持Hadoop 3,但更推荐使用Hadoop 2版本,因为测试更充分;

5、node01~03节点的Hadoop集群对Hadoop版本没有特别要求,但都需要配置环境变量HADOOP_HOME,例如:

vim /etc/profile

##HADOOP_HOME

export HADOOP_HOME=/opt/module/hadoop-3.3.0

export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

6、以上所有节点均部署了Oracle jdk 1.8.0_201(推荐使用Oracle jdk 1.8+),并配置了环境变量;

7、StarRocks集群中每个FE节点都需要配置Spark客户端与Yarn客户端,多FE时注意不要漏配(因为无法确定请求从哪个FE上发出,所以需要对每个FE都进行配置);

8、StarRocks集群中使用Spark客户端时不需要部署Scala,也不需要配置Spark、Yarn或Hadoop的环境变量。

在starrocks节点(192.168.110.98)上,各应用所在的路径为:

应用

部署路径

FE

/opt/module/starrocks/fe

BE

/opt/module/starrocks/be

Broker

/opt/module/starrocks/apache_hdfs_broker

Spark客户端

/opt/module/spark-2.4.8-bin-hadoop2.7

Yarn客户端

/opt/module/hadoop-2.10.0

二、导入介绍

Spark Load的整体操作可以分为五个步骤:

配置外部Spark资源-->FE配置Spark客户端-->FE配置YARN客户端-->配置计算资源Spark集群-->执行导入任务,我们逐项展开。

2.1 配置外部Spark资源

在starrocks节点,使用mysql-client访问StarRocks服务,为方便演示,我们使用root用户登录(密码也为root):

[root@starrocks ~]# mysql -h192.168.110.98 -P9030 -uroot -proot

要使用Spark Load,我们首先需要在StarRocks集群中创建Spark计算资源。也就是说,这里面配置的,就是我们需要使用的外部Spark计算集群。根据当前测试环境的配置情况,我们先创建名为spark_resource0的资源:

mysql> CREATE EXTERNAL RESOURCE "spark_resource0"

PROPERTIES

(

"type" = "spark",

"spark.master" = "yarn",

"spark.submit.deployMode" = "cluster",

"spark.executor.memory" = "1g",

"spark.hadoop.yarn.resourcemanager.address" = "192.168.110.12:8032",

"spark.hadoop.fs.defaultFS" = "hdfs://192.168.110.11:9000",

"working_dir" = "hdfs://192.168.110.11:9000/tmp/starrocks/sparketl",

"broker" = "hdfs_broker"

);

创建语句中主要参数的释义如下:

type:资源类型,必填,目前仅支持spark;

spark.master:必填,目前支持yarn;

spark.submit.deployMode:Spark程序的部署模式,必填,支持cluster,client两种;

spark.hadoop.yarn.resourcemanager.address:单点resource manager地址,端口需使用ASM端口,默认为8032;

spark.hadoop.fs.defaultFS:master为yarn时必填;

working_dir:Spark作为ETL资源时使用的目录,必填;

broker:StarRocks集群中broker的名字,在StarRocks中可以通过"show broker; "命令查看,Spark作为ETL资源使用时必填。

PROPERTIES部分的参数实际是Spark的参数,可以参考Spark文档中的参数介绍:https://spark.apache.org/docs/latest/configuration.htmlhttps://spark.apache.org/docs/latest/configuration.html

创建完成后,我们可以查看StarRocks中已经创建的资源:

mysql> SHOW RESOURCES;

对于不需要或者创建错误的资源,我们也可以执行删除,例如:

mysql> DROP RESOURCE spark_resource1;

创建好的外部资源,我们还需要授权给后面执行Spark Load命令的用户或角色,比如我们将资源spark_resource0的USAGE_PRIV权限授权给root用户(root用户本身便拥有所有资源使用权限,这里仅演示语法):

mysql> GRANT USAGE_PRIV ON RESOURCE "spark_resource0" TO "root"@"%";

2.2 FE配置Spark客户端

在刚接触Spark Load时,社区不时有同学疑惑,为FE配置Spark和Yarn客户端?那是不是说StarRocks集群要和Hadoop集群以及Spark集群耦合在一起?要混合部署在相同机器上吗?

其实不是的,这里的“客户端”可以理解为“依赖文件”,我们只需要在FE节点放置Spark和Yarn的二进制文件并简单配置就可以,并不需要启动它们,完全可以认为它们是StarRocks执行Spark Load时FE所需要的依赖。

在执行Spark Load时,FE底层是通过执行spark-submit的命令去提交spark任务,所以是需要为FE配置spark客户端的。同样,FE底层通过执行yarn命令去获取正在运行的application的状态,以及杀死application,因此也需要为FE配置yarn客户端。

当前测试环境只有一个FE,我们就将从官方下载好的spark-2.4.8-bin-hadoop2.7.tgz(https://archive.apache.org/dist/spark/spark-2.4.8/)解压至预定的目录,例如当前环境的路径为:/opt/module/spark-2.4.8-bin-hadoop2.7。

然后,我们还需要将spark中jars文件夹内所有的jar包打包为zip文件并命名为spark-2x.zip,例如当前环境下,我们执行打包命令:

[root@starrocks ~]# cd /opt/module/spark-2.4.8-bin-hadoop2.7/jars

[root@starrocks jars]# zip spark-2x.zip *

[root@starrocks jars]# ls | grep spark-2x.zip

spark-2x.zip

[root@starrocks jars]# pwd

/opt/module/spark-2.4.8-bin-hadoop2.7/jars

前面的操作我们得到Spark客户端的路径、Spark依赖包及其路径,接下来,我们就需要在FE的配置文件中添加这里的配置:

[root@starrocks ~]# vim /opt/module/starrocks/fe/conf/fe.conf

加入配置:

#配置SPARK-HOME环境变量

spark_home_default_dir = /opt/module/spark-2.4.8-bin-hadoop2.7

#配置SPARK依赖包

spark_resource_path = /opt/module/spark-2.4.8-bin-hadoop2.7/jars/spark-2x.zip

2.3 FE配置YARN客户端

在配置完Spark客户端后,我们继续为FE配置Yarn客户端。首先还是将下载好的hadoop-2.10.0.tar.gz(https://archive.apache.org/dist/hadoop/common/hadoop-2.10.0/)解压至预置路径,比如当前环境的:/opt/module/hadoop-2.10.0。

接下来,我们还需要修改一下yarn的配置文件:

[root@starrocks ~]# vim /opt/module/hadoop-2.10.0/libexec/hadoop-config.sh

在其首行添加:

#配置JAVA_HOME

export JAVA_HOME=/usr/java/jdk1.8.0_201

添加完成后,我们再次编辑fe.conf:

[root@starrocks ~]# vim /opt/module/starrocks/fe/conf/fe.conf

加入配置:

#配置YARN可执行文件路径

yarn_client_path = /opt/module/hadoop-2.10.0/bin/yarn

添加完成后退出。

修改FE的配置文件后,我们需要重启FE让配置生效。

-----------------------------------------------------------------------------------------------------------------------

客户端配置补充说明

对于前面的步骤二步骤三的配置,我们也可以采用另一套方案,即不修改FE配置文件,而是通过创建软链接的方式,将Spark目录和Yarn目录直接映射至FE配置参数的默认路径下。

配置项spark_home_default_dir默认为FE根目录下的 lib/spark2x路径,spark_resource_path参数默认为FE根目录下的lib/spark2x/jars/spark-2x.zip。

那么我们就可以使用软连接配置Spark客户端:

[root@starrocks ~]# cd /opt/module/starrocks/fe/lib

[root@starrocks ~]# ln -s /opt/module/spark-2.4.8-bin-hadoop2.7 spark2x

yarn_client_path默认为FE根目录下的lib/yarn-client/hadoop/bin/yarn路径,同理,我们也可以这样配置YARN客户端:

[root@starrocks ~]# mkdir /opt/module/starrocks/fe/lib/yarn-client

[root@starrocks ~]# cd /opt/module/starrocks/fe/lib/yarn-client

[root@starrocks ~]# ln -s /opt/module/hadoop-2.10.0 hadoop

这样配置完成后,我们就无需重启集群的FE服务了。

-----------------------------------------------------------------------------------------------------------------------

2.4 配置计算资源Spark集群

在node02节点,我们进行了Spark on Yarn单机环境搭建,简单的说明一下部署过程:

1、解压Scala文件并配置环境变量

[root@node02 ~]# vim /etc/profile

添加:

export SCALA_HOME=/opt/module/scala-2.11.12

export PATH=$PATH:$SCALA_HOME/bin

2、分发Spark文件并在profile中配置环境变量

export SPARK_HOME=/opt/module/spark-2.4.8-bin-hadoop2.7

export PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin

完成后执行source命令使环境变量生效:

[root@node02 ~]# source /etc/profile

3、修改Spark配置文件

[root@node02 ~]# cd /opt/module/spark-2.4.8-bin-hadoop2.7/conf

[root@node02 ~]# cp spark-env.sh.template spark-env.sh

[root@node02 ~]# vim spark-env.sh

在末尾添加下列配置:

# Hadoop配置文件目录

export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop

# YARN配置文件目录

export YARN_CONF_DIR=$HADOOP_HOME/etc/hadoop

# SPARK目录

export SPARK_HOME=/opt/module/spark-2.4.8-bin-hadoop2.7

# SPARK执行文件目录

export PATH=$SPARK_HOME/bin:$PATH

# 使Spark可读写HDFS中的数据

export SPARK_DIST_CLASSPATH=$(hadoop classpath)

# 配置JAVA_HOME

export JAVA_HOME=/usr/java/jdk1.8.0_201

4、验证集群状态

我们首先确认hdfs和yarn都已启动,然后运行自带的例子SparkPi:

[root@node02 ~]# cd $SPARK_HOME

[root@node02 ~]#./bin/spark-submit --class org.apache.spark.examples.SparkPi --master yarn --deploy-mode cluster --driver-memory 1G --num-executors 3 --executor-memory 1G --executor-cores 1  ./examples/jars/spark-examples_2.11-2.4.8.jar 100

如果看到控制台最后出现“final status: SUCCEEDED”,说明运行成功。

5、启动Spark服务

[root@node02 ~]# cd $SPARK_HOME

[root@node02 ~]#./sbin/start-all.sh

停止服务的命令为:./sbin/stop-all.sh

2.5 执行导入任务

到此,配置部分的准备工作已经完成,接下来继续演示一个简单的例子。我们使用Spark Load将HDFS中customer.csv文件的数据导入至StarRocks ods_data_load库的customer表,假设文件customer.csv的路径为:

hdfs://192.168.110.11:9000/loong/customer.csv(数据文件见评论区度盘),其内共有3W行数据,数据格式如下:

1|Customer#000000001|j5JsirBM9P|MOROCCO  0|MOROCCO|AFRICA|25-989-741-2988|BUILDING

2|Customer#000000002|487LW1dovn6Q4dMVym|JORDAN   1|JORDAN|MIDDLE EAST|23-768-687-3665|AUTOMOBILE

3|Customer#000000003|fkRGN8n|ARGENTINA7|ARGENTINA|AMERICA|11-719-748-3364|AUTOMOBILE

………………

我们先在StarRocks中创建对应数据的数据库及数据表,例如:

mysql> create database if not exists ods_data_load;

mysql> CREATE TABLE IF NOT EXISTS ods_data_load.`customer` (

  `c_custkey` int(11) NOT NULL COMMENT "",

  `c_name` varchar(26) NOT NULL COMMENT "",

  `c_address` varchar(41) NOT NULL COMMENT "",

  `c_city` varchar(11) NOT NULL COMMENT "",

  `c_nation` varchar(16) NOT NULL COMMENT "",

  `c_region` varchar(13) NOT NULL COMMENT "",

  `c_phone` varchar(16) NOT NULL COMMENT "",

  `c_mktsegment` varchar(11) NOT NULL COMMENT ""

) ENGINE=OLAP

DUPLICATE KEY(`c_custkey`)

COMMENT "OLAP"

DISTRIBUTED BY HASH(`c_custkey`) BUCKETS 12

PROPERTIES (

"replication_num" = "1"

);

准备工作全部完成后,启动Spark Load开始导入数据:

mysql> LOAD LABEL ods_data_load.label111301

(

    DATA INFILE("hdfs://192.168.110.11:9000/loong/customer.csv")

    INTO TABLE customer

    COLUMNS TERMINATED BY "|"

    (c_custkey,c_name,c_address,c_city,c_nation,c_region,c_phone,c_mktsegment)

)

WITH RESOURCE 'spark_resource0'

(

    "spark.executor.memory" = "2g",

    "spark.shuffle.compress" = "true"

)

PROPERTIES

(

    "timeout" = "3600"

);

LOAD语句的写法与Broker Load的写法非常相似,我们可以通过set或where语句来进行ETL,这部分可以参考上一篇Broker Load的介绍,这里不再赘述。和Broker Load最大的不同是,Spark Load的ETL是使用我们配置的Spark资源进行的,Broker Load等其他导入方式是使用StarRocks自身的计算资源,这也是Spark Load的设计核心所在。

WITH RESOURCE中的参数是Spark的资源参数,当我们有临时性的需求比如增加任务使用的内存资源时,我们就不需要修改Spark configs,可以在这里直接设置,该设置仅对本次任务生效,并不影响StarRocks集群中现有的配置。

执行任务后,我们同样可以使用show命令查看导入任务:

mysql> use ods_data_load;

mysql> show load order by createtime desc limit 1\G

*************************** 1. row ***************************

         JobId: 13046

         Label: label111301

         State: FINISHED

      Progress: ETL:100%; LOAD:100%

          Type: SPARK

       EtlInfo: unselected.rows=0; dpp.abnorm.ALL=0; dpp.norm.ALL=30000

      TaskInfo: cluster:spark_resource0; timeout(s):3600; max_filter_ratio:0.0

      ErrorMsg: NULL

    CreateTime: 2021-11-13 12:34:34

  EtlStartTime: 2021-11-13 12:34:46

 EtlFinishTime: 2021-11-13 12:35:01

 LoadStartTime: 2021-11-13 12:35:01

LoadFinishTime: 2021-11-13 12:35:04

         URL: http://node02:8088/proxy/application_1636629462368_0009/

    JobDetails: {"Unfinished backends":{"00000000-0000-0000-0000-000000000000":[]},"ScannedRows":30000,"TaskNumber":1,"All backends":{"00000000-0000-0000-0000-000000000000":[-1]},"FileNumber":1,"FileSize":2807046}

任务状态中我们需要关注的参数主要有:

State:导入任务当前所处的阶段。任务提交之后状态为PENDING,提交Spark ETL之后状态变为ETL,ETL完成之后FE调度BE执行push操作状态变为LOADING,push完成并且版本生效后状态变为FINISHED。导入任务的最终阶段有两个:CANCELLED和FINISHED,当Load job处于这两个阶段时导入完成。其中CANCELLED为导入失败,FINISHED为导入成功。

Progress:导入任务的进度描述。分为两种进度:ETL和LOAD,对应了导入流程的两个阶段ETL和LOADING。LOAD的进度范围为:0~100%。

LOAD进度 = 当前已完成所有replica导入的tablet个数 / 本次导入任务的总tablet个数* 100%。

如果所有导入表均完成导入,此时LOAD的进度为99%,导入进入到最后生效阶段,整个导入完成后,LOAD的进度才会改为100%。导入进度并不是线性的。所以如果一段时间内进度没有变化,并不代表导入没有在执行。

TaskInfo:显示作业的参数配置,比如使用的资源、超时时间和容错率等等。

JobDetails:显示作业的详细运行状态,包括导入文件的个数、总大小(字节)、子任务个数、已处理的原始行数等。

URL:可复制输入到浏览器,跳转至相应application的web界面。

当State状态为FINISHED时,证明导入任务已经完成,我们可以在StarRocks中验证数据的导入情况:

mysql> use ods_data_load;

……

mysql> select count(1) from customer;

+--------------+

|     count(1) |

+--------------+

|      30000   |

+--------------+

若任务长时间处于PENDING状态,说明任务可能是有问题的,我们可以取消该导入任务:

CANCEL LOAD FROM ods_data_load WHERE LABEL = "label10086";

三、问题排查

排查问题的方法主要就是看报错和日志,Spark Load任务的日志可以从三个途径查看:

1、FE根目录fe/log/spark_launcher_log/下存放spark客户端的提交日志;

2、log/fe.log中可能存在Spark状态的日志;

3、Hadoop集群的日志文件夹下的userlogs目录存放有作业具体失败原因。

你可能感兴趣的:(StarRocks,spark,hadoop,big,data,数据仓库)