本文主要给大家介绍隐藏在华为云数据湖探索服务(后文简称 DLI)背后的核心计算引擎——Spark。DLI 团队在 Spark 之上做了大量的性能优化与服务化改造,但其本质还是脱离不了 Spark 的核心概念与思想,因此笔者从以下几点阐述,让读者快速对 Spark 有一个直观的认识,玩转 DLI。
1、Spark的诞生及优势
2、Spark的核心概念
3、Spark的架构设计
Spark 的诞生及优势
2009 年,Spark 诞生于伯克利大学 AMPLab,诞生之初是属于伯克利大学的研究性项目。于 2010 年开源,2013 年成为 Apache 开源项目,经过几年的发展逐渐取代了 Hadoop,成为了开源社区炙手可热的大数据处理平台。
Spark 官方的解释:“Spark 是用于大规模数据处理的统一分析引擎“,把关键词拆开来看,“大规模数据”指的是 Spark 的使用场景是大数据场景;“统一”主要体现在将大数据的编程模型进行了归一化,同时满足多种类型的大数据处理场景(批处理、流处理、机器学习等),降低学习和维护不同大数据引擎的成本;“分析引擎”表明 Spark 聚焦在计算分析,对标的是 Hadoop 中的 MapReduce,对其模型进行优化与扩展。
Spark 为了解决 MapReduce 模型的优化和扩展,我们先探讨一下 MapReduce 存在的问题,然后分析 Spark 在 MapReduce 之上的改进。
(1)MapReduce 中间结果落盘,计算效率低下
随着业务数据不断增多,业务逻辑不断多样化,很多 ETL 和数据预处理的工作需要多个 MapReduce 作业才能完成,但是 MapReduce 作业之间的数据交换需要通过写入外部存储才能完成,这样会导致频繁地磁盘读写,降低作业执行效率。
Spark 设计之初,就想要解决频繁落盘问题。Spark 只在需要交换数据的 Shuffle 阶段(Shuffle 中文翻译为“洗牌”,需要 Shuffle 的关键性原因是某种具有共同特征的数据需要最终汇聚到一个计算节点上进行计算)才会写磁盘,其它阶段,数据都是按流式的方式进行并行处理。
(2)编程模型单一,场景表达能力有限
MapReduce 模型只有 Map 和 Reduce 两个算子,计算场景的表达能力有限,这会导致用户在编写复杂的逻辑(例如 join)时,需要自己写关联的逻辑,如果逻辑写得不够高效,还会影响性能。
与 MapReduce 不同,Spark 将所有的逻辑业务流程都抽象成是对数据集合的操作,并提供了丰富的操作算子,如:join、sortBy、groupByKey 等,用户只需要像编写单机程序一样去编写分布式程序,而不用关心底层 Spark 是如何将对数据集合的操作转换成分布式并行计算任务,极大的简化了编程模型
Spark 的核心概念
Spark 中最核心的概念是 RDD(Resilient Distributed Dataset) - 弹性分布式数据集,顾名思义,它是一个逻辑上统一、物理上分布的数据集合,Spark 通过对 RDD 的一系列转换操作来表达业务逻辑流程,就像数学中对一个向量的一系列函数转换。Spark 通过 RDD 的转换依赖关系生成对任务的调度执行的有向无环图,并通过任务调度器将任务提交到计算节点上执行,任务的划分与调度是对业务逻辑透明的,极大的简化了分布式编程模型,RDD 也丰富了分布式并行计算的表达能力。
RDD 上的操作分为 Transformation 算子和 Action 算子。Transformation 算子用于编写数据的变换过程,是指逻辑上组成变换过程。Action 算子放在程序的最后一步,用于对结果进行操作,例如:将结果汇总到 Driver 端(collect)、将结果输出到 HDFS(saveAsTextFile)等,这一步会真正地触发执行。
常见的 Transformation 算子包括:map、filter、groupByKey、join 等,这里面又可以分为 Shuffle 算子和非 Shuffle 算子,Shuffle 算子是指处理过程需要对数据进行重新分布的算子,如:groupByKey、join、sortBy 等。常见的 Action 算子如:count、collect、saveAsTextFile 等
如下是使用 Spark 编程模型编写经典的 WordCount 程序:
(该程序通过 RDD 的算子对文本进行拆分、统计、汇总与输出)
Spark 程序中涉及到几个概念,Application、Job、Stage、Task。每一个用户写的程序对应于一个 Application,每一个 Action 生成一个 Job(默认包含一个 Stage),每一个 Shuffle 算子生成一个新的 Stage,每一个 Stage 中会有 N 个 Task(N 取决于数据量或用户指定值)。
Spark 的架构设计
(注:橙色表示进程)
前面讲述了 Spark 核心逻辑概念,那么 Spark 的任务是如何运行在分布式计算环境的呢?接下来我们来看看开源框架 Spark 的架构设计。
Spark 是典型的主从(Master- Worker)架构,Master 节点上常驻 Master 守护进程,负责管理全部的 Worker 节点。Worker 节点上常驻 Worker 守护进程,负责与 Master 节点通信并管理 Executor。
(注:橙色和绿色表示进程)
Spark 程序在客户端提交时,会在 Application 的进程中启动一个 Driver。看一下官方对 Driver 的解释“The process running the main() function of the application and creating the SparkContext”。
我们可以把 Master 和 Worker 看成是生产部总部老大(负责全局统一调度资源、协调生产任务)和生产部分部部长(负责分配、上报分部的资源,接收总部的命令,协调员工执行任务),把 Driver 和 Executor 看成是项目经理(负责分配任务和管理任务进度)和普通员工(负责执行任务、向项目经理汇报任务执行进度)。
项目经理 D to 总部老大 M:Hi,老大,我刚接了一个大项目,需要你通知下面的分部部长 W 安排一些员工组成联合工作小组。
总部老大 M to 分部部长 W:最近项目经理 D 接了一个大项目,你们几个部长都安排几个员工,跟项目经理 D 一起组成一个联合工作小组。
分部部长 W to 员工 E:今天把大家叫到一起,是有个大项目需要各位配合项目经理 D 去一起完成,稍后会成立联合工作小组,任务的分配和进度都直接汇报给项目经理 D。
项目经理 D to 员工 E:从今天开始,我们会一起在这个联合工作小组工作一段时间,希望我们好好配合,把项目做好。好,现在开始分配任务…
员工 E to 项目经理 D:你分配的 xxx 任务已完成,请分配其它任务。
项目所有任务都完成后,项目经理 D to 总部老大 M:Hi,老大,项目所有的任务都已经完成了,联合工作小组可以解散了,感谢老大的支持。
评论