Spark浅析

Spark应用程序

Spark应用程序由一个驱动器进程和一组执行器进程组成。驱动进程运行main()函数,位于集群中的一个节点上,它负责三件事:维护Spark应用程序的相关信息;回应用户的程序或输入;分析任务并分发给若干执行器进行处理。驱动器是必须的,它是Spark应用程序的核心,它在应用程序执行的整个生命周期中维护着所有相关信息。

执行器负责执行驱动器分配给它的实际计算工作,这意味着每个执行器只负责两件事:执行由驱动器分配给它的代码,并将该执行器的计算状态报告给运行驱动器的节点。

Spark API的多语言支持

Scala:Spark主要用Scala编写

Java:可以用Java编写Spark代码

Python:Python几乎支持所有Scala支持的结构

SQL:Spark支持ANSI SQL2003标准的一个子集

R:Spark有两个常用的R库:一个作为Spark核心的一部分(SparkR),另一个是R语言开源社区维护的包(sparklyr)

启动Spark

当以交互方式启动Spark时,相当于隐式地创建了一个SparkSession来管理Spark应用程序,当不是通过交互模式而是通过独立应用程序启动Spark时,必须在应用程序代码中显式地创建SparkSession对象。

DataFrame

DataFrame是最常见的结构化API,简单来说,它是包含行和列的数据表,说明这些列和列类型的一些规则被称为模式(schema),可以将DataFrame想象为具有多个命名列的电子表格,但是我们熟悉的电子表格和Spark DataFrame是不同的,电子表格位于一台计算机上,而Spark DataFrame可以跨越数千台计算机。

Spark有几个核心抽象:Dataset,DataFrame,SQL表和RDD,这些不同的抽象都表示分布式数据集合,其中最简单和最有效的是DataFrame,它支持所有语言

数据分区

为了让多个执行器并行地工作,Spark将数据分解成多个数据块,每个数据块叫做一个分区。分区是位于集群中的一台物理机上的多行数据的集合,DataFrame的分区也说明了在执行过程中数据在集群中的物理分布。如果只有一个分区,即使拥有数千个执行器,Spark也只有一个执行器在处理数据。类似地,如果有多个分区,但只有一个执行器,那么Spark仍然只有一个执行器在处理数据,就是因为只有一个计算资源单位。

转换操作

转换操作是使用Spark表达业务逻辑的核心,有两类转换操作:第一类是指定窄依赖关系的转换操作,第二类是指定宽依赖关系的转换操作

具有窄依赖关系的转换操作(我们称之为窄转换)是每个输入分区仅决定一个输出分区的转换

具有宽依赖关系的转换是每个输入分区决定了多个输出分区,这种宽依赖关系的转换经常被称为洗牌(shuffle)操作,它会在整个集群中执行互相交换分区数据的功能。如果是窄转换,Spark将自动执行流水线处理,这意味着如果我们在DataFrame上指定了多个过滤操作,它们将全部在内存中执行,而属于宽转换的shuffle操作不是这样,当我们执行shuffle操作时,Spark将结果写入磁盘。

惰性评估

惰性评估的意思就是等到绝对需要时才执行计算。在Spark中,当用户表达一些对数据的操作时,不是立即修改数据,而是建立一个作用到原始数据的转换计划。Spark首先会将这个计划编译为可以在集群中高效运行的流水线式的物理执行计划,然后等待,直到最后时刻才开始执行代码。这会带来很多好处,因为Spark可以优化整个从输入端到输出端的数据流。一个很好的例子就是DataFrame的谓词下推,假设我们构建一个含有多个转换操作的Spark作业,并在最后指定了一个过滤操作,假设这个过滤操作只需要数据源中的某一行数据,则最有效的方法是在最开始仅访问我们需要的单个记录,Spark会通过自动下推这个过滤操作来优化整个物理执行计划。

动作操作

转换操作使我们能够建立逻辑转换计划,为了触发计算,我们需要运行一个动作操作(action),一个动作指示Spark在一系列转换操作后计算一个结果,最简单的动作操作是count,它计算一个DataFrame中的记录总数,count不是唯一的动作,有三类动作:

  1. 在控制台中查看数据的动作
  2. 在某个语言中将数据汇集为原生对象的动作
  3. 写入输出数据源的动作

完整示例

Spark可以从大量数据源中读取数据或写入数据,为了读取这些数据,需要用到与我们创建的SparkSession所关联的DataFrameReader,还需要指定文件格式及设置其他选项。为了获取模式信息,Spark会从文件中读取一些数据,然后根据Spark支持的类型尝试解析读取这些行中的数据类型。当然也可以在读取数据时选择严格指定模式

bash 复制代码
val flightData2015 = spark.read.option("inferSchema","true").option("header","true").csv("file:///data/2015-summary.csv")

csv文件被读到一个dataframe里后,又被转换为一个本地数组或行列表

在默认情况下,shuffle操作会输出200个shuffle分区,我们将此值设置为5,以减少shuffle输出分区的数量:

bash 复制代码
spark.conf.set("spark.sql.shuffle.partitions","5")

我们构建的转换逻辑计划定义了DataFrame的血统,这样在任何给定的时间点,Spark都知道如何通过对输入数据执行之前的操作来重新计算任何分区,这就是Spark编程模型的核心------函数式编程,当数据转换保持不变时,相同的输入始终导致相同的输出

DataFrame和SQL

不管使用什么语言,Spark以完全相同的方式执行转换操作,可以使用SQL或者DataFrame表达业务逻辑,并且在实际运行代码之前,Spark会将该逻辑编译到底层执行计划(可以在解释计划中看到),使用Spark SQL,可以将任何DataFrame注册为数据表或视图(临时表),并使用纯SQL对它进行查询。编写SQL查询或编写DataFrame代码并不会造成性能差异,它们都会被"编译"成相同的底层执行计划。

可以使用一个简单的方法将任何DataFrame放入数据表或视图中

bash 复制代码
flightData2015.createOrReplaceTempView("flight_data_2015")

请注意,这些计划编译后是完全相同的基本执行计划

再来执行一些更复杂的操作,在数据中找到前五个目标国家:

bash 复制代码
spark.sql("select dest_country_name,sum(count) sc from flight_data_2015 group by dest_country_name order by sc desc limit 5").show
bash 复制代码
flightData2015.groupBy("dest_country_name").sum("count").withColumnRenamed("sum(count)","destination_total").sort(col("destination_total").desc).limit(5).show
相关推荐
小淮AI1 小时前
国际教育课程的本土化探索:以枫叶教育三十年为观察样本
大数据·人工智能
龙兵AI增长破局圈.赵老师讲成交2 小时前
只有把过程管好,结果才会出来。
大数据·人工智能·ai·创业创新
qq407855603 小时前
面向智能补货需求的进销存系统盘点
大数据·人工智能·低代码·制造
CHENGQUAN_kenan3 小时前
佛山亚马逊卖家出口退税合规指南|9610免税、一般贸易退税、无票采购、申报误区全覆盖
大数据·经验分享·笔记·百度
Web3_Daisy3 小时前
从流动性到执行:如何降低 MEV 对 Web3 市场
大数据·人工智能·web3·区块链
日常通勤穿搭3 小时前
电商 AI 作图用哪个最方便?新手商家 AI 出图工具对比
大数据·人工智能
小淮AI4 小时前
一个国际家庭在武汉的择校笔记:两份外籍人员子女学校的课程方案比较
大数据·人工智能
一只鹿鹿鹿4 小时前
大数据中心安全系统解决方案(Word文件)
大数据·运维·物联网·安全·政务
qq_33776320195 小时前
仿博易大师内外盘国际期货软件源码全套开发:期货交易系统架构设计与核心技术解析
大数据·区块链
盛世宏博智慧档案5 小时前
POE温湿度传感器常见故障排查与优化解决原理
大数据