文章目录
- 简介
- 安装
- hdfs命令
- 概念
- 流程
- RDD函数
- 运行模式
- standalone运行模式
- yarn运行模式
- 流处理
- 监控端口
- 监控文件
- 停止任务
- 问题
最后更新
2022.03.09
简介
分布式计算的前提是 计算的数据 分区后 各区无状态,适合用spark分布式管理
分布式计算的前提是数据最好是分布式存储 然后各个算子(算法)计算的结果与结果之间不相关(无依赖,无状态)
一般写spark可以用java、scala、python
spark有固定的格式,需要创建任务
只要部署好spark,然后任务在主节点提交就可以了,spark框架可以自主将任务分发到不通节点
设置好需要的资源就可以了,比如设置多少core多少内存啥的,启动命令就可以设置
流程:数据存起来 spark拿出来 分区 计算 汇总结果
安装
下载JDK
yum -y update 更新yum
yum -y install java-1.8.0-openjdk*
java -version 1.8.0
安装hadoop
tar -zxvf hadoop-3.2.2.tar.gz
mv hadoop-3.2.2/ /usr/local/hadoop
cd /usr/local/hadoop/
./bin/hadoop version 3.2.2
安装spark
tar -zxvf spark-3.2.1-bin-hadoop3.2.tgz
mv spark-3.2.1-bin-hadoop3.2/ /usr/local/spark
cd /usr/local/spark/
cp ./conf/spark-env.sh.template ./conf/spark-env.sh
加一行 export SPARK_DIST_CLASSPATH=$(/usr/local/hadoop/bin/hadoop classpath)
配置环境变量(写在~./bashrc里每次启动都有)
export HADOOP_HOME=/usr/local/hadoop
export SPARK_HOME=/usr/local/spark
export PATH=$HADOOP_HOME/bin:$SPARK_HOME/bin:$JAVA_HOME/bin:$PATH
启动spark
./sbin/start-all.sh
此时主节点有进程Master,子节点有Worker
jps 查看本地运行着几个java程序&大数据
12257 Master
12345 Jps
11485 SparkSubmit
hdfs命令
hdfs dfs -mkdir /test 建文件夹
hdfs dfs -put x.xml /test 上传文件
hdfs dfs -put hd/ /test 上传文件夹
hdfs dfs -copyFromLocal x.xml /test 复制文件(只能复制本地)
hdfs dfs -ls /test 查看目录
hdfs dfs -cat /test/x.xml 查看文件
hdfs dfs -get /test/x.xml /usr 下载文件
hdfs dfs -rm -r /test 删除文件(夹)
概念
RDD算子,DAG有向无环图,job作业,stage阶段-作业的基本调度单位,task任务-一个阶段包含多个任务,driver驱动器-提交spark代码的程序,executor执行器-应用提交执行,workernode工作节点-负责执行的机器节点,application驱动器和执行器运行task为一个应用
spark可以运行在自带集群,也可以提交到外部集群,通过spark-submit指定集群位置
流程:
应用提交,启动驱动器创建sparkContext对象(对应用唯一),负责资源调度和监控任务
资源管理器收到申请,为执行器分配资源,启动执行器,sContext对象根据rdd构造DAG,DAG调度划分多个阶段-包含各自的任务,任务调度发给执行器运行,执行完反馈给调度器,sContext对象调用stop,释放资源,结束
流程
在./examples/src/main目录下有一些Spark的示例程序,有Scala、Java、Python、R等语言的版本。我们可以先运行一个示例程序SparkPi(计算π的近似值),执行命令 ./bin/run-example SparkPi
以下为log
2022-02-24 INFO util.Utils: Successfully started service 'sparkDriver' on port 11226.
在端口11226上成功启动服务'sparkDriver'
2022-02-24 INFO util.Utils: Successfully started service 'SparkUI' on port 4040.
在端口4040上成功启动服务“SparkUI”。
2022-02-24 INFO spark.SparkContext: Added JAR file:///usr/local/spark/examples/jars/s.jar at spark://Template:11226/jars/sp.jar with timestamp 1898
SparkContext在spark://Template:11226/jars/sp.jar中增加了JAR文件
2022-02-24 INFO executor.Executor: Starting executor ID driver on host Template
Executor:主机模板上启动的Executor ID驱动
2022-02-24 INFO executor.Executor: Fetching spark://Template:11226/jars/spark-examples.jar with timestamp 198
执行
2022-02-24 INFO client.TransportClientFactory: Successfully created connection to Template/192.168.6.103:11226 after 38 ms
成功连接到sd
2022-02-24 INFO spark.SparkContext: Starting job: reduce at SparkPi.scala:38
开始job
中间获得job的分区,提交ResultStage(包括rdd算子),存储在内存,在DAG调度中创建广播,在Task调度添加任务和配置文件,在分区启动任务
Executor Running task执行器运行任务
完成任务阶段 结果发送给驱动程序result sent to driver
Task调度移除已经完成的任务
DAG调度说,ResultStage已完成
2022-02-24 INFO scheduler.DAGScheduler: Job 0 is finished. Cancelling potential speculative or zombie tasks for this job
job完成,取消此任务
2022-02-24 INFO scheduler.TaskSchedulerImpl: Killing all running tasks in stage 0: Stage finished
杀了任务,任务结束
2022-02-24 INFO scheduler.DAGScheduler: Job 0 finished: reduce at SparkPi.scala:38, took 0.911174 s
xx任务完成
Pi is roughly 3.144075720378602
结果
2022-02-24 INFO ui.SparkUI: Stopped Spark web UI at http://Template:4040
2022-02-24 INFO spark.MapOutputTrackerMasterEndpoint: MapOutputTrackerMasterEndpoint stopped!
2022-02-24 INFO memory.MemoryStore: MemoryStore cleared
2022-02-24 INFO storage.BlockManager: BlockManager stopped
2022-02-24 INFO storage.BlockManagerMaster: BlockManagerMaster stopped
2022-02-24 INFO scheduler.OutputCommitCoordinator$OutputCommitCoordinatorEndpoint: OutputCommitCoordinator stopped!
2022-02-24 INFO spark.SparkContext: Successfully stopped SparkContext
2022-02-24 INFO util.ShutdownHookManager: Shutdown hook called
停止Spark webUI、MapOutputTrackerMasterEndpoint、清除缓存、BlockManager、OutputCommitCoordinator、SparkContext,关闭连接
python版运行 ./bin/spark-submit examples/src/main/python/pi.py
log和上面都一样的
直接python3 pi.py 也一样出来结果
import sys
from random import random
from operator import add
from pyspark.sql import SparkSession
if __name__ == "__main__":
spark = SparkSession.builder.appName("PythonPi").getOrCreate()
partitions = int(sys.argv[1]) if len(sys.argv) > 1 else 2
n = 100000 * partitions
def f(_):
x = random() * 2 - 1
y = random() * 2 - 1
return 1 if x ** 2 + y ** 2 <= 1 else 0
count = spark.sparkContext.parallelize(range(1, n + 1), partitions).map(f).reduce(add)
print("Pi is roughly %f" % (4.0 * count / n))
spark.stop()
指定Spark提交用Python3版本
conf/spark_env.sh 增加
PYSPARK_PYTHON='/usr/local/python3/bin/python3' # p3可执行文件
RDD函数
进入spark-shell
cd /usr/local/spark
./bin/spark-shell
scala >
from pyspark import SparkContext
sc=SparkContext()
print(sc.version) 3.2.1
sc创建时,py会和JVM通信,由JVM创建sparkContext对象
./bin/pyspark,启动shell窗口,已经建好了sparkcontext对象,可以直接用
读取文件,sc.textFile(路径),默认是从HDFS读取,从本地读取需加’file://’
RDD算子一般只是记录-惰性,.collect()时才开始计算-将数据收集到一起并返回给驱动器节点
rd=sc.parallelize([1,2],4),数组转为RDD,数组为[obj,obj]里面可以是任意类型,第二个参数是分区-集群中控制分区减少数据的传输有助提高性能
rd.count() 2,元素个数
rd.id() 唯一id
rd.getNumPartitions() 3 分区数
rd.keys()获取key
rd.values()获取value
rdd.reduce(lambda x, y: x + y) 相加,还有max min mean sum等数学函数
rd.map(lambda ).collect() map接受一个函数对每个元素做函数运算-返回列表,filter一样,flatMap是返回列表序列
groupByKey() 聚合,得到可迭代对象,需要map再转为list,groupBy指定聚合
reduceByKey() 配置聚合计算
sortByKey()排序,sortByKey(False)逆序从大到小排
rdd.sortBy(lambda x: x[1], False) 指定排序
rd1.union(rd2) 合并并集,intersection交集,subtract差集
rd1.zip(rd2) 同py的zip,变成列表元组
rd1.zipWithIndex() 和下标zip
rdd.keyBy(lambda x: f"h_{x}") 倒着zip,[('h_1',1),('h_2',2)]
distinct()去重
rdd.cache() 持久化,缓存rdd,具有容错性
不常用:join同sql,mapPartitions分区map,coalesce改变分区数,repartition重新分区,glom分区数据列表,pipe对元素执行linue命令
...等RDD函数
运行模式
py提交到spark上面运行,也可以通过 python3 x.py 执行,但最好的做法是提交到spark上运行
pyspark-submit --master xxx --name aaa cc.py arg1 arg2
xxx本地模式local[*](不指定master默认就是local),aaa项目文件目录或zip egg包,后面4个参数可以只有py
standalone运行模式
一台机器是master,剩下的属于worker(要在spark-env.sh中添加JAVA_HOME)
在sbin目录启动spark集群,先执行start-master.sh,然后执行start-slaves.sh,或者直接执行start-all.sh
submit提交作业把local[*]改成spark集群:–master spark://127.0.0.1:7077 就完事了
yarn运行模式
灵活的调度,yarn 是使用 spark 的公司采用的最多的一个模式
使用 yarn 模式,spark充当一个客户端,它需要做的就是提交作业到yarn上去执行,只需要一个节点提交作业即可,不需要spark集群(不需启动master和worker)
提交任务直接–master local换成–master yarn即可
想提交到yarn上去执行,那么必须配置HADOOP_CONF_DIR或者YARN_CONF_DIR,就是Hadoop配置文件所在的目录,export HADOOP_CONF_DIR=/opt/hadoop-2.6.0-cdh5.15.1/etc/hadoop
yarn必须要已经启动才可以,输入jps,要能看到NodeManager和ResourceManager
提交作业有两种模式,–deploy-mode client(提交作业的进程是不能停止的,否则作业就挂了),–deploy-mode cluster(提交完作业,进程就可以断开了,因为driver是运行在am里面的)
流处理
静态数据批处理直接存在HDFS上,动态数据流处理,由其他程序处理然后存入数据仓库-短期内不会改变
流处理方法:storm纯粹流处理。flink分布式大数据流处理。Spark Streaming是spark核心组件之一,将流式计算分解成一系列小的批处理作业(DStream离散化流),支持多种数据源,如Kafka,Flume等。structured streaming结构化流上个的升级版,是运行在性能更好的sparkSQL引擎上的,其他和上个无异,一般生产多还是用上个
nc -lk 9999监听,打开新窗口spark startall运行流处理示例
./bin/spark-submit examples/src/main/python/streaming/network_wordcount.py localhost 9999
nc窗口输入可在流处理log得到结果,具体内容流程见示例py
监控端口
import sys
from pyspark import SparkContext
from pyspark.streaming import StreamingContext
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Usage: network_wordcount.py <hostname> <port>", file=sys.stderr)
sys.exit(-1)
sc = SparkContext(appName="PythonStreamingNetworkWordCount")
ssc = StreamingContext(sc, 1)
lines = ssc.socketTextStream(sys.argv[1], int(sys.argv[2]))
counts = lines.flatMap(lambda line: line.split(" "))\
.map(lambda word: (word, 1))\
.reduceByKey(lambda a, b: a+b)
counts.pprint()
ssc.start()
ssc.awaitTermination()
注释
from pyspark.streaming import StreamingContext,流程序入口
ssc = StreamingContext(sc, 1) 流数据划分时间间隔1秒
lines = ssc.socketTextStream(sys.argv[1], int(sys.argv[2])) 传入主机和端口建立连接,如果监控文件系统,就调用textFileStream
然后定义处理过程,然后调用start开始接收数据和执行(start后不能有逻辑代码),一个应用只能建一个streamingcontext对象
awaitTermination等待处理完成,如果调用stop,也会停止spark进程sparkcontext,若只需停streaming,调用stop时stopSparkContext=False
监控文件
from pyspark import SparkContext
from pyspark.streaming import StreamingContext
if __name__ == "__main__":
sc = SparkContext(appName="HDFSfilesteam")
ssc = StreamingContext(sc, 10)
lines = ssc.textFileStream("/bd/st")
counts = lines.flatMap(lambda line: line.split(" "))\
.map(lambda x: (x, 1))\
.reduceByKey(lambda a, b: a+b)
counts.pprint()
ssc.start()
ssc.awaitTermination()
python3运行上py,每10秒触发一次计算
hdfs在/bd/st/上传一个文件,内容是 he hb he
(‘he’, 2)
(‘hb’, 1)
停止任务
def doo(x):
import time
time.sleep(100)
return [sum(x),min(x)]
from pyspark import SparkContext
#import pyspark.streaming
if __name__ == "__main__":
import os
print(os.getpid())
# from pyspark import SparkConf
# conf = SparkConf().setMaster("spark://192.168.6.103:7077").setAppName("Fisrt")
# sc = SparkContext(conf=conf)
sc = SparkContext(appName="PyStream")
rd=sc.parallelize([(1,4),(2,3,4)],2)
c=rd.map(doo).collect()
print('zzz = ',c,type(c))
sc.stop()
运行了一个sleep100秒的程序,./bin/spark-submit zzz/tepp.py ,产生5个进程
os.getpid()获取的p3 x.py的进程号,kill后,任务就停止了,sparkcontext stop
问题
没权限
su - hdfs 切用户
py4j.protocol.Py4JError: org.apache.spark.api.python.PythonUtils.isEncryptionEnabled does not exist in the JVM
添加两行代码即可
import findspark
findspark.init()