spark相关


最后更新
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()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值