写点什么

架构师训练营 1 期第 13 周:数据应用(二)- 总结

用户头像
piercebn
关注
发布于: 2020 年 12 月 20 日

Spark 是大数据领域现阶段使用最广泛的大数据引擎,它被认为是 MapReduce 的替代者,下面会介绍 Spark 的特点,优点及其工作原理

Spark 的特点

Spark VS Hadoop

  • 分别使用 Spark 和 MapReduce 完成逻辑回归计算(一个大数据机器学习的算法)的性能测试对比图,Spark 有明显优势


Spark 特点(Spark 为什么更快)

  • DAG 切分的多阶段计算过程更快速

  • 使用内存存储中间计算结果更高效

  • RDD 的编程模型更简单

Spark 编程示例

Spark WordCount 编程示例


作为编程模型的 RDD

  • RDD 是 Spark 的核心概念,是弹性分布式数据集(Resilient Distributed Datasets)的 缩写。RDD 既是 Spark 面向开发者的编程模型,又是 Spark 自身架构的核心元素。

  • 作为 Spark 编程模型的 RDD。我们知道,大数据计算就是在大规模的数据集上进行一系列的数据计算处理。MapReduce 针对输入数据,将计算过程分为两个阶段,一个 Map  阶段,一个 Reduce 阶段,可以理解成是面向过程的大数据计算。我们在用 MapReduce 编程的时候,思考的是,如何将计算逻辑用 Map 和 Reduce 两个阶段实现, map 和 reduce 函数的输入和输出是什么,MapReduce 是面向过程的。

  • 而 Spark 则直接针对数据进行编程,将大规模数据集合抽象成一个 RDD 对象,然后在 这个 RDD 上进行各种计算处理,得到一个新的 RDD,继续计算处理,直到得到最后的结果数据。所以 Spark 可以理解成是面向对象的大数据计算。我们在进行 Spark 编程的时候,思考的是一个 RDD 对象需要经过什么样的操作,转换成另一个 RDD 对象,思考的重心和落脚点都在 RDD 上。

  • WordCount 的代码示例里,第 2 行代码实际上进行了 3 次 RDD 转换,每次转换都得到 一个新的 RDD,因为新的 RDD 可以继续调用 RDD 的转换函数,所以连续写成一行代码。 事实上,可以分成 3 行。

  • RDD 上定义的函数分两种,一种是转换(transformation)函数,这种函数的返回值还 是 RDD;另一种是执行(action)函数,这种函数不再返回 RDD。

  • RDD 定义了很多转换操作函数,比如有计算 map(func)、过滤 filter(func)、合并数据 集 union(otherDataset)、根据 Key 聚合 reduceByKey(func, [numPartitions])、连接 数据集 join(otherDataset, [numPartitions])、分组 groupByKey([numPartitions]) 等 十几个函数。

作为数据分片的 RDD

  • 跟 MapReduce 一样,Spark 也是对大数据进行分片计算,Spark 分布式计算的数据分 片、任务调度都是以 RDD 为单位展开的,每个 RDD 分片都会分配到一个执行进程去处 理。

  • RDD 上的转换操作又分成两种,一种转换操作产生的 RDD 不会出现新的分片,比如 map、filter 等,也就是说一个 RDD 数据分片,经过 map 或者 filter 转换操作后,结 果还在当前分片。就像你用 map 函数对每个数据加 1,得到的还是这样一组数据,只是 值不同。实际上,Spark 并不是按照代码写的操作顺序去生成 RDD,比如 rdd2 = rdd1.map(func) 这样的代码并不会在物理上生成一个新的 RDD。物理上,Spark 只有在产生新的 RDD 分片时候,才会在物理上真的生成一个 RDD,Spark 的这种特性也被称作惰性计算

  • 另一种转换操作产生的 RDD 则会产生新的分片,比如 reduceByKey,来自不同分片的相同 Key 必须聚合在一起进行操作,这样就会产生新的 RDD 分片。然而,实际执行过程中,是否会产生新的 RDD 分片,并不是根据转换函数名就能判断出来的。

Spark 的计算阶段

  • 和 MapReduce 一个应用一次只运行一个 map 和一个 reduce 不同,Spark 可以根据 应用的复杂程度,分割成更多的计算阶段(stage),这些计算阶段组成一个有向无环图 DAG,Spark 任务调度器可以根据 DAG 的依赖关系执行计算阶段。

  • 这个 DAG 对应的 Spark 程序伪代码如下

  • 整个应用被切分成 3 个阶段,阶段 3 需要依赖阶段 1 和阶段 2,阶段 1 和阶段 2 互不依 赖。Spark 在执行调度的时候,先执行阶段 1 和阶段 2,完成以后,再执行阶段 3。如 果有更多的阶段,Spark 的策略也是一样的。只要根据程序初始化好 DAG,就建立了依 赖关系,然后根据依赖关系顺序执行各个计算阶段,Spark 大数据应用的计算就完成了。

  • Spark 作业调度执行的核心是 DAG,有了 DAG,整个应用就被切分成哪些阶段,每个阶段的依赖关系也就清楚了。之后再根据每个阶段要处理的数据量生成相应的任务集合(TaskSet),每 个任务都分配一个任务进程去处理,Spark 就实现了大数据的分布式计算。

  • 负责 Spark 应用 DAG 生成和管理的组件是 DAGScheduler,DAGScheduler 根据程序代码生成 DAG,然后将程序分发到分布式计算集群,按计算阶段的先后关系调度执行

  • 那么 Spark 划分计算阶段的依据是什么呢?显然并不是 RDD 上的每个转换函数都会生成一个计算阶段,比如上面的例子有 4 个转换函数,但是只有 3 个阶段。

  • 当 RDD 之间的转换连接线呈现多对多交叉连接的时候,就会产生新的阶段。一个 RDD 代表一 个数据集,图中每个 RDD 里面都包含多个小块,每个小块代表 RDD 的一个分片。

  • Spark 也需要通过 shuffle 将数据进行重新组合,相同 Key 的数据放在一起,进行聚合、 关联等操作,因而每次 shuffle 都产生新的计算阶段。这也是为什么计算阶段会有依赖关系,它需要的数据来源于前面一个或多个计算阶段产生的数据,必须等待前面的阶段执 行完毕才能进行 shuffle,并得到数据。

  • 计算阶段划分的依据是 shuffle,不是转换函数的类型,有的函数有时候有 shuffle,有时候没有。例子中 RDD B 和 RDD F 进行 join,得到 RDD G,这里的 RDD F 需要进行 shuffle,RDD B 就不需要。

Spark 的作业管理

  • Spark 里面的 RDD 函数有两种,一种是转换函数,调用以后得到的还是一个 RDD,RDD 的计算逻辑主要通过转换函数完成。

  • 另一种是 action 函数,调用以后不再返回 RDD。比如 count() 函数,返回 RDD 中数据的元素个数;saveAsTextFile(path),将 RDD 数据存储到 path 路径下。Spark 的 DAGScheduler 在遇到 shuffle 的时候,会生成一个计算阶段,在遇到 action 函数的时候,会生成一个作业(job)

  • RDD 里面的每个数据分片,Spark 都会创建一个计算任务去处理,所以一个计算阶段会包含很多个计算任务(task)

Spark 的执行过程

  • Spark 支持 Standalone、Yarn、Mesos、Kubernetes 等多种部署方案,几种部署方案原理也都一样,只是不同组件角色命名不同,但是核心功能和运行流程都差不多。

  • 首先,Spark 应用程序启动在自己的 JVM 进程里,即 Driver 进程,启动后调用 SparkContext 初始化执行配置和输入数据。SparkContext 启动 DAGScheduler 构造执行的 DAG 图,切分成最小的执行单位也就是计算任务。

  • 然后 Driver 向 Cluster Manager 请求计算资源,用于 DAG 的分布式计算。Cluster Manager 收到请求以后,将 Driver 的主机地址等信息通知给集群的所有计算节点 Worker。

  • Worker 收到信息以后,根据 Driver 的主机地址,跟 Driver 通信并注册,然后根据自己的空闲资源向 Driver 通报自己可以领用的任务数。Driver 根据 DAG 图开始向注册的 Worker 分配任务。

  • Worker 收到任务后,启动 Executor 进程开始执行任务。Executor 先检查自己是否有 Driver 的执行代码,如果没有,从 Driver 下载执行代码,通过 Java 反射加载后开始执行。

Spark 生态体系


发布于: 2020 年 12 月 20 日阅读数: 25
用户头像

piercebn

关注

还未添加个人签名 2019.07.24 加入

还未添加个人简介

评论

发布
暂无评论
架构师训练营 1 期第 13 周:数据应用(二)- 总结