03.03 「大数据」(七十六)Spark之工作机制

【导读:数据是二十一世纪的石油,蕴含巨大价值,这是·情报通·大数据技术系列第[76]篇文章,欢迎阅读和收藏】

1 基本概念

Spark 是基于内存计算的大数据并行计算框架。 Spark 基于内存计算,提高了在大数据环境下数据处理的实时性,同时保证了高容错性和高可伸缩性,允许用户将 Spark 部署在大量廉价硬件之上,形成集群。正是如此, Spark 工作机制也是围绕这几点开展,主要包括调度管理、内存管理、容错机制。

2 术语解释

「大数据」(七十六)Spark之工作机制

3 Spark 工作机制介绍

3.1 调度管理

Spark 调度管理按照场景可以分为两类,一类是 Spark 程序之间的调度,这是最主要的调度场景;另外一类是 Spark 程序内部的调度。

l Spark 程序之间的调度

当多个用户提交多个 Spark 程序时, Spark 是如何调度这些应用并合理地分配资源呢?

Standalone 模式下,默认使用 FIFO ,每个 app 会独占所有资源,可以通过以下几个参数调整集群相关的资源:

1) spark.cores.max :调整 app 可以在整个集群中申请的 CPU core 数量

2) spark.deploy.defaultCores :默认的 CPU core 数量

3) spark.executor.memory :限制每个 Executor 可用的内存

Mesos 模式下,可以使用

1) spark.mesos.coarse=true 设置静态配置资源的策略

2) 使用 mesos://URL 且不配置 spark.mesos.coarse=true (每个 app 会有独立固定的内存分配,空闲时其他机器可以使用其资源)

在 Yarn 模式下,提交作业时可以使用

1) 通过– num-executors 控制分配多少个 Executor 给 app

2) – executor-memory 和– executor-cores 分别控制 Executor 的内存和 CPU core

l Spark 程序内部的 Job 调度机制

一个程序应用中,由各个 Action 触发的多个 Job 之间也是存在调度关系的。 Action 操作实现上是调用了 SparkContext 的 runJob 方法提交 Job 。

Spark 中调度 Job 有两种策略

FIFO :

1) 第一个 Job 分配其所需的所有资源

2) 第二个 Job 如果还有剩余资源的话就分配,否则等待

FAIR :

1) 使用轮询的方式调度 Job

2) 可以通过配置 spark.scheduler.mode 调整 Job 的调度方式,也可以配置调度池。


其中调度池的配置如下:

n schedulingMode : FIFO 或者 FAIR

n weight :用于控制调度池相对于其他调度池的权重

n minShare :最小资源值 ( core 的数量 )

3.2 内存管理

相比 Hadoop MapReduce , Spark 计算具有巨大的性能优势,其中很大一部分是因为 Spark 对于内存的充分利用,以及提供的缓存机制。

l 序列化

序列化的本质就是将对象转换为字节流,可以理解为将链表中存储的非连续空间的数据存储转化为连续空间存储的数组中。

Spark 进行序列化操作后,内存或磁盘中 RDD 会含有对象的存储,而在节点间数据的传输时,序列化之后的数据可以节约空间和提高效率。

l 压缩

压缩是日常生活中的一个常见操作,好处显而易见,节约空间,从而就可以获得时间 上的效率。 Spark 中序列化之后的数据可以进行压缩以减少空间开销。

Spark 支持两种压缩算法,在不同的场景中选择不同的压缩算法可以有效的提高程序运行的效率:

n Snappy 算法:高压缩速度

n LZF 算法:高压缩比

l 块管理

RDD 从物理上看是一个元数据结构,记录着 Block 和 Node 之间的映射关系。

存储 RDD 是以 Block 块为单位的,每个分区对应一个块, PartitionID 通过元数据信息可以映射到 Block 。 Spark 保证了每一个 RDD 都可以被重新恢复, RDD 的持久化由 Spark 的 Storage 模块负责,实现了 RDD 与物理存储的解耦合。 Storage 模块负责管理 Spark 在计算过程中产生的数据,将那些在内存或磁盘、在本地或远程存取数据的功能封装了起来。

3.3 容错机制

Spark 以前的集群容错处理模型,像 MapReduce ,将计算转换为一个有向无环图( DAG )的任务集合,这样可以通过重复执行 DAG 里的一部分任务来完成容错恢复。但是由于主要的数据存储在分布式文件系统中,没有提供其他存储的概念,容错过程中需要在网络上进行数据复制,从而增加了大量的消耗。所以,分布式编程中经常需要做检查点,即将某个时机的中间数据写到存储(通常是分布式文件系统)中。

RDD 也是一个 DAG ,每一个 RDD 都会记住创建该数据集需要哪些操作,跟踪记录 RDD 的继承关系,这个关系在 Spark 里面叫 lineage 。由于创建 RDD 的操作是相对粗粒度的变换,即单一的操作应用于许多数据元素,而不需存储真正的数据。当一个 RDD 的某个分区丢失时, RDD 有足够的信息记录其如何通过其他 RDD 进行计算,且只需重新计算该分区。

RDD 之间的依赖分为两种。

Narrow Dependencies (窄依赖):父分区对应一个子分区。

Shuffle Dependencies (宽依赖):父分区对应多个子分区。

父分区最多被一个子分区所用,即一对一或者多对一的关系

对应窄依赖,只需要通过重新计算丢失的那一块数据来恢复,容错成本较小。但如果是宽依赖,则当容错重算分区时,因为父分区数据只有一部分是需要重算子分区的,其余数据重算则成了冗余计算。这时候就需要人为的添加检查点来提高容错机制的执行效率。


分享到:


相關文章: