Spark基础-Spark基本概念
基本架构
Spark程序由一个驱动进程(driver)和多个执行器进程(executor)组成。
driver运行main函数,位于集群中的一个节点上。负责三件事:
维护Spark应用程序相关信息
回应用户的程序或输入
分析任务并分发给若干executor执行
executor负责实际的计算工作,每个executor负责两件事情:执行由driver分配的代码
将计算状态报告给driver
集群管理器可以是Spark独立的集群管理器,yarn或Mesos
Spark的API
有两套基本的API
dataframe是最常见的结构化API,底层由RDD实现。它是包含行和列的数据表。
数据分区
为了实现多个executor并行计算,Spark将数据分解成多个数据块,每个数据块称为一个分区。分区是位于集群中一台物理机器上的多行数据的集合。使用Dataframe时,无需手动操作分区,由Spark自行决定。
转换操作
要“更改”DataFrame,需要告诉spark如何修改它以执行你需要的操作,这个过程被称为转换。
这些转换并没有实际输出,因为我们仅指定了一个抽象转换。在调用一个动作操作之前,spark不会真的执行转换操作。转换操作有两类:
每个输入分区仅决定一个输出分区的数据。执行窄转换时,spark直接在内存中进行。
宽依赖操作
每个输入分区决定了多个输出分区。宽依赖关系的转换常被称为洗牌(shuffle)。会在整个集群中执行相互交换分区数据的操作。执行shuffle时,spark会将数据写入磁盘。
惰性评估
惰性评估的意思就是等到绝对需要执行时才执行计算。Spark中,当用户表达一些对数据的操作时,不是立即修改数据,而是建立一个作用到原始数据的转换计划。Spark首先会将这个计划编译为可以在集群中高效运行的流水线式的物理执行计划。然后等到最后时刻才开始执行代码。
动作操作
转换操作使我们能建立逻辑执行计划。为了触发计算,我们需要运行一个动作操作(action)。一个动作指示Spark在一系列转换操作后计算一个结果。有三类动作操作:
调用某个dataframe的explain操作会显示dataframe的来源(即spark是如何执行查询操作的)
从上到下阅读解释计划,上面是最终结果,下面是数据源。每行的第一个关键字是倒叙的执行的操作。比如上面的计划,最终得到了一个df。倒叙的依次执行的步骤是排序,数据交换,文件扫描。
再贴一个更大的解释计划
可以看到 limit 语句以及 orderBy(在第一行中)。您还可以看到我们的聚合是如何在两个阶段中发生的,在 partial_sum 调用中。这是因为求和的数字列表是可交换的,而 Spark 可以按分
区执行和。当然,我们也可以在 DataFrame 中看到我们的读取方式。
当然,我们并不总是需要收集数据。我们也可以将其写入任何 Spark 支持的数据源。例如,
假设我们希望将信息存储在数据库中,比如 PostgreSQL,或者将它们写到另一个文件中。