博客 Spark:一站式的分布式计算引擎

Spark:一站式的分布式计算引擎

   数栈君   发表于 2023-07-25 16:30  323  0

1、 背景简介      


    Spark最初由美国加州伯克利大学(UCBerkeley)的AMP实验室于2009年开发,是基于内存计算的大数据并行计算框架,可用于构建大型的、低延迟的数据分析应用程序。2013年,Spark加入Apache孵化器项目后,开始获得迅猛的发展,如今已成为Apache软件基金会最重要的三大分布式计算系统开源项目之一(即Hadoop、Spark、Storm)。Spark使用简练、优雅的Scala语言编写,基于Scala提供了交互式的编程体验,不仅具备MapReduce所具有的优点,且解决了Hadoop MapReduce的缺陷。Spark正以其结构一体化、功能多元化的优势逐渐成为当今大数据领域最热门的大数据计算平台。


2、特性


  • 运行速度快:

    Spark使用先进的DAG(Directed Acyclic Graph,有向无环图)执行引擎,以支持循环数据流与内存计算,基于内存的执行速度可比Hadoop MapReduce 快上百倍,基于磁盘的执行速度也能快十倍;

  • 容易使用:

    Spark支持使用Scala、Java、Python和R语言进行编程,简洁的API设计有助于用户轻松构建并行程序,并且可以通过Spark Shell进行交互式编程;

    由于Spark采用Scala语言进行开发,因此,建议采用Scala语言进行Spark应用程序的编写

  • 通用性:

    Spark提供了完整而强大的技术栈,包括SQL查询、流式计算、机器学习和图算法组件,这些组件可以无缝整合在同一个应用中,足以应对复杂的计算;

  • 运行模式多样:

    Spark可运行于独立的集群模式中,或者运行于Hadoop中,也可运行于阿里云等云环境中,并且可以访问HDFS、Cassandra、HBase、Hive等多种数据源。

  • Spark最大的特点就是将计算数据、中间结果都存储在内存中,大大减少了IO开销,因而,Spark更适合于迭代运算比较多的数据挖掘与机器学习运算。



3、spark与hadoop优缺点对比


  • hadoop表达能力有限。

    计算都必须要转化成Map和Reduce两个操作,但这并不适合所有的情况,难以描述复杂的数据处理过程;

  • hadoop磁盘IO开销大。

    每次执行时都需要从磁盘读取数据,并且在计算完成后需要将中间结果写入到磁盘中,IO开销较大;

  • hadoop延迟高。

    一次计算可能需要分解成一系列按顺序执行的MapReduce任务,任务之间的衔接由于涉及到IO开销,会产生较高延迟。

    而且,在前一个任务执行完成之前,其他任务无法开始,难以胜任复杂、多阶段的计算任务。


  • Spark的计算模式也属于MapReduce,但不局限于Map和Reduce操作,还提供了多种数据集操作类型,编程模型比MapReduce更灵活;

  •  Spark提供了内存计算,中间结果直接放到内存中,带来了更高的迭代运算效率;

  • Spark基于DAG的任务调度执行机制,要优于MapReduce的迭代执行机制。



4、spark在hadoop生态圈中所扮演的角色


  • 现状:

    在实际应用中,大数据处理主要包括以下三个类型:

    复杂的批量数据处理:

    时间跨度通常在数十分钟到数小时之间;

      可以利用Hadoop MapReduce来进行批量数据处理,基于历史数据的交互式查询:

    时间跨度通常在数十秒到数分钟之间;

    可以用Impala来进行交互式查询(Impala与Hive相似,但底层引擎不同,提供了实时交互式SQL查询)基于实时数据流的数据处理:

    时间跨度通常在数百毫秒到数秒之间。

    对于流式数据处理可以采用开源流计算框架Storm。



  • 可以看到,处理不同的场景就需要一个不同的框架来支持,难免会产生数据格式转换、维护成本变高、资源难以协调分配等问题。


Spark的设计遵循“一个软件栈满足不同应用场景”的理念,逐渐形成了一套完整的生态系统,既能够提供内存计算框架,也可以支持SQL即席查询、实时流式计算、机器学习和图计算等。Spark可以部署在资源管理器YARN之上,提供一站式的大数据解决方案。


http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/d427851914ac7994dc7874999f218a09..jpg

二、基本组件、概念及运行架构

1、基本组件如下图所示:






http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/f61ecbd657382e01fcd07b8b4bf01225..jpg
基本组件


  • Spark Core:

    Spark Core包含Spark的基本功能,如内存计算、任务调度、部署模式、故障恢复、存储管理等。

    Spark建立在统一的抽象RDD之上,使其可以以基本一致的方式应对不同的大数据处理场景;

    通常所说的Apache Spark,就是指Spark Core;


  • Spark SQL:

    Spark SQL允许开发人员直接处理RDD,同时也可查询Hive、HBase等外部数据源。

    Spark SQL的一个重要特点是其能够统一处理关系表和RDD,使得开发人员可以轻松地使用SQL命令进行查询,并进行更复杂的数据分析;


  • Spark Streaming:

    Spark Streaming支持高吞吐量、可容错处理的实时流数据处理,其核心思路是将流式计算分解成一系列短小的批处理作业。

    Spark Streaming支持多种数据输入源,如Kafka、Flume和TCP套接字等;


  • MLlib(机器学习):

    MLlib提供了常用机器学习算法的实现,包括聚类、分类、回归、协同过滤等,降低了机器学习的门槛,开发人员只要具备一定的理论知识就能进行机器学习的工作;


  • GraphX(图计算):

    GraphX是Spark中用于图计算的API,可认为是Pregel在Spark上的重写及优化,Graphx性能良好,拥有丰富的功能和运算符,能在海量数据上自如地运行复杂的图算法。


2、基本概念(重要)


  • RDD:

    是弹性分布式数据集(Resilient Distributed Dataset)的简称,是分布式内存的一个抽象概念,提供了一种高度受限的共享内存模型;

  •  DAG:

    是Directed Acyclic Graph(有向无环图)的简称,反映RDD之间的依赖转换关系;

  •  Executor:

    是运行在工作节点(Worker Node)上的一个进程,负责运行任务,并为应用程序存储数据;

  •  应用:

    程序员编写的Spark应用程序;

  •  任务:

    运行在Executor上的工作单元;

  •  作业:

    一个作业包含多个RDD及作用于相应RDD上的各种操作;

  •  阶段:

    是作业的基本调度单位,一个作业会分为多组任务,每组任务被称为“阶段”,或者也被称为“任务集”。


3、运行架构


一个应用(Application)由一个任务控制节点(Driver)和若干个作业(Job)构成,一个作业由多个阶段(Stage)构成,一个阶段由多个任务(Task)组成。当执行一个应用时,任务控制节点会向集群管理器(Cluster Manager)申请资源,启动进程(Executor),并向Executor发送应用程序代码和文件,然后在Executor上执行任务,运行结束后,执行结果会返回给任务控制节点,或者写到HDFS或者其他数据库中。如下图所示:





http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/7b05473b53279cbb2443e3305c3ffe38..jpg
运行架构


4、基本流程


  • 首先应用提交后,任务控制节点(Driver)创建一个sparkContent,即运行环境上下文;

  • 然后sparkContent与资源管理器通信,注册并申请运行Executor的资源; 

资源管理器为Executor分配资源,并启动Executor进程,Executor运行情况将随着“心跳”发送到资源管理器上;

  • SparkContext根据RDD的依赖关系构建DAG图,DAG图提交给DAG调度器(DAGScheduler)进行解析,将DAG图分解成多个“阶段”(每个阶段都是一个任务集),并且计算出各个阶段之间的依赖关系,然后把一个个“任务集”提交给底层的任务调度器(TaskScheduler)进行处理;

  • Executor向SparkContext申请任务,任务调度器将任务分发给Executor运行;

  • 任务在Executor上运行,把执行结果反馈给任务调度器,然后反馈给DAG调度器,运行完毕后写入数据并释放所有资源。





http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/39cebf3ae044f3e36839be8c3709b639..jpg
基本流程


5、RDD的设计背景


    目前存在许多迭代式算法不同计算阶段之间会重用中间结果,即一个阶段的输出结果会作为下一个阶段的输入。但是,目前的MapReduce框架都是把中间结果写入到HDFS中,带来了大量的数据复制、磁盘IO和序列化开销。

    RDD就是为了满足这种需求而出现的,它提供了一个抽象的数据架构,只需将具体的应用逻辑表达为一系列转换处理,从而避免了中间结果的存储,大大降低了数据复制、磁盘IO和序列化开销。


6、RDD的产生(重要)


RDD是只读的记录分区的集合,不能直接修改,只能基于稳定的物理存储中的数据集来创建RDD,或者通过在其他RDD上执行确定的转换操作(如map、join和groupBy)而创建得到新的RDD。


7、RDD的操作(重要)


    RDD提供了一组丰富的操作以支持常见的数据运算,分为“行动”(Action)和“转换”(Transformation)两种类型,前者用于执行计算并指定输出的形式,后者指定RDD之间的相互依赖关系。两类操作的主要区别是,转换操作(比如map、filter、groupBy、join等)接受RDD并返回RDD,而行动操作(比如count、collect等)接受RDD但是返回非RDD(即输出一个值或结果)。


    Spark用Scala语言实现了RDD的API,程序员可以通过调用API实现对RDD的各种操作。RDD典型的执行过程如下:

  • RDD读入外部数据源(或者内存中的集合)进行创建;

  • RDD经过一系列的“转换”操作,每一次都会产生不同的RDD,供给下一个“转换”使用;

  • 最后一个RDD经“行动”操作进行处理,并输出到外部数据源(或者变成Scala集合或标量)。


    需要说明的是,RDD采用了惰性调用,真正的计算发生在RDD的“行动”操作,对于“行动”之前的所有“转换”操作,Spark只是记录下“转换”操作应用的一些基础数据集以及RDD生成的轨迹,即相互之间的依赖关系,而不会触发真正的计算。

所以从宏观上来讲,一个spark应用程序,就是针对RDD的一系列操作运算。





http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/b5f73f946cb1e29cd40c685c578dbc72..jpg
RDD操作


8、RDD的特性


强大的容错性:由于RDD是只读的不可修改,若要修改就要从父RDD转换到子RDD,所以只要记录下RDD之间的血缘关系就可以完整的计算出数据,不必在多个集群节点之间来回的复制冗余数据。


高效性:数据在内存中的多个RDD之间进行传递,不必落地到磁盘或HDFS上;并且可以存放对象,避免了来回的序列化和反序列化


9、RDD的依赖关系


RDD中不同的操作会使得不同RDD中的分区会产生不同的依赖。RDD中的依赖关系分为窄依赖(Narrow Dependency)与宽依赖(Wide Dependency)

窄依赖表现为一个父RDD的分区对应于一个子RDD的分区,或多个父RDD的分区对应于一个子RDD的分区;窄依赖可以并行的计算,效率更高

宽依赖则表现为存在一个父RDD的一个分区对应一个子RDD的多个分区  宽依赖涉及到多个父RDD分区,需要整合计算,效率偏低





http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/c07c6f0804ed9a01af909697c8649141..jpg
宽依赖窄依赖区别

总体而言,如果父RDD的一个分区只被一个子RDD的一个分区所使用就是窄依赖,否则就是宽依赖。窄依赖典型的操作包括map、filter、union等,宽依赖典型的操作包括groupByKey、sortByKey等。一般来说,使用聚合函数进行操作的都是宽依赖;或者想象一下接下来的操作是否需要整合全部数据来操作,如果需要就是宽依赖,比如分组、排序、求最大、最小、平均值等等。


10、阶段划分


阶段划分方法是:在DAG图中进行反向解析,遇到宽依赖就断开,遇到窄依赖就把当前的RDD加入到当前的阶段中;将窄依赖尽量划分在同一个阶段中,可以实现并行计算,效率会更高





http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/7cbfaa3c31e8c31f2003e8d421c8606f..jpg
阶段划分

这样划分出多个“阶段”以后,每个阶段都代表了一组关联的、相互之间没有Shuffle依赖关系的任务组成的任务集合。每个任务集合会被提交给任务调度器(TaskScheduler)进行处理,由任务调度器将任务分发给Executor运行。


11、RDD整体运行流程


  • 创建RDD对象;

  • SparkContext负责计算RDD之间的依赖关系,构建DAG;

  • DAGScheduler负责把DAG图分解成多个阶段,每个阶段中包含了多个任务,每个任务会被任务调度器分发给各个工作节点(Worker Node)上的Executor去执行。





http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/5415deed42b22377542cd05b482fb3bf..jpg
RDD运行流程



http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/d427851914ac7994dc7874999f218a09..jpg

三、部署模式及架构


1、部署模式
  • Local模式:单机模式,不使用集群管理器。


  • StandAlone模式:相当于单机模式,使用本身自带的资源调度管理服务,可以独立部署到一个集群中,而不需要依赖其他系统来为其提供资源管理调度服务。


  • Spark on Mesos模式:

Mesos是一种资源调度管理框架,可以为运行在它上面的Spark提供服务。由于Mesos和Spark存在一定的血缘关系,因此,Spark框架在进行设计开发的时候,就充分考虑到了对Mesos的充分支持,这也是官方推荐的模式


  • Spark on YARN模式:

Spark可运行于YARN之上,与Hadoop进行统一部署,即“Spark on YARN”,其架构如图所示,资源管理和调度依赖YARN,分布式存储则依赖HDFS。

 

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/d9f38e7e4b56b5965f71297968092078..jpg

部署模式案例

  


2、从“hadoop+storm”架构 转向 spark架构


      目前大部分企业采用Hadoop处理批量历史数据的实时查询和离线分析,而Storm则负责对流数据的实时处理。

    而切换到Spark以后,可以应对批处理和实时处理的不同场景,但是需要注意的是Spark Streaming的原理是将流数据分解成一系列短小的批处理作业,每个短小的批处理作业使用面向批处理的Spark Core进行处理,通过这种方式变相实现流计算,而不是真正实时的流计算。对于需要毫秒级实时响应的企业应用而言,仍然需要采用流计算框架(如Storm)。





http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/6905af370ceb2edaff00d3366de03b02..jpg

用Spark架构满足批处理和流处理需求

最终版架构可以使用hadoop+spark+storm同时部署的架构,它们可同时运行于资源管理框架YARN之上。

免责申明:

本文系转载,版权归原作者所有,如若侵权请联系我们进行删除!

《数据治理行业实践白皮书》下载地址:https://fs80.cn/4w2atu

《数栈V6.0产品白皮书》下载地址:https://fs80.cn/cw0iw1

想了解或咨询更多有关袋鼠云大数据产品、行业解决方案、客户案例的朋友,浏览袋鼠云官网:https://www.dtstack.com/?src=bbs

同时,欢迎对大数据开源项目有兴趣的同学加入「袋鼠云开源框架钉钉技术群」,交流最新开源技术信息,群号码:30537511,项目地址:

https://github.com/DTStack


0条评论
社区公告
  • 大数据领域最专业的产品&技术交流社区,专注于探讨与分享大数据领域有趣又火热的信息,专业又专注的数据人园地

最新活动更多
微信扫码获取数字化转型资料
钉钉扫码加入技术交流群