Spark 基础知识-02

目录

一、Spark ON YARN模式环境搭建(主流)

1、Spark ON YARN的运行原理

2、Spark ON YARN模式部署和测试

二、Spark ON YARN的运行模式

1、Cluster和Client的区别

2、演示

3、两种模式任务提交流程

三、PySpark类库

四、本机开发环境搭建

五、RDD的介绍

1、RDD的定义

2、RDD的五大特性

3、HelloWorld案例分析

六、RDD的常见API算子

1、RDD的创建

2、RDD的算子


一、Spark ON YARN模式环境搭建(主流)

1、Spark ON YARN的运行原理

        在企业中,多数场景下,会将Spark运行到YARN集群中。YARN本身是一个资源调度框架,负责对运行在内部的计算框架进行资源调度管理。Spark作为典型的计算框架,其本身也可以直接运行在YARN中,并接受YARN的调度,本质上就是用Spark取代MR。对于Spark ON YARN模式,无需部署Spark集群,只需要找一台服务器,充当Spark的客户端,即可提交任务到YARN集群中运行。 

        在Standalone中Master负责对集群资源进行管理,Worker负责对当前机器资源进行管理。但是在Spark ON YARN模式下,资源调度任务全部由YARN取代,即Master角色由YARN的ResourceManage担任,Worker角色由YARN的NodeManage担任,Driver角色在YARN容器内或提交任务的客户端进程中(可以手动选择),Executor运行在YARN提供的容器中。

         Spark ON YARN的本质就是资源管理全部由YARN担任,Spark只作为计算框架,即Spark只负责具体任务的执行,取代以前性能低的MR,Spark的Driver和Excutor都在YARN的容器中执行。ApplicationMaster是YARN自己的任务管家不起作用(但是会与Driver绑定在一起)。也就是在Spark ON YARN模式下Spark只有Driver和Excutor两个角色。

2、Spark ON YARN模式部署和测试

前提:A、YARN集群已经安装好

           B、在整个YARN集群中有一台Spark客户端工具,比如可以使用spark-submit,将Spark程序提交到YARN容器中运行

        在这里我们已经把YARN集群安装好了,且node11,22,33都有Spark即有3台Spark客户端工具(实际生产环境中只需要1台即可)后续的测试使用node11为Spark客户端。因此Spark ON YARN就已经配置好了,就是这么简单!!!,Spark ON YARN的配置只需要保证在spark-env.sh文件中配置好HADOOP_CONF_DIR和YARN_CONF_DIR即可,这个配置我们在上文已经配置好了。

        测试:

        bin/pyspark                                                         # 以local模式启动

        bin/pyspark --master Standalone模式地址       # 以Standalone模式启动

        bin/pyspark --master yarn                                 # 以Spark ON YARN模式启动

         打开YARN的WEB UI:node11:8088

         注意与Master的WEB UI界面一样YARN的WEB UI(8088)只记录程序pysparkshell的执行情况,具体该程序下的子Job不会记录。需要打开node11:4040查看。

         在node11:8088中点击Application Master也可以打开4040端口页面,这是YARN的webproxyserver提供的web跳转服务。

二、Spark ON YARN的运行模式

1、Cluster和Client的区别

        Spark ON YARN有两种运行模式:Cluster模式 | Client模式(默认模式),者两种模式的唯一区别就是Driver的运行位置。

        Cluster模式即Driver运行在YARN容器内部,和ApplicationMaster在同一个容器内;Client模式即Driver运行在客户端进程中,比如Driver运行在spark-submit程序的进程中。

        (1)Cluster模式

        (2)Client模式

        可以看到Cluster模式Driver和Executor都在容器内部,因此通信过程一定要比Client模式这种垮集群的通信快,那Cluster模式效率高为什么还会存在Client模式呢?因为Cluster模式查看日志不太方便,在Cluster模式下Driver在容器内部,那程序/任务在运行过程中产生的日志也一定在YARN容器内部,在这种场景下,我们想要快速的验证一些结果就不太方便,需要进入到容器内部才能看到Driver的控制台输出,因此在某些场景下比如我们只是想简单的在YARN上测试一些东西,如果还要先到容器内部查看日志就不太方便了,Client模式的好处是Driver在客户端进程中,可以直接在终端查看日志信息。但是Client的性能肯定没有Cluster模式好。在Cluster模式下Driver被ApplicationMaster绑定,如果Driver出现问题,yarn会自动重新启动ApplicationMaster(Driver),如果是Client模式,Driver出现问题则无法使用了。

2、演示

        Client模式测试:

        打开node11:18080

        然后打开Executors: 

         Cluster模式测试:

        3、两种模式任务提交流程

        (1)Client模式任务提交流程

         A:本地机器一旦开启了一个Spark程序,会自动在该机器上开启一个Driver进程,然后Driver向ResourceManager申请启动ApplicationMaster。

        B:随后ResourceManager分配Container容器,在合适的NodeManager上启动ApplicationMaster,ApplicationMaster的作用就是向ResourceManager申请Executor。

        C:ApplicationMaster会向Driver询问需要什么资源,Driver会反馈需要 --num-executor 3个,--total-executor-cores 3个.....这些资源,然后ApplicationMaster会向ResourceManager申请资源。ResourceManager收到申请后,先检查资源够不够,如果资源够,会给ApplicationMaster返回资源的地址等信息。

        D:ApplicationMaster收到ResourceManager的反馈后,在指定的NodeManager上分配容器启动Executor进程。Executor进程启动后会向Driver反向注册,Executor全部注册完成后Driver就能和所有的Executors通信了,开始执行任务的main函数。

        E:之后执行到一个API算子时,会触发一个Job,并根据宽依赖划分Stage,每个Stage生成对应的TaskSet,之后将Task分发到各个Executor上执行。

        (2)Cluster模式任务提交流程

         注意:无论时Client模式还是Cluster模式,一定都是ResourceManager先在一个合适的NodeManager上分配一个容器,启动ApplicationMaster。然后ApplicationMaster得到ResourceManager的资源反馈后,再在指定的NodeManager上分配容器,启动Executor。

三、PySpark类库

        1、框架 VS 类库:它两不是同一个概念

        类库就是一推别人写好的代码,直接导入进行使用,例如python的pandas,numpy等等。

        框架是可以独立运行,并提供编程结构的一种软件产品,例如Spark就是一个独立的框架,Hive,Hadoop都是框架。前文所安装的Spark就是Spark框架,只不过该框架提供了python的API。类库像pandas用于小规模数据集的处理,框架Spark用于大规模数据集的处理。

        上文执行的bin/pyspark是一个交互式解析器程序,相当于是python的解析器,只不过其内部默认情况下有pyspark类库,默认情况下已经通过pyspark类库下的SparkContext和SparkConf构建了Spark环境sc,直接使用即可。在生产环境中一般不用pyspark解析器因为在该解析器内部只能写一行代码,通常都是在外部写好.py文件通过spark-submit提交的方式来执行,因此在外部写Spark API需要手动import pyspark。

        2、PySpark类库安装:

         在node11,22,33上都要安装pyspark类库

四、本机开发环境搭建

        本小节将在本地计算机中安装python和pycharm,后续所有的Spark API代码开发都在本地计算机的pycharm中,然后将开发的代码提交到linux系统搭建的Spark ON YARN环境中运行。Spark的运行需要python环境,因此Linux中需要安装python相关组件,本地计算机中的python用于具体的开发任务,此外Spark 的开发可能会用到hadoop的部分功能,因此需要在本地计算机配置hadoop。

        1、将hadoop-3.3.0文件中的hadoop.dll文件(hadoop的动态连接库)复制到C:\Windows\System32里面去,然后配置HADOOP_HOME环境变量指向hadoop-3.3.0文件夹位置:

         2、在本地计算机上安装python,然后安装pyspark类库(如果本身电脑有python直接用即可,如果没有安装,则可以按照在linux中的安装思路下载一个Windows系统的Anaconda3来安装python)

        3、安装好pycharm,新建一个项目:

         4、配置ssh远程python解析器:PySpark类库支持在Windows上执行,但是毕竟PySpark与Spark相关属于大数据体系,在Windows上执行会有性能问题以及一些小bug, 在Linux上执行是完美和高效的。所以,我们也可以配置好Linux上的远程解释器, 来运行Python Spark代码。

         注意配置ssh远程解析器需要pycharm专业版

         配置好以后需要等一会,此时pycharm正在进行项目同步,即建本地创建的项目同步到Linux系统下。

         在本地执行一下main.py文件本质上是在执行同步过去的main.py文件:

        5、测试

        这里的数据使用的是HDFS上的数据,当然也支持本地的数据,我们随意在本地计算机上创建一个world.txt文件,文件中输入一些单词,该文件会自动同步到Linux系统中。

         如果Linux系统中没有该文件我们可以手动同步一下:

        默认情况下是会自动同步的(保存文件或run),打开File Transfer后,对当前项目的任何文件进行修改,立刻会看到Automatic upload:

        如果发现当前的电脑没有同步,说明没有开启自动同步,需要手动配置一下:

         将数据文件直接设置为Linux系统下由Windows同步过去的文件,可以正常执行,说明确确实实本质上使用的数据就是Linux系统下的数据。

        测试使用Windows自己的python解析器:在运行代码之前需要在代码中添加下面两行代码,告诉Spark本机的python在哪里,否则会报错。 

import os
os.environ['PYSPARK_PYTHON'] = r"D:\bigdata\python\python.exe"

        可以看到正常执行了,但是会出现一些警告,这就是因为pyspark类库毕竟是与Spark相关与Windows兼容性不高,会出现各种小bug。因此建议使用Linux中的python解析器运行。

        上述添加的两行代码相当于配置一个系统变量,只不过是临时的,每次编写新的.py文件都需要添加以上两行代码,我们可以将其设置为永久:设置好以后重启pycharm就生效了,新添的那两行代码就可以去掉了。

        6、将代码提交到集群环境中运行

        注意上述的所有测试,spark的部署模式都是local[*],即上述代码的执行并不在我们搭建的Spark ON YARN集群环境上。首先将上述代码的setMaster部分删除,因为提交到集群可以通过客户端工具的参数指定master,比如spark-submit工具。所以,我们不在代码中固定master的设置,不然客户端工具参数无效, 代码的优先级是最高的。

        此外需要注意的是,将代码提交到集群环境中时,代码里面所用的数据必须是hdfs文件系统上的数据。因为集群环境下,数据会进行切片,假设有3台服务器,每天服务器都会处理一部分数据。如果使用的是本地的数据即只有1台服务器有数据,其他两台服务器本身连数据都找不到,导致无法运行。

        如果使用的是本地的python解析器,则需要手动将代码拷贝到Linux系统上,如果使用的是远程解析器,则代码会自动同步过去,直接使用即可。

         执行完成后打开18080端口,就可以看到历史信息了。

         此时只有node11节点有该数据,node22,33没有数据,再次执行spark-submit,指定excutor的数量为6个,确保node22,33工作。如果不指定excutor的数量由于当前的任务特别简单,可能该任务只会在1个excutor上执行,假设这个excutor在node11上,则也会正常执行。

         因此在集群上运行时,数据的路径一定要写hdfs路径。具体执行过程如下:

        7、分布式代码执行分析

        当所有的Executors向Driver反向注册以后,就要开始执行应用程序的main函数代码了,这里以上述单词计数程序为例分析代码执行流程。

        Python ON Spark执行原理:

        Spark框架是由java开发出来的,最初是不能在python中运行的,但是由于python越来越火热,因此Spark官方在原有Spark的基础上进行了扩充,让其支持python,如下图所示(灰色部分就是扩充的内容):

        PySpark宗旨是在不破坏Spark已有的运行时架构,在Spark架构外层包装一层Python API,借助Py4j实现Python和Java的交互,进而实现通过Python编写Spark应用程序

         在Driver端具体运行的是JVM,在Executor端具体运行的是python进程

五、RDD的介绍

1、RDD的定义

        弹性分布式数据集(Resilient Distributed Datasets,RDD)是Spark框架中的一个统一数据抽象对象,可以实现在内存中进行集群化运算,且是高度容错的。RDD是Spark的核心,它代表了一个不可变可分区,里面的元素可并行计算集合

        Datasets:一个数据集合,用于存储数据,通list,dict一样

        Distributed:RDD中的数据是分布式存储的,可用于分布式计算

        Resilient:RDD中的数据可以存储在内存中或者磁盘中,且分区数可以动态增加和减少

2、RDD的五大特性

        (1)RDD是有分区的

        RDD的分区是RDD数据存储的最小单位,一份RDD数据本质上会分成多个分区

        rdd.glom()算子可以将RDD对象的分区排布显示出来。可以看到非kv型的数据分区就是均分。

    (2)API算子会作用在所有分区上

        (3)RDD之间是有依赖关系的

        比如通过RDD1会产生RDD2,RDD2依赖与RDD1,RDD3依赖与RDD2......,会形成一个依赖链条,这个链条称为RDD的血缘关系,也称为RDD的迭代计算:textFile-->RDD1-->RDD2-->RDD3-->RDD4。

        (4)k-v型的RDD可以有分区器

        默认分区器:hash分区规则,可以通过rdd.partitionBy的方法手动设置分区器。该特性只针对k-v型的RDD,即RDD中存储的是二元元组:("hadoop", 2)。

        (5)RDD计算过程Executor的规划,会尽量靠近数据所在的服务器

        该特性是RDD中提升计算性能的特性。有了这个特性,当对RDD对象进行API计算之前,假设当前有3台服务器,RDD对象的分区分别在node11,node22上,node33上没有,即node33上没有数据。假设我们设置了Executor的数量为2,那么这两个Executor会分配在node11,22上,因为离数据本身很近,如果将Executor放到node33上,node33本身没有数据,执行计算任务需要先从别的机器上读取数据进行网络传输,然后在计算。将Executor规划到靠近数据所在的服务器,可以避免网络读取,做到本地读取,加快执行效率。Spark会在确保并行计算能力的前提下,尽量确保本地读取,这里是尽量,不是100%,因此该特性是可能的。

3、HelloWorld案例分析

六、RDD的常见API算子

1、RDD的创建

        有两种方式,分别是将本地的可迭代的对象转化为RDD,以及将文件中的数据转化为RDD

        方式一:本地-->RDD

        方式二:文件-->RDD

        对于读取文件来说,如果不指定参数2,它的默认分区数与CPU无关,主要与文件的大小有关,如果读取的数据来自hdfs则默认分区数与block块的数量有关。因此默认分区数是动态变化的。

        除了textFile算子可以读取文件之外,wholeTextFile算子也可以读取文件(该算子主要适用于小文件过多的情况,该算子在读取时会自动对其进行优化),假设当前有一个文件夹tiny_files,里面存储了大量的小文件,通过wholeTextFile算子来读取文件夹tiny_files时,会自动对小文件进行优化,返回的结果是kv型数据,k是每个小文件的路径,v的小文件的值。

2、RDD的算子

        在Spark中算子共分为两类:Transformation转换算子(返回值仍然是RDD对象,例如map,flatMap,reduceByKey),Action动作/行为算子(返回值不是RDD对象,例如collect)。

        Transformation算子是lazy懒加载的,它会受到Action算子的驱动,如果没有Action算子,Transformation算子是不工作的。Transformation算子相当于构建执行计划,Action是一个指令让这个执行计划开始工作。

        (1)map算子-T

        功能:将RDD对象中的每条数据按照给定的逻辑(传入的处理函数)来处理,传入的函数支持lambda表达式。

        (2)flatMap算子-T

        功能:对RDD对象执行map算子,然后进行解除嵌套操作。解除嵌套就是:

        (3)reduceByKey算子-T

        功能:针对k-v型的RDD(二元元组),自动按照key分组,然后按照给定的函数,完成组内数据的聚合操作。

        (4)mapValues算子-T

        功能:针对k-v型的RDD,对其内部的value执行map操作

        

        (5)groupBy算子-T

        功能:将RDD的数据进行分组,传入的函数就是指定分组规则。

        (6)filter算子-T

        功能:过滤想要的数据进行保留,函数返回值为True的数据被保留,为False的数据被丢弃

        (7)distinct算子-T

        功能:去重

        (8)union算子-T

        功能:两个RDD合并为1个RDD,只合并不会去重,且不同类型的RDD也可以合并

        (9)join算子-T

        功能:对两个RDD实现SQL中的内、外连接,join算子只能用于kv型数据,在关联时会按照key进行关联。

        (10)intersection算子-T

        功能:求两个RDD的交集

        (11)glom算子-T

        功能:将RDD的数据加上嵌套,这个嵌套是按照分区来进行的。就是将RDD对象的分区排布显示出来。

        (12)groupByKey算子-T

        功能:针对kv型的RDD自动按照key分组,类似与groupBy,groupBy需要指定分组逻辑,而groupByKey不需要指定分组逻辑,自动按照key分组。reduceByKey是自动按照key分组,然后按照聚合逻辑对各组进行聚合操作。

        groupByKey的返回值与groupBy一样都是kv型,k是key,v是可迭代的对象,需要进一步处理才可以具体看到内容。注意与groupBy不同的是groupBy返回的是同组数据的整体,而groupByKey返回的是同组数据的value。

        (13)sortBy算子-T

        功能:基于指定的排序依据对RDD数据进行排序

        注意:分区数如果设置的不为1,可能产生的结果不是完全排好序的结果,因为分区数不为1,即执行排序的过程在多个分区中进行,此时只能保证在每个分区内有序,想要做到全局有序,必须将numPartitions=1。这里分区数设为3也是全局有序啊?为什么?因为spark的部署模式是local即单机模式,分区数无论设为多少,本质还是在一台服务器上运行。

        (14)sortByKey算子-T

        功能:针对kv型的数据,按照key进行排序

        案例:

"""
从json文件orders.txt文件中找到北京所出售的商品,同时对结果集进行去重, 得到北京售卖的商品类别信息
"""

from pyspark import SparkConf,SparkContext
import os
import json
os.environ['PYSPARK_PYTHON'] = r"D:\bigdata\python\python.exe"
if __name__ == '__main__':
    conf = SparkConf().setAppName("111").setMaster("local[*]")
    sc = SparkContext(conf=conf)
    rdd = sc.textFile("./orders.txt").flatMap(lambda x: x.split("|")).map(lambda x: json.loads(x)).\
        map(lambda x: (x["areaName"], x["category"])).filter(lambda x: x[0] == '北京').distinct()
    print(rdd.collect())

        将案例提交到YARN中运行:

        方式一:在pycharm中直接执行(远程解析器)

        修改权限再次执行即可。打开node11:8088可以看到test-yarn-1在运行。可能会出现以下错误:

错误的原因是没有设置CapacityScheduler或者设置的scheduler不是CapacityScheduler,需要在hive-site.xml中设置以下配置:

<!-- 选择调度器,默认容量 -->
    <property>
        <description>The class to use as the resource scheduler.</description>
        <name>yarn.resourcemanager.scheduler.class</name>
        <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler</value>
    </property>

        注意在实际生产环境下开发代码时,不可能在一个.py文件中就将所有的逻辑都写完,一般都是会涉及多个.py文件,这里我们将上述代码倒数第三行的代码,脱离出来,反倒单独的一个文件中来模拟多个.py文件依赖执行的情况,并将其放到YARN集群中运行:

        发现明明我把defs_19导入进来了为什么会找不到呢?这就是分布式集群的问题,如果程序是单机运行的不会出现这种错误。与使用集群环境数据必须来自与hdfs一样,运行的主代码在运行时会自动放到集群环境中,但是其余的文件并不会自动放到集群环境中,因此在集群环境下运行找不到文件。

        方式二:spark-submit方式

        将上述两个代码手动上传至linux系统下的任意目录下,删除主代码中的setMaster。由于在Spark环境中已经设置了HADOOP_CONF_DIR,代码中也可以删除。在执行命令时可以通过--py-files参数执行额外提交的py文件,因此代码中conf.set需要删除。

        spark-submit --master yarn --py-files ./defs_19.py ./main.py

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值