Spark2.1.0模型设计与基本架构(上)
随着近十年互联网的迅猛发展,越来越多的人融入了互联网——利用搜索引擎查询词条或问题;社交圈子从现实搬到了Facebook、Twitter、微信等社交平台上;女孩子们现在少了逛街,多了在各大电商平台上的购买;喜欢棋牌的人能够在对战平台上找到世界各地的玩家对弈。在国内随着网民数量的持续增加,造成互联网公司的数据在体量、产生速度、多样性等方面呈现出巨大的变化。本文将对Spark的背景、基础知识、模块设计进行介绍。
随着近十年互联网的迅猛发展,越来越多的人融入了互联网——利用搜索引擎查询词条或问题;社交圈子从现实搬到了Facebook、Twitter、微信等社交平台上;女孩子们现在少了逛街,多了在各大电商平台上的购买;喜欢棋牌的人能够在对战平台上找到世界各地的玩家对弈。在国内随着网民数量的持续增加,造成互联网公司的数据在体量、产生速度、多样性等方面呈现出巨大的变化。
互联网产生的数据相较于传统软件产生的数据,有着数据挖掘的巨大潜力。通过对数据的挖掘,可以统计出PV、UV,计算出不同设备与注册率、促销与下单率之间的关系,甚至构建热点分析、人群画像等算法模型,产生一系列报表、图形、离线统计、实时计算的产品。互联网公司如果能有效利用这些数据,将对决策和战略发展起到至关重要的作用。
在大数据的大势之下,Hadoop、Spark、Flink、Storm、Dremel、Impala、Tez等一系列大数据技术如雨后春笋般不断涌现。工程师们正在使用这些工具在摸索中前行。
Spark是一个通用的并行计算框架,由加州伯克利大学(UCBerkeley)的AMP实验室开发于2009年,并于2010年开源。2013年成长为Apache旗下在大数据领域最活跃的开源项目之一。
Spark目前已经走过了0.x和1.x两个时代,现在正在2.x时代稳步发展。Spark从2012年10月15日发布0.6到2016年1月4日发布1.6只经过了三年时间,那时候差不多每个月都会有新的版本发布,平均每个季度会发布一个新的二级版本。
自从2016年7月发布了2.0.0版本以来,只在当年12月又发布了2.1.0版本,直到目前为止还没有新的二级版本发布。Spark发布新版本的节奏明显慢了下来,当然这也跟Spark团队过于激进的决策(比如很多API不能向前兼容,让用户无力吐槽)有关。
Spark也是基于map reduce 算法模型实现的分布式计算框架,拥有Hadoop MapReduce所具有的优点,并且解决了Hadoop MapReduce中的诸多缺陷。
Hadoop MRv1的局限
早在Hadoop1.0版本,当时采用的是MRv1版本的MapReduce编程模型。MRv1版本的实现都封装在org.apache.hadoop.mapred包中,MRv1的Map和Reduce是通过接口实现的。MRv1包括三个部分:
- 运行时环境(JobTracker和TaskTracker);
- 编程模型(MapReduce);
- 数据处理引擎(Map任务和Reduce任务)。
MRv1存在以下不足。
- 可扩展性差:在运行时,JobTracker既负责资源管理又负责任务调度,当集群繁忙时,JobTracker很容易成为瓶颈,最终导致它的可扩展性问题。
- 可用性差:采用了单节点的Master,没有备用Master及选举操作,这导致一旦Master出现故障,整个集群将不可用。
- 资源利用率低:TaskTracker 使用slot等量划分本节点上的资源量。slot代表计算资源(CPU、内存等)。一个Task 获取到一个slot 后才有机会运行,Hadoop 调度器负责将各个TaskTracker 上的空闲slot 分配给Task 使用。一些Task并不能充分利用slot,而其他Task也无法使用这些空闲的资源。slot 分为Map slot 和Reduce slot 两种,分别供MapTask 和Reduce Task 使用。有时会因为作业刚刚启动等原因导致MapTask很多,而Reduce Task任务还没有调度的情况,这时Reduce slot也会被闲置。
- 不能支持多种MapReduce框架:无法通过可插拔方式将自身的MapReduce框架替换为其他实现,如Spark、Storm等。
MRv1的示意如图1。
图1 MRv1示意图
Apache为了解决以上问题,对Hadoop升级改造,MRv2最终诞生了。MRv2中,重用了MRv1中的编程模型和数据处理引擎。但是运行时环境被重构了。JobTracker被拆分成了通用的资源调度平台(ResourceManager,简称RM)、节点管理器(NodeManager)和负责各个计算框架的任务调度模型(ApplicationMaster,简称AM)。ResourceManager依然负责对整个集群的资源管理,但是在任务资源的调度方面只负责将资源封装为Container分配给ApplicationMaster 的一级调度,二级调度的细节将交给ApplicationMaster去完成,这大大减轻了ResourceManager 的压力,使得ResourceManager 更加轻量。NodeManager负责对单个节点的资源管理,并将资源信息、Container运行状态、健康状况等信息上报给ResourceManager。ResourceManager 为了保证Container的利用率,会监控Container,如果Container未在有限的时间内使用,ResourceManager将命令NodeManager杀死Container,以便于将资源分配给其他任务。MRv2的核心不再是MapReduce框架,而是Yarn。在以Yarn为核心的MRv2中,MapReduce框架是可插拔的,完全可以替换为其他MapReduce实现,比如Spark、Storm等。MRv2的示意如图2所示。
图2 MRv2示意图
Hadoop MRv2虽然解决了MRv1中的一些问题,但是由于对HDFS的频繁操作(包括计算结果持久化、数据备份、资源下载及Shuffle等)导致磁盘I/O成为系统性能的瓶颈,因此只适用于离线数据处理或批处理,而不能支持对迭代式、流式数据的处理。
Spark的特点
Spark看到MRv2的问题,对MapReduce做了大量优化,总结如下:
- 减少磁盘I/O:随着实时大数据应用越来越多,Hadoop作为离线的高吞吐、低响应框架已不能满足这类需求。HadoopMapReduce的map端将中间输出和结果存储在磁盘中,reduce端又需要从磁盘读写中间结果,势必造成磁盘IO成为瓶颈。Spark允许将map端的中间输出和结果存储在内存中,reduce端在拉取中间结果时避免了大量的磁盘I/O。Hadoop Yarn中的ApplicationMaster申请到Container后,具体的任务需要利用NodeManager从HDFS的不同节点下载任务所需的资源(如Jar包),这也增加了磁盘I/O。Spark将应用程序上传的资源文件缓冲到Driver本地文件服务的内存中,当Executor执行任务时直接从Driver的内存中读取,也节省了大量的磁盘I/O。
- 增加并行度:由于将中间结果写到磁盘与从磁盘读取中间结果属于不同的环节,Hadoop将它们简单的通过串行执行衔接起来。Spark把不同的环节抽象为Stage,允许多个Stage既可以串行执行,又可以并行执行。
- 避免重新计算:当Stage中某个分区的Task执行失败后,会重新对此Stage调度,但在重新调度的时候会过滤已经执行成功的分区任务,所以不会造成重复计算和资源浪费。
- 可选的Shuffle排序:HadoopMapReduce在Shuffle之前有着固定的排序操作,而Spark则可以根据不同场景选择在map端排序或者reduce端排序。
- 灵活的内存管理策略:Spark将内存分为堆上的存储内存、堆外的存储内存、堆上的执行内存、堆外的执行内存4个部分。Spark既提供了执行内存和存储内存之间是固定边界的实现,又提供了执行内存和存储内存之间是“软”边界的实现。Spark默认使用“软”边界的实现,执行内存或存储内存中的任意一方在资源不足时都可以借用另一方的内存,最大限度的提高资源的利用率,减少对资源的浪费。Spark由于对内存使用的偏好,内存资源的多寡和使用率就显得尤为重要,为此Spark的内存管理器提供的Tungsten实现了一种与操作系统的内存Page非常相似的数据结构,用于直接操作操作系统内存,节省了创建的Java对象在堆中占用的内存,使得Spark对内存的使用效率更加接近硬件。Spark会给每个Task分配一个配套的任务内存管理器,对Task粒度的内存进行管理。Task的内存可以被多个内部的消费者消费,任务内存管理器对每个消费者进行Task内存的分配与管理,因此Spark对内存有着更细粒度的管理。
基于以上所列举的优化,Spark官网声称性能比Hadoop快100倍,如图3所示。即便是内存不足需要磁盘I/O时,其速度也是Hadoop的10倍以上。
图3 Hadoop与Spark执行逻辑回归时间比较
Spark还有其他一些特点。
- 检查点支持:Spark的RDD之间维护了血缘关系(lineage),一旦某个RDD失败了,则可以由父RDD重建。虽然lineage可用于错误后RDD的恢复,但对于很长的lineage来说,恢复过程非常耗时。如果应用启用了检查点,那么在Stage中的Task都执行成功后,SparkContext将把RDD计算的结果保存到检查点,这样当某个RDD执行失败后,在由父RDD重建时就不需要重新计算,而直接从检查点恢复数据。
- 易于使用。Spark现在支持Java、Scala、Python和R等语言编写应用程序,大大降低了使用者的门槛。自带了80多个高等级操作符,允许在Scala,Python,R的shell中进行交互式查询。
- 支持交互式:Spark使用Scala开发,并借助于Scala类库中的Iloop实现交互式shell,提供对REPL(Read-eval-print-loop)的实现。
- 支持SQL查询。在数据查询方面,Spark支持SQL及Hive SQL,这极大的方便了传统SQL开发和数据仓库的使用者。
- 支持流式计算:与MapReduce只能处理离线数据相比,Spark还支持实时的流计算。Spark依赖SparkStreaming对数据进行实时的处理,其流式处理能力还要强于Storm。
- 可用性高。Spark自身实现了Standalone部署模式,此模式下的Master可以有多个,解决了单点故障问题。Spark也完全支持使用外部的部署模式,比如YARN、Mesos、EC2等。
- 丰富的数据源支持:Spark除了可以访问操作系统自身的文件系统和HDFS,还可以访问Kafka、Socket、Cassandra、HBase、Hive、Alluxio(Tachyon)以及任何Hadoop的数据源。这极大地方便了已经使用HDFS、HBase的用户顺利迁移到Spark。
- 丰富的文件格式支持:Spark支持文本文件格式、Csv文件格式、Json文件格式、Orc文件格式、Parquet文件格式、Libsvm文件格式,也有利于Spark与其他数据处理平台的对接。
Spark使用场景
Hadoop常用于解决高吞吐、批量处理的业务场景,例如对浏览量的离线统计。如果需要实时查看浏览量统计信息,Hadoop显然不符合这样的要求。Spark通过内存计算能力极大地提高了大数据处理速度,满足了以上场景的需要。此外,Spark还支持交互式查询,SQL查询,流式计算,图计算,机器学习等。通过对Java、Python、Scala、R等语言的支持,极大地方便了用户的使用。
笔者就目前所知道的Spark应用场景,进行介绍。
1.医疗健康
看病是一个非常典型的分析过程——医生根据患者的一些征兆、检验结果,结合医生本人的经验得出结论,最后给出相应的治疗方案。现在国内的医疗状况是各地区医疗水平参差不齐,医疗资源也非常紧张,特别是高水平医生更为紧缺,好医院的地区分布很不均衡。大城市有更完善的医疗体系,而农村可能就只有几个赤脚医生。一些农民看病可能要从村里坐车到镇,再到县城,再到地级市甚至省会城市,看病的路程堪比征程。
大数据根据患者的患病征兆、检验报告,通过病理分析模型找出病因并给出具体的治疗方案。即便是医疗水平落后的地区,只需要输入患者的患病征兆和病例数据既可体验高水平医师的服务。通过Spark从海量数据中实时计算出病因,各个地区的医疗水平和效率将获得大幅度提升,同时也能很好的降低因为医生水平而导致误诊的概率。
实施医疗健康的必然措施是监测和预测。通过监测不断更新整个医疗基础库的知识,并通过医疗健康模型预测出疾病易发的地区和人群。
2.电商
通过对用户的消费习惯、季节、产品使用周期等数据的收集,建立算法模型来判断消费者未来一个月、几个月甚至一年的消费需求(不是简单的根据你已经消费的产品,显示推荐广告位),进而提高订单转化率。
在市场营销方面,通过给买家打标签,构建人群画像,进而针对不同的人群,精准投放广告、红包或优惠券。
3.安全领域
面对日益复杂的网络安全,通过检测和数据分析区分出不同的安全类型。并针对不同的安全类型,实施不同的防御、打击措施。
- 端安全:使用安全卫士、云查杀对经过大数据分析得到的病毒、木马等进行防御。
- 电商安全:反刷单、反欺诈、合规。
- 金融安全:风险控制。
- 企业安全:反入侵。
- 国家安全:舆情监测,打击罪犯。
4.金融领域
构建金融云,通过对巨量的计量数据收集。通过Spark实时处理分析,利用低延迟的数据处理能力,应对急迫的业务需求和数据增长。
量化投资——收集大宗商品的价格,黄金,石油等各种数据,分析黄金、股票等指数趋势,支持投资决策。
除了以上领域外,在搜索引擎、生态圈异常检测、生物计算等诸多领域都有广泛的应用场景。
版本变迁
经过5年多的发展,Spark目前的大版本是2.3.0。Spark主要版本的发展过程如下:
- Spark诞生于UCBerkeley的AMP实验室(2009)。
- Spark正式对外开源(2010)。
- Spark 0.6.0版本发布(2012-10-15),大范围的性能改进,增加了一些新特性,并对Standalone部署模式进行了简化。
- Spark 0.7.0版本发布(2013-02-27),增加了更多关键特性,例如:PythonAPI、Spark Streaming的alpha版本等。
- Spark接受进入Apache孵化器(2013-06-21)。
- Spark 0.8.0版本发布(2013-09-25),一些新功能及可用性改进。
- Spark 0.8.1版本发布(2013-12-19),支持Scala 2.9,YARN 2.2,Standalone部署模式下调度的高可用性,shuffle的优化等。
- Spark 0.9.0版本发布(2014-02-02),增加了GraphX、机器学习、流式计算等新特性,对核心引擎的优化(外部聚合、加强对YARN的支持)等。
- Spark 1.0.0版本发布(2014-05-30),增加了Spark SQL。对MLlib、GraphX和Spark Streaming都增加了新特性并进行了优化。Spark核心引擎还增加了对安全YARN集群的支持。
- Spark 1.1.0版本发布(2014-09-11)。对MLlib andSpark SQL进行了显著的扩展等。
- Spark 1.2.0版本发布(2014-12-18),Spark SQL增加了对HIVE 13、动态分区的支持,SparkStreaming增加了Python语言的API等。
- Spark 1.3.0版本发布(2015-03-13),在Spark SQL 中增加了DataFrameAPI。
- Spark 1.4.0版本发布(2015-06-11),增加了R语言的API,对Spark核心引擎的可用性进行了改进,对MLlib和Spark Streaming进行了扩展。
- Spark 1.5.0版本发布(2015-09-09),对各种功能和API进行了修改或改进。
- Spark 1.6.0版本发布(2016-01-04),对Spark Core、Spark SQL、Spark Streaming、MLlib的API进行了改进,对SparkCore和Spark SQL的性能进行了优化。
- Spark 2.0.0版本发布(2016-07-26),增加API的稳定性,对SQL 2003标准的支持,性能的优化,结构化的Streaming,R语言UDF的支持等。
- Spark 2.1.0版本发布(2016-12-28),主要对结构化的Streaming进行了改进。
- Spark 2.2.0版本发布(2017-07-11),正式提供非实验性质的结构化的Streaming。
- Spark 2.3.0版本发布(2018-02-28),增加结构化Streaming的连续处理,Kubernetes的调度后端。
基本概念
要想对Spark有整体性的了解,推荐读者阅读Matei Zaharia的Spark论文。此处笔者先介绍Spark中的一些概念:
- RDD(resillient distributed dataset):弹性分布式数据集。Spark应用程序通过使用Spark的转换API可以将RDD封装为一系列具有血缘关系的RDD,也就是DAG。只有通过Spark的动作API才会将RDD及其DAG提交到DAGScheduler。RDD的祖先一定是一个跟数据源相关的RDD,负责从数据源迭代读取数据。
- DAG(Directed Acycle graph):有向无环图。在图论中,如果一个有向图无法从某个顶点出发经过若干条边回到该点,则这个图是一个有向无环图(DAG图)。Spark使用DAG来反映各RDD之间的依赖或血缘关系。
- Partition:数据分区。即一个RDD的数据可以划分为多少个分区。Spark根据Partition的数量来确定Task的数量。
- NarrowDependency:窄依赖。即子RDD依赖于父RDD中固定的Partition。NarrowDependency分为OneToOneDependency和RangeDependency两种。
- ShuffleDependency:Shuffle依赖,也称为宽依赖。即子RDD对父RDD中的所有Partition都可能产生依赖。子RDD对父RDD各个Partition的依赖将取决于分区计算器(Partitioner)的算法。
- Job:用户提交的作业。当RDD及其DAG被提交给DAGScheduler调度后,DAGScheduler会将所有RDD中的转换及动作视为一个Job。一个Job由一到多个Task组成。
- Stage:Job的执行阶段。DAGScheduler按照ShuffleDependency作为Stage的划分节点对RDD的DAG进行Stage划分(上游的Stage将为ShuffleMapStage)。因此一个Job可能被划分为一到多个Stage。Stage分为ShuffleMapStage和ResultStage两种。
- Task:具体执行任务。一个Job在每个Stage内都会按照RDD的Partition 数量,创建多个Task。Task分为ShuffleMapTask和ResultTask两种。ShuffleMapStage中的Task为ShuffleMapTask,而ResultStage中的Task为ResultTask。ShuffleMapTask和ResultTask类似于Hadoop中的 Map任务和Reduce任务。
Scala与Java的比较
目前越来越多的语言可以运行在Java虚拟机上,Java平台上的多语言混合编程正成为一种潮流。在混合编程模式下可以充分利用每种语言的特点和优势,以便更好地完成功能。Spark同时选择了Scala和Java作为开发语言,也是为了充分利用二者各自的优势。表1对这两种语言进行比较。
表1 Scala与Java的比较
|
Scala |
Java |
语言类型 |
面向函数为主,兼有面向对象 |
面向对象(Java8也增加了lambda函数编程) |
简洁性 |
非常简洁 |
不简洁 |
类型推断 |
丰富的类型推断,例如深度和链式的类型推断、 duck type 、隐式类型转换等,但也因此增加了编译时长 |
少量的类型推断 |
可读性 |
一般,丰富的语法糖导致的各种奇幻用法,例如方法签名、隐式转换 |
好 |
学习成本 |
较高 |
一般 |
语言特性 |
非常丰富的语法糖和更现代的语言特性,例如 Option 、模式匹配、使用空格的方法调用 |
丰富 |
并发编程 |
使用Actor的消息模型 |
使用阻塞、锁、阻塞队列等 |
注意:虽然Actor是Scala语言最初进行推广时,最吸引人的特性之一,但是随着Akka更加强大的Actor类库的出现,Scala已经在官方网站宣布废弃Scala自身的Actor编程模型,转而全面拥抱Akka提供的Actor编程模型。与此同时,从Spark2.0.0版本开始,Spark却放弃了使用Akka,转而使用Netty实现了自己的Rpc框架。遥想当年Scala“鼓吹”Actor编程模型优于Java的同步编程模型时,又有谁会想到如今这种场面呢?
Scala作为函数式编程的代表,天生适合并行运行,如果用Java语言实现相同的功能会显得非常臃肿。很多介绍Spark的新闻或文章经常以Spark内核代码行数少或API精炼等内容作为宣传的“法器”,这应该也是选择Scala的原因之一。另一方面,由于函数式编程更接近计算机思维,因此便于通过算法从大数据中建模,这也更符合Spark作为大数据框架的理念吧!
由于Java适合服务器、中间件开发,所以Spark使用Java更多的是开发底层的基础设施或中间件。
模块设计
整个Spark主要由以下模块组成:
- Spark Core:Spark的核心功能实现,包括:基础设施、SparkContext(Application通过SparkContext提交)、Spark执行环境(SparkEnv)、存储体系、调度系统、计算引擎、部署模式、任务提交与执行等。
- Spark SQL:提供SQL处理能力,便于熟悉关系型数据库操作的工程师进行交互查询。此外,还为熟悉Hive开发的用户提供了对Hive SQL的支持。
- Spark Streaming:提供流式计算处理能力,目前支持ApacheKafka、Apache Flume、Amazon Kinesis和简单的TCP套接字等数据源。在早期的Spark版本中还自带对Twitter、MQTT、ZeroMQ等的支持,现在用户想要支持这些工具必须自己开发实现。此外,Spark Streaming还提供窗口操作用于对一定周期内的流数据进行处理。
- GraphX:基于图论,实现的支持分布式的图计算处理框架。GraphX的基础是点、边等图论的理论。GraphX 基于图计算的Pregel模型提供了多种多样的Pregel API,这些Pregel API可以解决图计算中的常见问题。
- MLlib:Spark提供的机器学习库。MLlib提供了机器学习相关的统计、分类、回归等领域的多种算法实现。其一致的API接口大大降低了用户的学习成本。
Spark SQL、Spark Streaming、GraphX、MLlib的能力都是建立在核心引擎之上,如图4。
图4 Spark各模块依赖关系
Spark核心功能
Spark Core中提供了Spark最基础与最核心的功能,主要包括:
- 基础设施:在Spark中有很多基础设施,被Spark中的各种组件广泛使用。这些基础设施包括Spark配置(SparkConf)、Spark内置的Rpc框架(在早期Spark版本中Spark使用的是Akka)、事件总线(ListenerBus)、度量系统。SparkConf用于管理Spark应用程序的各种配置信息。Spark内置的Rpc框架使用Netty实现,有同步和异步的多种实现,Spark各个组件间的通信都依赖于此Rpc框架。如果说Rpc框架是跨机器节点不同组件间的通信设施,那么事件总线就是SparkContext内部各个组件间使用事件——监听器模式异步调用的实现。度量系统由Spark中的多种度量源(Source)和多种度量输出(Sink)构成,完成对整个Spark集群中各个组件运行期状态的监控。
- SparkContext:通常而言,用户开发的Spark应用程序(Application)的提交与执行都离不开SparkContext的支持。在正式提交Application之前,首先需要初始化SparkContext。SparkContext隐藏了网络通信、分布式部署、消息通信、存储体系、计算引擎、度量系统、文件服务、Web UI等内容,应用程序开发者只需要使用SparkContext提供的API完成功能开发。
- SparkEnv:Spark执行环境(SparkEnv)是Spark中的Task运行所必须的组件。SparkEnv内部封装了Rpc环境(RpcEnv)、序列化管理器、广播管理器(BroadcastManager)、map任务输出跟踪器(MapOutputTracker)、存储体系、度量系统(MetricsSystem)、输出提交协调器(OutputCommitCoordinator)等Task运行所需的各种组件。
- 存储体系:Spark优先考虑使用各节点的内存作为存储,当内存不足时才会考虑使用磁盘,这极大地减少了磁盘I/O,提升了任务执行的效率,使得Spark适用于实时计算、迭代计算、流式计算等场景。在实际场景中,有些Task是存储密集型的,有些则是计算密集型的,所以有时候会造成存储空间很空闲,而计算空间的资源又很紧张。Spark的内存存储空间与执行存储空间之间的边界可以是“软”边界,因此资源紧张的一方可以借用另一方的空间,这既可以有效利用资源,又可以提高Task的执行效率。此外,Spark的内存空间还提供了Tungsten的实现,直接操作操作系统的内存。由于Tungsten省去了在堆内分配Java对象,因此能更加有效的利用系统的内存资源,并且因为直接操作系统内存,空间的分配和释放也更迅速。在Spark早期版本还使用了以内存为中心的高容错的分布式文件系统Alluxio(Tachyon)供用户进行选择。Alluxio能够为Spark提供可靠的内存级的文件共享服务。
- 调度系统:调度系统主要由DAGScheduler和TaskScheduler组成,它们都内置在SparkContext中。DAGScheduler负责创建Job、将DAG中的RDD划分到不同的Stage、给Stage创建对应的Task、批量提交Task等功能。TaskScheduler负责按照FIFO或者FAIR等调度算法对批量Task进行调度;为Task分配资源;将Task发送到集群管理器分配给当前应用的Executor上由Executor负责执行等工作。现如今,Spark增加了SparkSession和DataFrame等新的API,SparkSession底层实际依然依赖于SparkContext。
- 计算引擎:计算引擎由内存管理器(MemoryManager)、Tungsten、任务内存管理器(TaskMemoryManager)、Task、外部排序器(ExternalSorter)、Shuffle管理器(ShuffleManager)等组成。MemoryManager除了对存储体系中的存储内存提供支持和管理,还外计算引擎中的执行内存提供支持和管理。Tungsten除用于存储外,也可以用于计算或执行。TaskMemoryManager对分配给单个Task的内存资源进行更细粒度的管理和控制。ExternalSorter用于在map端或reduce端对ShuffleMapTask计算得到的中间结果进行排序、聚合等操作。ShuffleManager用于将各个分区对应的ShuffleMapTask产生的中间结果持久化到磁盘,并在reduce端按照分区远程拉取ShuffleMapTask产生的中间结果。
Spark扩展功能
为了扩大应用范围,Spark陆续增加了一些扩展功能,主要包括:
- Spark SQL:由于SQL具有普及率高、学习成本低等特点,为了扩大Spark的应用面,因此增加了对SQL及Hive的支持。Spark SQL的过程可以总结为:首先使用SQL语句解析器(SqlParser)将SQL转换为语法树(Tree),并且使用规则执行器(RuleExecutor)将一系列规则(Rule)应用到语法树,最终生成物理执行计划并执行的过程。其中,规则包括语法分析器(Analyzer)和优化器(Optimizer)。Hive的执行过程与SQL类似。
- Spark Streaming:Spark Streaming与Apache Storm类似,也用于流式计算。SparkStreaming支持Kafka、Flume、Kinesis和简单的TCP套接字等多种数据输入源。输入流接收器(Receiver)负责接入数据,是接入数据流的接口规范。Dstream是Spark Streaming中所有数据流的抽象,Dstream可以被组织为DStreamGraph。Dstream本质上由一系列连续的RDD组成。
- GraphX:Spark提供的分布式图计算框架。GraphX主要遵循整体同步并行计算模式(Bulk Synchronous Parallell,简称BSP)下的Pregel模型实现。GraphX提供了对图的抽象Graph,Graph由顶点(Vertex)、边(Edge)及继承了Edge的EdgeTriplet(添加了srcAttr和dstAttr用来保存源顶点和目的顶点的属性)三种结构组成。GraphX目前已经封装了最短路径、网页排名、连接组件、三角关系统计等算法的实现,用户可以选择使用。
- MLlib:Spark提供的机器学习框架。机器学习是一门涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多领域的交叉学科。MLlib目前已经提供了基础统计、分类、回归、决策树、随机森林、朴素贝叶斯、保序回归、协同过滤、聚类、维数缩减、特征提取与转型、频繁模式挖掘、预言模型标记语言、管道等多种数理统计、概率论、数据挖掘方面的数学算法。
有关Spark2.1.0架构相关的其余内容,请继续阅读《Spark2.1.0模型设计与基本架构(下)》一文。
引用:本文的图1和图2都来源自http://blog.chinaunix.net/uid-28311809-id-4383551.html。