Pyspark学习笔记

0. 前言

这里是我在学习Spark中的一些个人整理的笔记, 所以全文都只是我的个人理解,可能会出现错误,也有可能并不是那么的规范。这里并没有完全写完,因为这是我在学习的过程中写的,后续会不断的补充和修正。

1. Spark环境安装

这里我使用的是三台linux虚拟机集成的环境, 使用的端口号为:
192.168.88.161 node1
192.168.88.162 node2
192.168.88.163 node3
并且在三台虚拟机上都安装了anaconda并创建了虚拟环境, 但是并没有构建Spark集群, 即只在node1上安装了Spark, 这里不做过多的演示.

2. Pyspark入门

2.1 pyspark入门案例

2.1.1 从HDFS上读取文件并实现排序

  1. 启动hdfs集群
# 启动所有集群, 既然也启动了hdfs集群, 这里只需要在node1上运行即可
start-all.sh
# 确定是否启动成功
jps
  1. 将需要处理的文件上传到hdfs上
    在这里插入图片描述
    这里是我的需要处理的文件在node1虚拟机上的位置
cd /tmp/pycharm_project_715/day01/data  # 这里是我的需要处理的文件所在文件夹的路径
# 前面一个是linux中文件所在路径, 由于在执行该语句之前我们已经cd到了所在文件夹, 所以这里的相对路径就只是word.txt
# 后面一个是要存储到hdfs上的路径
hdfs dfs -put word.txt /data/word.txt

该文件的内容为:

hello you Spark Flink
hello me hello she Spark
spark hadoop hadoop
hive hbase

  1. 编写pyspark代码处理文件
    需求: 需要将这四行数据从hdfs中读取(或在linux本地读取), 并统计单词出现的次数
思路
  1. 对文件进行分割, 将每一列以空格为分隔符分割, 并将四行合并到一起
  1. 将单词转化为 (hello, 1) 的形势, 方便后续统计
  1. 将该元组tup[0]相同的元组合并
from pyspark import SparkContext, SparkConf

import os

os.environ['SPARK_HOME'] = '/export/server/spark'
os.environ['PYSPARK_PYTHON'] = '/root/anaconda3/bin/python3'
os.environ['PYSPARK_DRIVER_PYTHON'] = '/root/anaconda3/bin/python3'
os.environ['JAVA_HOME'] = '/export/server/jdk1.8.0_241'

if __name__ == '__main__':
    # 1. 创建运行环境
    # setMaster设置集群格式, 这里选择的是linux本地执行, 且分配能分配的最多核
    # setAppName设置业务名称, 这里根据需求设置即可, 没有固定的值
    conf = SparkConf().setMaster('local[*]').setAppName('统计单词')
    sc = SparkContext(conf=conf)

    # 2. 读取文件
    # rdd_file = sc.textFile('file:///tmp/pycharm_project_715/day01/data/word.txt') # 从linux本地中读取文件, 格式为 file://linux虚拟机本地存储的位置
    rdd_file = sc.textFile('hdfs://node1:8020/data/word.txt')   # 从hdfs中读取文件, 格式为 hdfs://虚拟机地址(这里由于我的电脑配置了地址, 否则需要192.168.88.161):8020/需要读取的文件地址

    # 3. 对文件进行处理
    # 3.1 对文件进行分割, 将每一列以空格为分隔符分割, 并将四行合并到一起
    rdd_flat = rdd_file.flatMap(lambda line: line.split())
    # 3.2 将单词转化为(hello, 1)的形势, 方便后续统计
    rdd_tup = rdd_flat.map(lambda word: (word, 1))
    # 3.3 将该元组tup[0]相同的元组合并
    result = rdd_tup.reduceByKey(lambda x, y: x + y)
    print(result.collect())

2.1.2 基于Spark-Submit方式运行

上述2.1.1 的入门案例中的代码是在pycharm中运行的, spark还有一种运行方式, 就是Spark-Submit方式, 这个文件所在位置为/export/server/spark/bin/spark-submit, 即spark安装位置/bin/spark-submit

 # cd切换到spark安装路径的bin目录下
cd /export/server/spark/bin
# 使用spark-submit运行刚刚写的python脚本文件, 格式为: 
# spark安装地址/bin/spark-submit --master local[*](这里是设置在linux本地运行, 也可以选择yarn集群运行) python脚本位置
./spark-submit \
--master local[*] \
/tmp/pycharm_project_715/day01/src/01-pyspark-wordcount-hdfs.py

2.2 Spark On Yarn 环境搭建

2.2.1 Spark On Yarn的本质

SparkOnYearn的本质就是把spark应用提交到Yarn,由Yarn进行统一的调度和管理
这种方式是在公司使用比较多的方式

2.2.2 配置 Spark On Yarn

  1. 修改spark-env.sh
cd /export/server/spark/conf
cp spark-env.sh.template spark-env.sh
vim /export/server/spark/conf/spark-env.sh

添加以下内容:
HADOOP_CONF_DIR=/export/server/hadoop/etc/hadoop
YARN_CONF_DIR=/export/server/hadoop/etc/hadoop
SPARK_HISTORY_OPTS="-Dspark.history.fs.logDirectory=hdfs://node1:8020/sparklog/ -Dspark.history.fs.cleaner.enabled=true"

同步到其他两台(单节点时候, 不需要处理)
cd /export/server/spark/conf
scp -r spark-env.sh node2:$PWD
scp -r spark-env.sh node3:$PWD
  1. 修改hadoop的yarn-site.xml
cd /export/server/hadoop-3.3.0/etc/hadoop/
vim /export/server/hadoop-3.3.0/etc/hadoop/yarn-site.xml

添加以下内容, 将以下内容添加到<configuration>  </configuration>中:
    <!-- 设置yarn集群的内存分配方案 -->
    <property>
        <name>yarn.nodemanager.resource.memory-mb</name>
        <value>20480</value>
    </property>
    <property>
        <name>yarn.scheduler.minimum-allocation-mb</name>
        <value>2048</value>
    </property>
    <property>
        <name>yarn.nodemanager.vmem-pmem-ratio</name>
        <value>2.1</value>
    </property>

将以上操作同步到其他两台虚拟机中

cd /export/server/hadoop/etc/hadoop
scp -r yarn-site.xml node2:$PWD
scp -r yarn-site.xml node3:$PWD
  1. Spark设置历史服务地址
cd /export/server/spark/conf
cp spark-defaults.conf.template spark-defaults.conf
vim spark-defaults.conf

添加以下内容:
spark.eventLog.enabled                  true
spark.eventLog.dir                      hdfs://node1:8020/sparklog/
spark.eventLog.compress                 true
spark.yarn.historyServer.address        node1:18080


配置后, 需要在HDFS上创建 sparklog目录
hdfs dfs -mkdir -p /sparklog

设置日志级别:

cd /export/server/spark/conf
cp log4j.properties.template log4j.properties
vim log4j.properties

修改以下内容:(在公司开发中, 日志显示等级为WARN即可, 但是由于这里是学习阶段, 多看看日志, 所以这里我暂时没有改)

在这里插入图片描述

# 同步到其他节点(不需要同步, spark只有单节点)
cd /export/server/spark/conf
scp -r spark-defaults.conf log4j.properties node2:$PWD
scp -r spark-defaults.conf log4j.properties node3:$PWD
  1. 配置依赖spark jar包

当Spark Application应用提交运行在YARN上时,默认情况下,每次提交应用都需要将依赖Spark相关jar包上传到YARN集群中,为了节省提交时间和存储空间,将Spark相关jar包上传到HDFS目录中,设置属性告知Spark Application应用。

# 在hdfs中创建/spark/jars文件夹, 并将linux本地中spark中的jars文件夹中的所有文件复制到hdfs上
hadoop fs -mkdir -p /spark/jars/
hadoop fs -put /export/server/spark/jars/* /spark/jars/

# 修改spark-defaults.conf
cd /export/server/spark/conf
vim spark-defaults.conf
添加以下内容:
spark.yarn.jars  hdfs://node1:8020/spark/jars/*

同步到其他节点, 由于我只在node1上配置了spark, 所以这里不需要执行, 但是如果你搭建了spark集群, 这里也可以配置一下

cd /export/server/spark/conf
scp -r spark-defaults.conf root@node2:$PWD
scp -r spark-defaults.conf root@node3:$PWD
  1. 启动服务
    Spark Application运行在YARN上时,上述配置完成
    启动服务:HDFS、YARN、MRHistoryServer和Spark HistoryServer,命令如下:
# 启动HDFS和YARN服务,在node1执行命令
start-dfs.sh
start-yarn.sh
# 或
start-all.sh
# 注意:在onyarn模式下不需要启动start-all.sh(jps查看一下看到worker和master)

# 启动MRHistoryServer服务,在node1执行命令
mr-jobhistory-daemon.sh start historyserver

# 启动Spark HistoryServer服务,,在node1执行命令
/export/server/spark/sbin/start-history-server.sh

Spark HistoryServer服务WEB UI页面地址:
http://node1:18080/

  1. 测试修改结果
    先将圆周率PI程序提交运行在YARN上,命令如下:
SPARK_HOME=/export/server/spark
${SPARK_HOME}/bin/spark-submit \
--master yarn \
--conf "spark.pyspark.driver.python=/root/anaconda3/bin/python3" \
--conf "spark.pyspark.python=/root/anaconda3/bin/python3" \
${SPARK_HOME}/examples/src/main/python/pi.py \
10

2.3 Spark 程序与PySpark交互流程

2.3.1 spark-submit提交任务到spark集群,部署模式是client模式

1 启动Driver
2 向Master申请资源
3 Master向Driver分配资源 返回资源列表
Executor1 : node1 1core 2G
Executor2 : node3 1core 2G
4 连接对应的worker节点,通知它们启动Executor,当worker启动完成后,会反向注册到dirver(通知driver)
5 启动main程序
5.1 启动sparkcontext,构造出sc对象,基于py4j把python程序转成java程序进行执行
5.2 当sc启动完成后,会把后续的rdd相关程序合并在一起,根据RDD的依赖关系,形成一个DAG的执行图。根据DAG可以划分出有几个阶段,每个阶段有多少个线程,每个线程运行在那个executor上(任务分配)
5.3 每个阶段有多少个线程,每个线程运行在那个executor上确定后,把任务分发到对应的executor执行
5.4 executor获取到分发的任务后,开始执行,Task执行完成后把结果返回给driver。前提是有需要返回结果的操作,比如collect,也有操作不需要返回结果比如saveAsTextFile
5.5 当driver获取所有的executor返回的结果之后,开始执行非RDD程序,通知master关闭sc,执行资源回收的工作

2.3.2 spark-submit提交任务到spark集群,部署模式是cluster模式

1 首先把任务提交到主节点
2 Master根据Driver资源信息,在worker节点中随机找一台符合要求的节点,启动Driver,把任务提交Driver
3 对应worker节点接收到任务后,启动Driver,并且和Master保持心跳机制,告知master启动成功,申请资源
4 master根据申请的资源在集群中进行查找,返回资源列表
Executor1 : node1 1core 2G
Executor2 : node3 1core 2G
5 连接对应的worker节点,通知它们启动Executor,当worker启动完成后,会反向注册到dirver(通知driver)
6 启动main程序
6.1 启动sparkcontext,构造出sc对象,基于py4j把python程序转成java程序进行执行
6.2 当sc启动完成后,会把后续的rdd相关程序合并在一起,根据RDD的依赖关系,形成一个DAG的执行图。根据DAG可以划分出有几个阶段,每个阶段有多少个线程,每个线程运行在那个executor上(任务分配)
6.3 每个阶段有多少个线程,每个线程运行在那个executor上确定后,把任务分发到对应的executor执行
6.4 executor获取到分发的任务后,开始执行,Task执行完成后把结果返回给driver。前提是有需要返回结果的操作,比如collect,也有操作不需要返回结果比如saveAsTextFile
6.5 当driver获取所有的executor返回的结果之后,开始执行非RDD程序,通知master关闭sc,执行资源回收的工作

2.3.3 spark-submit提交任务到yarn集群,部署模式是client模式

在这里插入图片描述

1 启动Driver
2 连接到yarn主节点(ResurceManager)向主节点提交资源任务(最终启动executor)
3 yarn主节点接收到任务后,会选择一个nodeManager,启动AppMaster,启动后,和ResourceManager建立心跳机制,通知主节点appmaster启动成功
4 appmaster根据提交的资源信息向ResourceManager申请资源,通过心跳方式发送请求,不断向ResoureManager询问
5 一旦appmaster检测到资源准备完成,也会获取资源信息列表,appmaster根据资源信息列表,找到对应的nodeManager启动Executor
6 当Executor启动完成后,会通知appMaster并且通知Driver
7 启动main程序
7.1 启动sparkcontext,构造出sc对象,基于py4j把python程序转成java程序进行执行
7.2 当sc启动完成后,会把后续的rdd相关程序合并在一起,根据RDD的依赖关系,形成一个DAG的执行图。根据DAG可以划分出有几个阶段,每个阶段有多少个线程,每个线程运行在那个executor上(任务分配)
7.3 每个阶段有多少个线程,每个线程运行在那个executor上确定后,把任务分发到对应的executor执行
7.4 executor获取到分发的任务后,开始执行,Task执行完成后把结果返回给driver。前提是有需要返回结果的操作,比如collect,也有操作不需要返回结果比如saveAsTextFile
7.5 当driver获取所有的executor返回的结果之后,开始执行非RDD程序,通知appmaster关闭sc,回收资源

2.3.4 spark-submit提交任务到yarn集群,部署模式是cluster模式

在这里插入图片描述

yarn的client模式和cluster模式区别
client下:Driver和app Master是两个不同程序
Driver负责任务分配 监控 管理工作
appMaster负责申请资源启动executor
cluster模式下:Driver和AppMaster合二为一,作用合在一起

3. RDD操作

3.1 Spark Code

3.1.1 RDD的基本介绍

RDD:弹性分布式数据集

早期计算模式是python + mysql, 这只适用于小规模数据, 不适合扩展

随着计算的发展, 数据的规模也在不断变大, 单机模式已经不适用于需求了, 所以出现了分布式技术, 也就是hadoop中的MR(mapreduce)

MR流程:
首先读取数据到内存,对数据进行转换处理,把处理的结果写入环形缓冲区(内存),当缓冲区满了则写入到磁盘。如果有多个缓冲区的内容,则进行合并,最终把结果存储在磁盘中。

这种处理流程,在有限的资源下可以处理大规模数据, 但是使用mr进行数据处理效率非常低, 有大量的磁盘交互工作, 因此出现了高效计算和迭代工具 spark(RDD)

3.1.2 RDD的特性

1 可分区: 每个RDD都必须是可以分区的,每个分区代表一个Task线程,可分区也是分布式的基本要求
2 计算函数会作用在每个分区: 每个RDD都是由一个计算函数得到的,计算函数作用在每个分区上
3 RDD之间存在依赖关系
4 对于kv类型rdd存在分区函数
5 移动存储不如移动计算(让计算和数据更近)

3.1.3 RDD的特点

1 RDD可分区
2 RDD是只读(不能更改)
3 RDD之间有依赖:宽依赖窄依赖
4 RDD每次计算都会重新计算,需要把结果缓存下来,RDD不保存数据
5 检查点(checkpoint),相当于对结果进行备份。当RDD的依赖关系越来越长,为了减少因为计算失败导致回溯效率低问题,不要再检查之前的依赖关系,直接从检查点的位置获取结果即可

3.1.4 如何构建RDD

3.1.4.1 设置pycharm运行模板

在讲述如何创建RDD之前, 我想先讲一下如何在pycharm中设置模板
在这里插入图片描述
在这里插入图片描述

这里是模板内容

from pyspark import SparkContext, SparkConf

import os

os.environ['SPARK_HOME'] = '/export/server/spark'
os.environ['PYSPARK_PYTHON'] = '/root/anaconda3/bin/python3'
os.environ['PYSPARK_DRIVER_PYTHON'] = '/root/anaconda3/bin/python3'
os.environ['JAVA_HOME'] = '/export/server/jdk1.8.0_241'

if __name__ == '__main__':
    print('pyspark模板')
    # 初始化spark
    conf = SparkConf().setMaster('local[*]').setAppName('APP')      # 这里的APP需要根据业务名称修改
    sc = SparkContext(conf=conf)
3.1.4.2 构建RDD的两种方法
  1. 通过并行化的方式把代码中数据构建RDD,测试中使用
# 使用parallelize将代码中数据构建成RDD格式
rdd_init = sc.parallelize([1, 2, 3, 4, 5])
  1. 通过读取外部数据的方式构建RDD,生产中使用

在之前的样例中读取hdfs或linux本地的word.txt文件时, 就是使用的这种方式

# hdfs
rdd_file = sc.textFile('hdfs://node1:8020/data/word.txt')	# 读取hdfs上 /data/word.txt文件
rdd_file = sc.textFile('hdfs://node1:8020/data')			# 读取hdfs上 /data 目录下的所有文件

# linux本地
rdd_file = sc.textFile('file:///tmp/data')					# 读取linux本地上 /tmp/data目录下的所有文件, 注意, 这里的 /// 最后一个是由于linux的根目录为 / , 所以其他文件都是以/开头的

3.1.5 RDD算子相关操作

3.1.5.1 RDD算子分类

RDD中算子可以分为两类: transformation(转换算子)、action(动作算子)

转换算子:

  1. 返回的结果都是新的RDD(RDD是只读)
  2. 所有的转换算子都是惰性的,只有遇到action算子才会真正的执行
  3. RDD不存储数据,只存储转换的规则,遇到action算子后对数据进行处理

动作算子:

  1. 返回的结果不是RDD或者没有返回值
  2. 所有的动作算子都是立即执行的,每个action操作都会触发任务

3.1.5.2 transformation转换算子介绍

  1. glom, getNumPatitions, collect

glom: 显示如何分区
getNumPatitions: 获取分区数量
collect: 获取整个RDD的完整内容(不显示分区情况)

    # 创建rdd, 第二个参数为分区数, 默认为2
    rdd_init = sc.parallelize([1, 2, 3, 4, 5, 6], 3)
    # 打印rdd_init的分区情况
    print('rdd_init的分区情况:', rdd_init.getNumPartitions())
    # 打印rdd_init的内容(不显示分区)
    print('rdd_init的内容(不显示分区)', rdd_init.collect())
    # 打印rdd_init的内容(显示分区)
    print('rdd_init的内容(显示分区)', rdd_init.glom().collect())

运行结果:
在这里插入图片描述

  1. map
About This Book, Learn why and how you can efficiently use Python to process data and build machine learning models in Apache Spark 2.0Develop and deploy efficient, scalable real-time Spark solutionsTake your understanding of using Spark with Python to the next level with this jump start guide, Who This Book Is For, If you are a Python developer who wants to learn about the Apache Spark 2.0 ecosystem, this book is for you. A firm understanding of Python is expected to get the best out of the book. Familiarity with Spark would be useful, but is not mandatory., What You Will Learn, Learn about Apache Spark and the Spark 2.0 architectureBuild and interact with Spark DataFrames using Spark SQLLearn how to solve graph and deep learning problems using GraphFrames and TensorFrames respectivelyRead, transform, and understand data and use it to train machine learning modelsBuild machine learning models with MLlib and MLLearn how to submit your applications programmatically using spark-submitDeploy locally built applications to a cluster, In Detail, Apache Spark is an open source framework for efficient cluster computing with a strong interface for data parallelism and fault tolerance. This book will show you how to leverage the power of Python and put it to use in the Spark ecosystem. You will start by getting a firm understanding of the Spark 2.0 architecture and how to set up a Python environment for Spark., You will get familiar with the modules available in PySpark. You will learn how to abstract data with RDDs and DataFrames and understand the streaming capabilities of PySpark. Also, you will get a thorough overview of machine learning capabilities of PySpark using ML and MLlib, graph processing using GraphFrames, and polyglot persistence using Blaze. Finally, you will learn how to deploy your applications to the cloud using the spark-submit command., By the end of this book, you will have established a firm understanding of the Spark Python API and how it can be used t
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值