如果说对于的大数据处理最有贡献的当属Hadoop的三招绝学,HDFS、YARN、MapReduce,而Spark师从Hadoop,青出于蓝而胜于蓝,创建的Spark Core改进了Hadoop基于磁盘的分布式计算,独成一派创建了机遇内存的分布式计算引擎。
Hadoop MapReduce
欲知Spark详情还必须从Hadoop的三招绝学说起,其一便是MapReduce。顾名思义,MapReduce实际上就是两种计算的抽象,Map和Reduce类。
Map:用于封装数据映射逻辑,通过map接口来定义数据转换流程
打开文件Reduce:用户封装数据聚合逻辑,通过reduce接口来定义数据汇聚过程
Map计算结束后,一般来说需要对数据进行分发才能启动Reduce计算逻辑来执行数据汇聚的操作,数据分发的过程称之为Shuffle。MapReduce 提供的分布式任务调度让开发者专注于业务逻辑实现,而无需关心依赖管理、代码分发等分布式实现问题。在 MapReduce 框架下,为了完成端到端的计算作业,Hadoop 采用 YARN 来完成分布式资源调度从而充分利用廉价的硬件资源,采用 HDFS 作为计算抽象之间的数据接口来规避廉价磁盘引入的系统稳定性问题。
虽然Hadoop自成体系的三板斧可以实现任何分布式处理任务,但是也存在一个不可改变的弊端,基于磁盘的分片副本会带来巨大的磁盘I/O和网络I/O开销。
Spark Core
Spark是基于Hadoop的一种改进,基于内存的分布式计算引擎。基于内存的计算并不是将所有的计算都放在的内存中完成,而是通过RDD来实现。
RDD
RDD(Resilient Distributed Datasets),全称是“弹性分布式数据集”,是Spark对于分布式数据进行抽象的数据模型,这种数据模型用于囊括、封装所有内存中和磁盘中的分布式数据实体。
RDD算子 VS HDFS算子?
回顾Hadoop计算流程,MapReduce计算模型中采用HDFS所做算子之间的数据接口,所有算子的临时结果都以文件的形式存储到HDFS,以供下游数据的消费,下游的算子再从HDFS读取文件转为键值对,通过Map或者Reduce操作后再以文件的存储到HDFS。不难发现,以HDFS作为数据接口才是Hadoop计算效率低的根源
RDD 的设计以数据作为第一视角,不再强调算子的重要性,算子仅仅是 RDD 数据转换的一种计算规则,map 算子和 reduce 算子纷纷被弱化、稀释。以RDD核心属性中的 dependencies 与 compute 来确定RDD流转操作,这两个操作描述了“从当前 RDD 出发,再经过怎样的计算规则与转换,可以获得新的数据集”。
可以看出RDD通过dependencies 中指定的依赖关系和 compute 定义的计算逻辑构成了一条从起点到终点的数据转换路径。这条路径在Spark有个专门的术语,叫做Lineage——血统。Spark Core 依赖血统进行依赖管理、阶段划分、任务分发、失败重试,任意一个 Spark 计算作业都可以析构为一个 Spark Core 血统。
另外三个核心属性就是partitions、partitioner 和 preferredLocations。
- partitions 属性记录了 RDD 的每一个数据分片,方便开发者灵活地访问数据集
- partitioner 则描述了 RDD 划分数据分片的规则和逻辑,采用不同的 partitioner 对 RDD 进行划分,能够以不同的方式得到不同数量的数据分片
- preferredLocations —— 位置偏好,该属性与 partitions 属性一一对应,定义了每一个数据分片的物理位置偏好。具体来说包括:本地内存、本地磁盘、本机架磁盘、其他机架磁盘
Lineage VS DAG
如果说Lineage是从数据流转的视角出发来描述RDD转换逻辑,那么DAG(Directed Acyclic Graph,有向无环图)就是就是从计算角度来描述RDD转换逻辑。由DAG实现的数据流转可以通过节点表示RDD数据,通过DAG的连接线表示算子的操作。
根据RDD之间依赖关系的不同将DAG划分成不同的Stage(调度阶段)。
- 对于窄依赖,partition的转换处理在一个Stage中完成计算。
- 对于宽依赖,由于有Shuffle的存在,只能在parent RDD处理完成后,才能开始接下来的计算,因此宽依赖是划分Stage的依据。
内存计算的由来
本着减少数据IO的目的,遵循“数据不动代码动”的原则。Spark Core尊重数据分片的存储位置的偏好,尽可能将计算分发到本地计算节点去执行,从而减少来源于数据传输带来的大幅开销,进而从整体上提升了执行性能。
为了实现这一目的,RDD的5大核心属性分别从数据视角和计算视角来刻画数据模型的抽象,任何分布式作业都可以通过RDD抽象之间的转换来实现。理论上来说,如果计算节点的内存足够多,所有的RDD转换操作都可以放到内存中来执行。
hi,我是小K,一个从事过推荐算法、大数据开发的全栈工程师,热衷于技术学习、技术分享,如果觉得这篇文章对您有所帮助,请点在评论支持。关注我获取更多有趣技术文章。