传送门:
定义:Apache Spark是用于大规模数据(large-scala data)处理的统一(unified)分析引擎(数据处理分析引擎)。
RDD 是一种分布式内存抽象,其使得程序员能够在大规模集群中做内存运算,并且有一定的容错方式。而这也
是整个 Spark 的核心数据结构,Spark 整个平台都围绕着RDD进行。
"分而治之"的思想,对数据的处理与计算,都是进行分区,对数据进行分布式任务分配来完成大规模数据集的计算。
Spark 借鉴了 MapReduce 思想发展而来,保留了其分布式并行计算的优点并改进了其明显的缺陷,让中间数据存储在内存中提高了运行速度、并提供丰富的操作数据的API提高了开发速度。
Spark是一款分布式内存计算的统一分析引擎。其特点就是对任意类型的数据进行自定义计算。Spark可以计算:结构化、半结构化、非结构化等各种类型的数据结构,同时也支持使用Python、Java、Scala、R以及SQL语言去开发应用程序计算数据。Spark的适用面非常广泛,所以,被称之为 统一的(适用面广)的分析引擎(数据处理)。
Spark解决什么问题? 海量数据的计算,可以进行离线批处理和实时流计算
注:
线程是CPU的基本调度单位
一个进程一般包含多个线程, 一个进程下的多个线程共享进程的资源
不同进程之间的线程相互不可见
线程不能独立执行
一个线程可以创建和撤销另外一个线程
尽管Spark相对于Hadoop而言具有较大优势,但Spark并不能完全替代Hadoop
Spark与Hadoop融合在一起,形成HDFS+YARN+Spark。仍然需要使用Hadoop中的存储(HDFS)和资源管理调度(YARN)。
运行速度快
由于Apache Spark支持内存计算,并且通过DAG(有向无环图)执行引擎支持无环数据流,所以官方宣称其在内存中的运算速度要比Hadoop的MapReduce快100倍,在硬盘中要快10倍。
Spark处理数据与MapReduce处理数据相比,有如下两个不同点:
- 其一、Spark处理数据时,可以将中间处理结果数据存储到内存中;
- 其二、Spark 提供了非常丰富的算子(API), 可以做到复杂任务在一个Spark 程序中完成。
易于使用
Spark支持了包括 Java、Scala、Python 、R和SQL语言在内的多种语言
通用性强
在 Spark 的基础上,Spark 还提供了包括Spark SQL、Spark Streaming、MLib 及GraphX在内的多个工具库,我们可以在一个应用中无缝地使用这些工具库。
- Spark SQL模块:通过SQL语言来完成结构化数据处理
- Spark Streaming模块:完成流式数据处理
- MLib模块:完后机器学习的数据计算
- GraphX模块:完成图计算
多种模式运行
Spark 支持多种运行方式,包括在 Hadoop 和 Mesos 上,也支持 Standalone的独立运行模式,同时也可以运行在云Kubernetes——容器(Spark 2.3开始支持)上。对于数据源而言,Spark 支持从HDFS、HBase、Cassandra 及 Kafka 等多种途径获取数据。
- 文件系统: LocalFS、HDFS、Hive、text、parquet、orc、json、csv
- 数据库RDBMs: mysql、Orade、mssql
- NOSQL数据库:HBase、ES、Redisiv
- 消息对象:Kafka
整个Spark 框架模块包含: SparkCore、Spark SQL、SparkStreaming、Spark GraphX、Spark MLlib,而后四项的能力都是建立在核心引擎之上。
Spark提供多种运行模式,包括:本地模式、集群模式和云模式
注:正常情况下Executor是干活的角色,不过在特殊场景下(Local模式)Driver可以即管理又干活
使用三台Linux虚拟机服务器来学习,三台虚拟机的功能分别是:
我使用的是课程中提供的虚拟机,没有自己搭建
课程资料中提供了3台虚拟机的压缩包, 同学们解压后导入VMWare即可
软件存放在/export/software
组件安装存放/export/server/
本质:启动一个JVM Process进程(一个进程里面有多个线程),执行任务Task。简单来讲,Local模式就是以一个独立进程配合其内部线程(每个线程模拟一个Spark服务器)来提供完成Spark运行时环境.。Local模式可以通过spark-shell/pyspark/spark-submit等来开启。
Local下的角色分布:
Driver也算一种特殊的Executor, 只不过多数时候, 我们将Executor当做纯Worker对待, 这样和Driver好区分(一类是管理 一类是工人)
注意: Local模式只能运行一个Spark程序, 如果执行多个Spark程序, 那就是由多个相互独立的Local进程在执行
配置Spark由如下5个环境变量需要设置,这5个环境变量 都需要配置在:
/etc/profile
中
spark中代码展示如下:
bin/pyspark:利用bin目录下的pyspark来进行测试
bin/pyspark 程序, 可以提供一个
交互式
的 Python解释器环境, 在这里面可以写普通python代码让spark执行
这一步碰到一个错误:开启hadoop集群后,可以正常使用了
WEB UI (4040):
Spark的任务在运行后,会在Driver所在机器绑定到4040端口,提供当前任务的监控页面供查看。如果4040端口被占用, 会顺延到4041 … 4042…
输入:服务器ip:4040
即可打开:
打开监控页面后, 可以发现 在程序内仅有一个Driver。因为我们是Local模式, Driver即管理 又干活。
spark-submit
利用bin目录下的spark-submit来提交写好的代码到spark集群中运行
总结:pyspark/spark-shell/spark-submit 对比
Standalone模式是Spark自带的一种集群模式,Standalone模式是真实地在多个机器之间搭建Spark集群的环境,完全可以利用该模式搭建多机器集群,用于实际的大数据处理。StandAlone 是完整的Spark运行环境,其中:
如图所示,Spark集群是一个Master进程和3个Worker进程,可以开启非常多的任务。诸如:一个任务Driver以及负责该任务的Executor;二个任务Driver以及负责这两个任务的Executor
集群规划如下:
node1运行: Spark的Master进程 和 1个Worker进程
node2运行: spark的1个worker进程
node3运行: spark的1个worker进程
整个集群提供: 1个master进程 和 3个worker进程
安装步骤:
在所有机器安装Python(Anaconda),都创建pyspark
虚拟环境 以及安装虚拟环境所需要的包pyspark jieba pyhive
在所有机器配置环境变量
将/etc/profile
和/root/.bashrc
文件中都如node1配置
配置配置文件
在/export/server/spark/conf中进行如下操作:
(pyspark_env) [root@node1 conf]# mv workers.template workers
node1.itcast.cn
node2.itcast.cn
node3.itcast.cn
(pyspark_env) [root@node1 conf]# mv spark-env.sh.template spark-env.sh
(pyspark_env) [root@node1 conf]# vim spark-env.sh
#!/usr/bin/env bash
JAVA_HOME=/export/server/jdk1.8.0_241/
HADOOP_CONF_DIR=/export/server/hadoop/etc/hadoop/
YARN_CONF_DIR=/export/server/hadoop/etc/hadoop/
export SPARK_MASTER_HOST=node1.itcast.cn
export SPARK_MASTER_PORT=7077
SPARK_MASTER_WEBUI_PORT=8080
SPARK_WORKER_CORES=2
SPARK_WORKER_MEMORY=2g
SPARK_WORKER_PORT=7078
SPARK_WORKER_WEBUI_PORT=8081
SPARK_HISTORY_OPTS="-Dspark.history.fs.logDirectory=hdfs://node1.itcast.cn:8020/sparklog/ -Dspark.history.fs.cleaner.enabled=true"
SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER -Dspark.deploy.zookeeper.url=node1.itcast.cn:2181,node2.itcast.cn:2181,node3.itcast.cn:2181 -Dspark.deploy.zookeeper.dir=/spark-ha"
在HDFS上创建程序运行历史记录存放的文件夹:sparklog
(pyspark_env) [root@node1 conf]# hadoop fs -mkdir /sparklog
(pyspark_env) [root@node1 conf]# hadoop fs -chmod 777 /sparklog
(pyspark_env) [root@node1 conf]# hadoop fs -ls /
Found 7 items
drwxr-xr-x - root supergroup 0 2021-10-24 23:07 /flink
drwxr-xr-x - root supergroup 0 2021-10-24 17:38 /hbase
drwxr-xr-x - root supergroup 0 2021-10-24 16:02 /spark
drwxrwxrwx - root supergroup 0 2022-06-17 20:45 /sparklog
drwxr-xr-x - root supergroup 0 2021-10-24 22:19 /test
drwxrwx--- - root supergroup 0 2021-10-24 16:10 /tmp
drwxr-xr-x - root supergroup 0 2021-10-24 16:09 /user
配置spark-defaults.conf文件:
(pyspark_env) [root@node1 conf]# mv spark-defaults.conf.template spark-defaults.conf
(pyspark_env) [root@node1 conf]# vim spark-defaults.conf
spark.eventLog.enabled true
spark.eventLog.dir hdfs://node1.itcast.cn:8020/sparklog/
spark.eventLog.compress true
spark.yarn.historyServer.address node1.itcast.cn:18080
(pyspark_env) [root@node1 conf]# mv log4j.properties.template log4j.properties
(pyspark_env) [root@node1 conf]# vim log4j.properties
# Set everything to be logged to the console
log4j.rootCategory=WARN, 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 WARN. 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=WARN
# Settings to quiet third party logs that are too verbose
log4j.logger.org.sparkproject.jetty=WARN
log4j.logger.org.sparkproject.jetty.util.component.AbstractLifeCycle=ERROR
这个文件的修改不是必须的,为什么修改为WARN。因为Spark是个话唠,会疯狂输出日志,设置级别为WARN只输出警告和错误日志,
将Spark安装文件夹分发到其他服务器上
(pyspark_env) [root@node1 server]#scp -r spark-3.1.2-bin-hadoop3.2 node2 : /export/server/
(pyspark_env) [root@node1 server]#scp -r spark-3.1.2-bin-hadoop3.2 node3 :/export/server/
分别在其他服务器上建立软链接
(pyspark_env) [root@node2 server]#ln -s /export/server/spark-3.1.2-bin-hadoop3.2 /export/server/spark
(pyspark_env) [root@node3 server]#ln -s /export/server/spark-3.1.2-bin-hadoop3.2 /export/server/spark
启动历史服务器:
启动spark之前需要先启动hadoop,因为spark使用hdfs文件系统作为写入日志的地方。
(pyspark_env) [root@node1 hadoop]# sbin/start-dfs.sh
Starting namenodes on [node1.itcast.cn]
Starting datanodes
Starting secondary namenodes [node2.itcast.cn]
(pyspark_env) [root@node1 hadoop]# sbin/start-yarn.sh
Starting resourcemanager
Starting nodemanagers
[root@node1 hadoop]# sbin/mr-jobhistory-daemon.sh start historyserver
WARNING: Use of this script to start the MR JobHistory daemon is deprecated.
WARNING: Attempting to execute replacement "mapred --daemon start" instead.
(pyspark_env) [root@node1 hadoop]# jps
2960 NodeManager
2771 ResourceManager
2347 DataNode
3388 JobHistoryServer
2127 NameNode
3455 Jps
(pyspark_env) [root@node1 spark]# sbin/start-history-server.sh
starting org.apache.spark.deploy.history.HistoryServer, logging to /export/server/spark/logs/spark-root-org.apache.spark.deploy.history.HistoryServer-1-node1.itcast.cn.out
启动Spark的Master和Worker进程:
# 启动全部master和worker
sbin/start-all.sh
# 或者可以一个个启动:
# 启动当前机器的master
sbin/start-master.sh
# 启动当前机器的worker
sbin/start-worker.sh
# 停止全部
sbin/stop-all.sh
# 停止当前机器的master
sbin/stop-master.sh
# 停止当前机器的worker
sbin/stop-worker.sh
(pyspark_env) [root@node1 spark]# sbin/start-all.sh
starting org.apache.spark.deploy.master.Master, logging to /export/server/spark/logs/spark-root-org.apache.spark.deploy.master.Master-1-node1.itcast.cn.out
node3.itcast.cn: starting org.apache.spark.deploy.worker.Worker, logging to /export/server/spark/logs/spark-root-org.apache.spark.deploy.worker.Worker-1-node3.itcast.cn.out
node2.itcast.cn: starting org.apache.spark.deploy.worker.Worker, logging to /export/server/spark/logs/spark-root-org.apache.spark.deploy.worker.Worker-1-node2.itcast.cn.out
node1.itcast.cn: starting org.apache.spark.deploy.worker.Worker, logging to /export/server/spark/logs/spark-root-org.apache.spark.deploy.worker.Worker-1-node1.itcast.cn.out
(pyspark_env) [root@node1 spark]# jps
4049 DataNode
7873 Master
3832 NameNode
4664 NodeManager
7976 Worker
7737 HistoryServer
4475 ResourceManager
8028 Jps
## 可以发现spark的Master和Worker进程
使用客户端工具进行测试。
bin/pyspark
[root@node1 bin]# ./pyspark --master spark://node1.itcast.cn:7077
可以发现:Running Applications中有一个正在运行的任务
进入该任务,可以看到3个Worker:
点击Application Detail UI,可以看到在spark任务中运行的多个子任务
注意:
bin/spark-submit (PI)
[root@node1 bin]# ./spark-submit --master spark://node1.itcast.cn:7077 /export/server/spark/examples//src/main/python/pi.py 100
bin/spark-shell
[root@node1 bin]# spark-shell --master spark://node1.itcast.cn:7077
在Spark中运行单词计数,
登录4040端口,查看任务运行状态,图中显示一个Application有一个Job(可以有多个)。
可以发现一个Job分为多个阶段
点击某一阶段,可以发现一个阶段又可以有多个任务并行运行。
切换到【Executors】Tab页面
从图中可以看到Spark Application运行到集群上时,由两部分组成:Driver Program和Executors。
Driver Program
Executors
用户程序从最开始的提交到最终的计算执行,需要经历以下几个阶段:
用户程序创建 SparkContext 时,新创建的 SparkContext 实例会连接到 ClusterManager。 Cluster Manager 会根据用户提交时设置的 CPU 和内存等信息为本次提交分配计算资源,启动 Executor。
Driver会将用户程序划分为不同的执行阶段Stage,每个执行阶段Stage由一组完全相同Task组成,这些Task分别作用于待处理数据的不同分区。在阶段划分完成和Task创建后, Driver会向Executor发送 Task;
Executor在接收到Task后,会下载Task的运行时依赖,在准备好Task的执行环境后,会开始执行Task,并且将Task的运行状态汇报给Driver;
Driver会根据收到的Task的运行状态来处理不同的状态更新。 Task分为两种:一种是Shuffle Map Task,它实现数据的重新洗牌,洗牌的结果保存到Executor 所在节点的文件系统中;另外一种是Result Task,它负责生成结果数据;
Driver 会不断地调用Task,将Task发送到Executor执行,在所有的Task 都正确执行或者超过执行次数的限制仍然没有执行成功时停止;
Spark Application程序运行时三个核心概念:Job、Stage、Task,说明如下:
监控页面有4040,8080,18080,它们有何区别吗?
- 4040: 是一个运行的Application在运行的过程中临时绑定的端口,用以查看当前任务的状态。4040被占用会顺延到4041、4042等。4040是一个临时端口,当前程序运行完成后, 4040就会被注销
- 8080: 默认是StandAlone下,Master角色(进程)的WEB端口,用以查看当前Master(集群)的状态
- 18080: 默认是历史服务器的端口,由于每个程序运行完成后,4040端口就被注销了。 在以后想回看某个程序的运行状态就可以通过历史服务器查看,历史服务器长期稳定运行,可供随时查看被记录的程序的运行过程。
Spark Standalone集群是Master-Slaves架构的集群模式,和大部分的Master-Slaves结构集群一样,存在着Master单点故障(SPOF)的问题。如何解决这个单点故障的问题,Spark提供了两种方案:
前提: 确保Zookeeper 和 HDFS 均已经启动
先在spark-env.sh
中, 删除: SPARK_MASTER_HOST=node1.itcast.cn
原因: 配置文件中固定master是谁, 那么就无法用到zk的动态切换master功能了.
在spark-env.sh
中, 增加:
SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER -Dspark.deploy.zookeeper.url=node1:2181,node2:2181,node3:2181 -Dspark.deploy.zookeeper.dir=/spark-ha"
# spark.deploy.recoveryMode 指定HA模式 基于Zookeeper实现
# 指定Zookeeper的连接地址
# 指定在Zookeeper中注册临时节点的路径
将spark-env.sh 分发到每一台服务器上
scp spark-env.sh node2:/export/server/spark/conf/
scp spark-env.sh node3:/export/server/spark/conf/
停止当前StandAlone集群
sbin/stop-all.sh
启动集群:
# 在node1上 启动一个master 和全部worker
sbin/start-all.sh
# 注意, 下面命令在node2上执行
sbin/start-master.sh
# 在node2上启动一个备用的master进程
master主备切换:
提交一个spark任务到当前alive
master上:
bin/spark-submit --master spark://node1:7077 /export/server/spark/examples/src/main/python/pi.py 1000
在提交成功后, 将alivemaster直接kill掉,不会影响程序运行:
当新的master接收集群后, 程序继续运行, 正常得到结果.
结论:HA模式下, 主备切换 不会影响到正在运行的程序.
最大的影响是 会让它中断大约30秒左右.
对于企业来说,在已有YARN集群的前提下,在单独准备Spark StandAlone集群,对资源的利用就不高。 所以,在企业中,多数场景下,会将Spark运行到YARN集群中,提高资源利用率。YARN本身是一个资源调度框架,负责对运行在内部的计算框架进行资源调度管理。作为典型的计算框架,Spark本身也是直接运行在YARN中,并接受YARN的调度的。所以,对于Spark On YARN,无需部署Spark集群,只要找一台服务器,充当Spark的客户端,即可提交任务到YARN集群中运行。
为什么需要Spark on YARN?
提高资源利用率,在已有YARN的场景下让Spark收到YARN的调度,可以更好的管控资源,提高利用率并方便管理。
资源管理层面:
任务运行层面:
简单来讲,Spark On Yarn就是将Driver和Executor运行在容器内部。我们只需要关心任务运行层面,资源管理层面Spark不在管理,有YARN统一协调。
Spark On Yarn需要:
只需要确保在spark-env.sh 配置以下环境变量即可
- HADOOP_CONF_DIR
- YARN_CONF_DIR
注意: 交互式环境 pyspark 和 spark-shell 无法运行 cluster模式
–deploy-mode 选项是指定部署模式, 默认是 客户端模式
- client就是客户端模式
- cluster就是集群模式
–deploy-mode 仅可以用在YARN模式下
bin/pyspark
[root@node1 spark]# bin/pyspark --master yarn
bin/spark-shell
bin/spark-shell --master yarn --deploy-mode client|cluster
注意: 交互式环境 pyspark 和 spark-shell 无法运行 cluster模式
bin/spark-submit (PI)
[root@node1 spark]# bin/spark-submit --master yarn /export/server/spark/examples/src/main/python/pi.py 100
Spark On YARN是有两种运行模式的,一种是Cluster模式,一种是Client模式。这两种模式的区别就是Driver运行的位置。
client模式
[root@node1 spark]# bin/spark-submit --master yarn --deploy-mode client --driver-memory 512m --executor-memoryy 512m --num-executors 3 --total-executor-cores 3 /export/server/spark/examples/src/main/python/pi.py 100
cluster模式
[root@node1 spark]# bin/spark-submit --master yarn --deploy-mode cluster --driver-memory 512m --executor-memory 512m --num-executors 3 --total-executor-cores 3 /export/server/spark/examples/src/main/python/pi.py 100
Client模式和Cluster模式最本质的区别是:Driver程序运行在哪里。
Client模式:学习测试时使用,生产不推荐(要用也可以,性能略低,稳定性略低)。
Cluster模式:生产环境中使用该模式
在YARN Client模式下,Driver在任务提交的本地机器上运行,示意图如下:
具体流程步骤如下:
在YARN Cluster模式下,Driver运行在NodeManager Contanier中,此时Driver与AppMaster合为一体,示意图如下:
具体流程步骤如下:
客户端工具我们可以用的有:
这4个客户端工具的参数基本通用.
以spark-submit 为例:
bin/spark-submit --master spark://node1:7077 xxx.py
Usage: spark-submit [options] <app jar | python file | R file> [app arguments]
Usage: spark-submit --kill [submission ID] --master [spark://...]
Usage: spark-submit --status [submission ID] --master [spark://...]
Usage: spark-submit run-example [options] example-class [example args]
Options:
--master MASTER_URL spark://host:port, mesos://host:port, yarn,
k8s://https://host:port, or local (Default: local[*]).
--deploy-mode DEPLOY_MODE 部署模式 client 或者 cluster 默认是client
--class CLASS_NAME 运行java或者scala class(for Java / Scala apps).
--name NAME 程序的名字
--jars JARS Comma-separated list of jars to include on the driver
and executor classpaths.
--packages Comma-separated list of maven coordinates of jars to include
on the driver and executor classpaths. Will search the local
maven repo, then maven central and any additional remote
repositories given by --repositories. The format for the
coordinates should be groupId:artifactId:version.
--exclude-packages Comma-separated list of groupId:artifactId, to exclude while
resolving the dependencies provided in --packages to avoid
dependency conflicts.
--repositories Comma-separated list of additional remote repositories to
search for the maven coordinates given with --packages.
--py-files PY_FILES 指定Python程序依赖的其它python文件
--files FILES Comma-separated list of files to be placed in the working
directory of each executor. File paths of these files
in executors can be accessed via SparkFiles.get(fileName).
--archives ARCHIVES Comma-separated list of archives to be extracted into the
working directory of each executor.
--conf, -c PROP=VALUE 手动指定配置
--properties-file FILE Path to a file from which to load extra properties. If not
specified, this will look for conf/spark-defaults.conf.
--driver-memory MEM Driver的可用内存(Default: 1024M).
--driver-java-options Driver的一些Java选项
--driver-library-path Extra library path entries to pass to the driver.
--driver-class-path Extra class path entries to pass to the driver. Note that
jars added with --jars are automatically included in the
classpath.
--executor-memory MEM Executor的内存 (Default: 1G).
--proxy-user NAME User to impersonate when submitting the application.
This argument does not work with --principal / --keytab.
--help, -h 显示帮助文件
--verbose, -v Print additional debug output.
--version, 打印版本
Cluster deploy mode only(集群模式专属):
--driver-cores NUM Driver可用的的CPU核数(Default: 1).
Spark standalone or Mesos with cluster deploy mode only:
--supervise 如果给定, 可以尝试重启Driver
Spark standalone, Mesos or K8s with cluster deploy mode only:
--kill SUBMISSION_ID 指定程序ID kill
--status SUBMISSION_ID 指定程序ID 查看运行状态
Spark standalone, Mesos and Kubernetes only:
--total-executor-cores NUM 整个任务可以给Executor多少个CPU核心用
Spark standalone, YARN and Kubernetes only:
--executor-cores NUM 单个Executor能使用多少CPU核心
Spark on YARN and Kubernetes only(YARN模式下):
--num-executors NUM Executor应该开启几个
--principal PRINCIPAL Principal to be used to login to KDC.
--keytab KEYTAB The full path to the file that contains the keytab for the
principal specified above.
Spark on YARN only:
--queue QUEUE_NAME 指定运行的YARN队列(Default: "default").