- 1、Spark概述
- 2、Spark体验
- 3、Spark核心编程
- 4、数据开发三层架构
- 5、SparkSQL核心编程
- 6、SparkStreaming
1、Spark概述
Spark 是一种基于内存的快速、通用、可扩展的大数据分析计算引擎。
-
Spark Core
Spark Core中提供了Spark最基础与最核心的功能,Spark的其他功能如:Spark SQL,Spark Streaming,GraphX,MLib都是在Spark Core的基础上进行扩展的
-
Spark SQL
Spark SQL是Spark用来操作结构化数据的组件。通过Spark SQL,用户可以使用SQL或者HQL来查询数据
-
Spark Streaming
Spark Streaming是Spark平台上针对实时数据进行流式计算的组件
-
Spark MLib
MLib是Spark提供的一个机器学习算法库。
-
Spark GraphX
GraphX是Spark面向图计算提供的框架与算法库
2、Spark体验
2.1 Maven项目相关配置
-
依赖配置
<dependencies> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core_2.12</artifactId> <version>3.0.0</version> </dependency> </dependencies> <build> <plugins> <!-- 该插件用于将 Scala 代码编译成 class 文件 --> <plugin> <groupId>net.alchim31.maven</groupId> <artifactId>scala-maven-plugin</artifactId> <version>3.2.2</version> <executions> <execution> <!-- 声明绑定到 maven 的 compile 阶段 --> <goals> <goal>testCompile</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.1.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
-
配置log4j.properties文件在resources目录,控制日志级别
log4j.rootCategory=ERROR, console log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.target=System.err log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n # Set the default spark-shell log level to ERROR. When running the spark-shell, the # log level for this class is used to overwrite the root logger's log level, so that # the user can have different defaults for the shell and regular Spark apps. log4j.logger.org.apache.spark.repl.Main=ERROR # Settings to quiet third party logs that are too verbose log4j.logger.org.spark_project.jetty=ERROR log4j.logger.org.spark_project.jetty.util.component.AbstractLifeCycle=ERROR log4j.logger.org.apache.spark.repl.SparkIMain$exprTyper=ERROR log4j.logger.org.apache.spark.repl.SparkILoop$SparkILoopInterpreter=ERROR log4j.logger.org.apache.parquet=ERROR log4j.logger.parquet=ERROR # SPARK-9183: Settings to avoid annoying messages when looking up nonexistent UDFs in SparkSQL with Hive support log4j.logger.org.apache.hadoop.hive.metastore.RetryingHMSHandler=FATAL log4j.logger.org.apache.hadoop.hive.ql.exec.FunctionRegistry=ERROR
2.2 Spark运行环境
2.2.1 Local模式
local模式,不需要其他任何任何节点资源,在本地执行Spark代码的环境,一般用于教学,调试,演示等。
-
解压安装包
tar -zxvf spark-3.0.0-bin-hadoop3.2.tgz -C /opt/software
-
修改文件夹为spark_local
mv spark-3.0.0-bin-hadoop3.2 spark_local
-
启动spark-shell
./bin/spark-shell
-
启动成功后,可以查看Web UI监控页面
http://pc001:4040
-
执行spark任务
sc.textFile("/home/nuochengze/sublime_dir/word.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).collect
-
Web UI反应程序在运行
-
-
退出本地模式
ctrl+c或者输入
:quit
-
本地提交应用
bin/spark-submit \ --class org.apache.spark.examples.SparkPi \ --master local[2] \ ./examples/jars/spark-examples_2.12-3.1.2.jar \ 10
-
关键字解释
-
执行结果
-
2.2.2 Standalone模式
只使用Spark自身节点运行的集群模式,即独立部署(Standalone)模式
集群规划:
pc001 | pc002 | pc003 | |
---|---|---|---|
Spark | Worker Master | Worker | Worker |
实现步骤:
-
解压缩安装包
tar -zxvf spark-3.0.0-bin-hadoop3.2.tgz -C /opt/software cd /opt/software mv spark-3.0.0-bin-hadoop3.2 spark-standalone
-
修改配置文件
-
进入解压缩后的路径的conf目录,修改workers.template文件为workers
mv workers.template workers
-
修改workers文件,添加work节点
pc001 pc002 pc003
-
修改spark-env.sh.template文件名为spark-env.sh
mv spark-env.sh.template spark-env.sh
-
修改spark-env.sh文件,添加JAVA_HOME环境变量和集群对应的master节点
export JAVA_HOME=/opt/software/jdk1.8.0_201 SPARK_MASTER_HOST=pc001 SPARK_MASTER_PORT=7077
说明:7077端口,为spark集群内部通讯端口
-
分发到其他host
-
-
启动集群
-
执行脚本命令
$SPARK_STANDALONE/sbin/start-all.sh
-
查看三台服务器的运行进程
-
查看Master资源监控Web UI:http://pc001:8080 (默认端口为8080)
-
-
提交应用
./bin/spark-submit \ --class org.apache.spark.examples.SparkPi \ --master spark://pc001:7077 \ ./examples/jars/spark-examples_2.12-3.1.2.jar \ 10
- --class表示要执行程序的主类
- --master spark://pc001:7077 standalone模式,连接到spark集群
- ./examples/jars/spark-examples_2.12-3.1.2.jar 运行类所在的jar包
- 10 表示程序的入口参数
-
执行程序时状态说明
程序在执行任务时,会产生多个java进程
在执行任务时,默认采用服务器集群节点的总核数,每个节点内存1024M
-
提交参数说明
# 在提交应用中,一般会同时提交参数 ./bin/spark-submit \ --class <main-class> --master <master-url> \ ... # other options <application-jar> [application-arguments]
参数 解释 可选值举例 --class Spark程序中包含主函数的类 --master Spark程序运行的模式(环境) (1)local[*]
(2)spark://pc001:7077
(3)Yarn--executor-memory 1G 指定每个executor可用内存为1G --total-executor-cores 2 指定所有executor使用的cpu核数为2个 --executor-cores 指定每个executor使用的cpu核数 application-jar 打包好的应用jar,包含依赖。这个URL在集群中全局可见,如hdfs:// 共享存储系统。如果是file://path,那么所有的节点的path都包含同样的jar application-arguments 传递给main()方法的参数 -
配置历史服务
在spark-shell停掉之后,集群监控pc001:4040页面无法看到历史任务的运行情况,需要配置历史服务器记录任务运行情况
-
修改/conf/spark-defaults.conf.template文件名为spark-defaults.conf
-
修改spark-default.conf文件,配置日志存储路径
spark.eventLog.enabled true spark.eventLog.dir hdfs://pc001:8082/spark/log_directory
说明:HDFS上的directory_spark目录需要提前存在
hdfs dfs -mkdir /spark/log_directory
-
修改spark-env.sh文件,添加日志配置
export SPARK_HISTORY_OPTS=" -Dspark.history.ui.port=18080 -Dspark.history.fs.logDirectory=hdfs://pc001:8082/spark/log_directory -Dspark.history.retainedApplications=30"
- 参数1含义:WebUI访问的端口号为18080
- 参数2含义:指定历史服务器日志存储路径
- 参数3含义:指定保存Application历史记录的个数,如果超过这个值,旧的应用程序信息将被删除,这个是内存中的应用数,而不是页面上显示的应用数
-
分发配置文件
-
重新启动集群和历史服务
./sbin/stop-all.sh ./sbin/start-all.sh ./sbin/start-history-server.sh
-
重新执行任务测试
./bin/spark-submit \ --class org.apache.spark.examples.SparkPi \ --master spark://pc001:7077 \ ./examples/jars/spark-examples_2.12-3.1.2.jar \ 10
-
查看历史服务:http://pc001:18080
-
-
配置高可用(HA)
集群中Master节点只有一个,容易造成单点故障问题。需要配置多个Master节点,一旦处于活动状态的Master发生故障时,由备用Master提供服务。其HA,由zookeeper提供可用性监测。
集群规划:
pc001 pc002 pc003 Spark Master
Zookeeper
WorkerMaster
Zookeeper
Worker
Zookeeper
Worker-
停止集群
./sbin/stop-all.sh ./sbin/stop-history-server.sh
-
启动zookeeper
-
修改/conf/spark-env.sh文件并添加配置
# 注释如下内容: # SPARK_MASTER_HOST=pc001 # SPARK_MASTER_PORT=7077 # Master监控页面默认访问端口为8080,但是可能会和Zookeeper冲突,自定义一下 SPARK_MASTER_WEBUI_PORT=8989 # 添加Zookeeper集群调度 export SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER -Dspark.deploy.zookeeper.url=pc001,pc002,pc003 -Dspark.deploy.zookeeper.dir=/spark"
-
分发配置给其他host
-
重启集群
./sbin/stop-all.sh ./sbin/stop-history-server.sh ./sbin/start-all.sh ./sbin/start-history-server.sh
-
访问pc001的Web UI:http://pc001:8989
-
启动pc002的单独Master节点,此时pc002节点Master状态处于备用状态
ssh pc002 "$SPARK_STANDALONE_HOME/sbin/start-master.sh"
-
访问pc002的Web UI:http://pc002:8989
-
此时当pc001的master进程被意外中止时,pc002的master能及时替补
-
应用提交
./bin/spark-submit \ --class org.apache.spark.examples.SparkPi \ --master spark://pc001:7077,pc002:7077 \ ./examples/jars/spark-examples_2.12-3.1.2.jar \ 10
-
2.2.3 Yarn模式
Standalone模式由Spark自身提供计算资源,但是因为其主要是计算框架,所以它本身提供的资源调度不是强项。在结合了Yarn后,Spark会更易用。
-
解压安装包
tar -zxvf spark-3.0.0-bin-hadoop3.2.tgz -C /opt/software cd /opt/software mv spark-3.0.0-bin-hadoop3.2 spark-yarn
-
修改hadoop配置文件$HADOOP_HOME/etc/hadoop/yarn-site.xml,并分发给其他host
<property> <!-- 虚拟内存检查,默认打开,修改为关闭 --> <name>yarn.nodemanager.vmem-check-enabled</name> <value>false</value> </property> <property> <!-- 物理内存检查,默认打开,修改为关闭 --> <name>yarn.nodemanager.pmem-check-enabled</name> <value>false</value> </property>
-
修改conf/spark-env.sh,添加JAVA_HOME和YARN_CONF_DIR配置
export JAVA_HOME=/opt/software/jdk1.8.0_201 YARN_CONF_DIR=/opt/software/hadoop-3.1.3/etc/hadoop
-
重启hadoop集群
-
提交应用
./bin/spark-submit \ --class org.apache.spark.examples.SparkPi \ --master yarn \ --deploy-mode cluster \ ./examples/jars/spark-examples_2.12-3.1.2.jar \ 10
-
配置历史服务器
-
修改/conf/spark-defaluts.conf.template文件名为spark-defaults.conf
-
修改spark-default.conf文件,配置日志存储路径
spark.eventLog.enabled true spark.eventLog.dir hdfs://pc001:8082/spark/log_directory
-
修改spark-env.sh文件,添加日志配置
export SPARK_HISTORY_OPTS="-Dspark.history.ui.port=18080 -Dspark.history.fs.logDirectory=hdfs://pc001:8082/spark/log_directory -Dspark.history.retainedApplications=30"
-
修改spark-defaults.conf文件
spark.yarn.historyServer.address=pc001:18080 spark.history.ui.port=18080
-
启动历史服务
sbin/start-history-server.sh
-
-
重新提交应用
./bin/spark-submit \ --class org.apache.spark.examples.SparkPi \ --master yarn \ --deploy-mode client \ ./examples/jars/spark-examples_2.12-3.1.2.jar \ 10
2.3 部署模式的比较
模式 | Spark安装机器数 | 需启动的进程 | 所属者 | 应用场景 |
---|---|---|---|---|
Local | 1 | 无 | Spark | 测试 |
Standalone | 3 | Master及Worker | Spark | 单独部署 |
Yarn | 1 | Yarn及HDFS | Hadoop | 混合部署 |
2.4 常用端口号
- Spark查看当前Spark-shell运行任务情况端口号:4040
- Spark Master内部通信服务端口号:7077
- Standalone模式下,Spark Master Web端口号:8989(防止和zookeeper的端口号8088重合)
- Spark历史服务器端口号:18080
- Hadoop Yarn任务运行情况查看端口号:8088
3、Spark核心编程
Spark计算框架封装了三大数据结构:
- RDD:弹性分布式数据集
- 累加器:分布式共享只写变量
- 广播变量:分布式共享只读变量
3.1 RDD
3.1.1 RDD的定义
RDD(Resilient Distributed Dataset):弹性分布式数据集,是Spark中最基本的数据处理模型,在代码中是一个抽象类,它代表一个弹性的、不可变的、可分区的、集合中元素可并行计算的集合。
-
弹性
- 存储的弹性:内存与磁盘的自动切换
- 容错的弹性:数据丢失可以自动恢复
- 计算的弹性:计算出错重试机制
- 分辨的弹性:可根据需要重新分片
-
分布式
数据存储在大数据集群不同节点上
-
数据集
RDD封装了计算逻辑,并不保存数据
-
数据抽象
RDD是一个抽象类,需要子类具体实现
-
不可变
RDD封装了计算逻辑,是不可改变的,如果想要改变只能产生新的RDD封装新的计算逻辑
-
可分区、并行计算
3.1.2 RDD的核心属性
RDD共有5个核心属性
# RDD.scala
* Internally, each RDD is characterized by five main properties:
*
* - A list of partitions
* - A function for computing each split
* - A list of dependencies on other RDDs
* - Optionally, a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned)
* - Optionally, a list of preferred locations to compute each split on (e.g. block locations for
* an HDFS file)
-
分区列表
RDD数据结构中存在分区列表,用于执行任务时并行计算,为实现分布式计算的重要属性。
/** * Implemented by subclasses to return the set of partitions in this RDD. This method will only * be called once, so it is safe to implement a time-consuming computation in it. * * The partitions in this array must satisfy the following property: * `rdd.partitions.zipWithIndex.forall { case (partition, index) => partition.index == index }` */ protected def getPartitions: Array[Partition]
-
分区计算函数
Spark在计算时,是使用分区函数对每一个分区进行计算
/** * :: DeveloperApi :: * Implemented by subclasses to compute a given partition. */ @DeveloperApi def compute(split: Partition, context: TaskContext): Iterator[T]
-
RDD之间的依赖关系
RDD是计算模型的封装,当需求中需要将多个计算模型进行组合时,就需要将多个RDD建立依赖关系
/** * Implemented by subclasses to return how this RDD depends on parent RDDs. This method will only * be called once, so it is safe to implement a time-consuming computation in it. */ protected def getDependencies: Seq[Dependency[_]] = deps
-
分区器
当数据为KV类型数据时,可以通过设定分区器自定义数据的分区
/** Optionally overridden by subclasses to specify how they are partitioned. */ @transient val partitioner: Option[Partitioner] = None
-
首选位置(可选)
计算数据时,可以根据计算节点的状态选择不同的节点位置进行计算
/** * Optionally overridden by subclasses to specify placement preferences. */ protected def getPreferredLocations(split: Partition): Seq[String] = Nil
3.1.3 基础编程
3.1.3.1 RDD创建
在Spark中创建RDD可以分为4种:
-
从集合(内存)中创建RDD
通过parallelize和makeRDD创建RDD,makeRDD的底层是parallelize
import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} object RDD_M