本文会依次介绍spark的发展过程、与Hadoop的区别、Spark生态、Spark的运行架构。内容比较多,大家可以分模块看,此外在文章前段如果出现一些不易懂的专业名词,请不要着急后面会依次介绍。
Spark知识涉及面比较广,会与HBase、HDFS、Kafka、ML等都交集,路长且艰,小编仅与读者共同前行,若有任何不同意见,欢迎留言指教。
一、Spark基本介绍
Spark是由加州伯克利大学的AMP实验室开发的,后开源给Apache,成为其顶级开源项目之一。Spark主要与Hadoop生态的MapReduce对标,在2014年打破了MapReduce保持的基准排序记录,其仅使用206个节点在23分钟的时间里完成了100TB数据的排序,而MapReduce则是使用2000个节点在72分钟的时间里完成同样数据的排序。也就是说,Spark仅使用了十分之一的计算资源,获得了比MapReduce快3倍的速度。(PS:关于Hadoop生态系统,需要童鞋另行搜集相关资料,整个Hadoop生态对计算机发展有着非常重要的作用,它让众多企业的算力能力有了质的提升飞跃)
二、Spark和Hadoop的区别
首先我们需要厘清概念,Spaek对标的是Hadoop的MapReduce技术,因此该版块主要是比较Spark和MapReduce的区别。
- 表达能力 MapReduce中计算只能转换为map和reduce两个操作,但并不是所有的计算机操作都能用这两个操作来替代的,故而MapReduce的表达能力有限。Spark的计算模式相比而下就更加丰富,其不局限于map和reduce,还提供了多种数据集操作类型,编程模式比MapReduce更灵活,包括转换操作和动作操作等,这一块后面的章节会介绍。
- 磁盘开销大 MapReduce每次执行都会从磁盘中读取数据,计算完的结果和中间结果也会写入磁盘,这导致其磁盘开销巨大。而Spark将提供了内存计算,中间结果放在了内存中,提高了迭代效率。
- 延迟性 MapReduce多个任务之间的衔接涉及IO开销,而这会产生较高的延迟。而Spark各任务之间的衔接只会在内存中完成,降低了系统的延迟性。
- 执行机制 Spark基于DAG的任务调度执行机制,要优于MapReduce的迭代执行机制。
- 编写难度 MapReduce需要编写不少相对底层的代码,不够高效。相对而言,Spark提供了多种高层次、简洁的API,通常情况下,对于实现相同功能的应用程序,Spark的代码量要比Hadoop少2-5倍。更重要的是,Spark提供了实时交互式编程反馈,可以方便地验证、调整算法。
三、Spark生态
Spark的生态系统主要包含了Spark Core、Spark SQL、Spark Streaming、MLLib和GraphX 等组件,各个组件的具体功能如下:
- Spark Core:Spark Core包含Spark的基本功能,如内存计算、任务调度、部署模式、故障恢复、存储管理等。Spark建立在统一的抽象RDD之上,使其可以以基本一致的方式应对不同的大数据处理场景;通常所说的Apache Spark,就是指Spark Core;
- Spark SQL:Spark SQL允许开发人员直接处理RDD,同时也可查询Hive、HBase等外部数据源。Spark SQL的一个重要特点是其能够统一处理关系表和RDD,使得开发人员可以轻松地使用SQL命令进行查询,并进行更复杂的数据分析;(PS:将DB里面的内容读出转换为DataFrame进行操作)
- Spark Streaming:Spark Streaming支持高吞吐量、可容错处理的实时流数据处理,其核心思路是将流式计算分解成一系列短小的批处理作业。Spark Streaming支持多种数据输入源,如Kafka、Flume和TCP套接字等;(PS:注意Spark的实时流处理是小批次的处理作业,不是单条实时处理)
- MLlib(机器学习):MLlib提供了常用机器学习算法的实现,包括聚类、分类、回归、协同过滤等,降低了机器学习的门槛,开发人员只要具备一定的理论知识就能进行机器学习的工作;
- GraphX(图计算):GraphX是Spark中用于图计算的API,可认为是Pregel在Spark上的重写及优化,Graphx性能良好,拥有丰富的功能和运算符,能在海量数据上自如地运行复杂的图算法。(PS:未来知识图谱在各种计算场景已用中都会扮演极其重要的作用,因而图数据库的读写计算会非常普及的,而spark与图计算有很好的的连接)
四、Spark架构
(1)基本概念
- RDD:是弹性分布式数据集(Resilient Distributed Dataset)的简称,是分布式内存的一个抽象概念,提供了一种高度受限的共享内存模型;
- DAG:是Directed Acyclic Graph(有向无环图)的简称,反映RDD之间的依赖关系;
- Executor:是运行在工作节点(Worker Node)上的一个进程,负责运行任务,并为应用程序存储数据;
- 应用:用户编写的Spark应用程序;
- 作业:一个作业包含多个RDD及作用于相应RDD上的各种操作;
- 阶段:是作业的基本调度单位,一个作业会分为多组任务,每组任务被称为“阶段”,或者也被称为“任务集”。(一个作业会分为多个阶段,而每个阶段都会运行在相应的RDD上,当然这些RDD会被分配到各个Executor中)
- 任务:运行在Executor上的工作单元;
(2)架构设计
Spark运行架构包括集群资源管理器(Cluster Manager)、运行作业任务的工作节点(Worker Node)、每个应用的任务控制节点(Driver)和每个工作节点上负责具体任务的执行进程(Executor)。其中,集群资源管理器可以是Spark自带的资源管理器,也可以是YARN或Mesos等资源管理框架。
与Hadoop MapReduce计算框架相比,Spark所采用的Executor有两个优点:一是利用多线程来执行具体的任务(Hadoop MapReduce采用的是进程模型),减少任务的启动开销;二是Executor中有一个BlockManager存储模块,会将内存和磁盘共同作为存储设备,当需要多轮迭代计算时,可以将中间结果存储到这个存储模块里,下次需要时,就可以直接读该存储模块里的数据,而不需要读写到HDFS等文件系统里,因而有效减少了IO开销;或者在交互式查询场景下,预先将表缓存到该存储系统上,从而可以提高读写IO性能。
(3)概念间相互关系
在Spark中,一个应用(Application)由一个任务控制节点(Driver)和若干个作业(Job)构成,一个作业由多个阶段(Stage)构成,一个阶段由多个任务(Task)组成。当执行一个应用时,任务控制节点会向集群管理器(Cluster Manager)申请资源,启动Executor,并向Executor发送应用程序代码和文件,然后在Executor上执行任务,运行结束后,执行结果会返回给任务控制节点,或者写到HDFS或者其他数据库中。
(4)运行基本流程
- 当一个Spark应用被提交时,首先需要为这个应用构建起基本的运行环境,即由任务控制节点(Driver)创建一个SparkContext,由SparkContext负责和资源管理器(Cluster Manager)的通信以及进行资源的申请、任务的分配和监控等。SparkContext会向资源管理器注册并申请运行Executor的资源;
- 资源管理器为Executor分配资源,并启动Executor进程,Executor运行情况将随着“心跳”发送到资源管理器上;
- SparkContext根据RDD的依赖关系构建DAG图,DAG图提交给DAG调度器(DAGScheduler)进行解析,将DAG图分解成多个“阶段”(每个阶段都是一个任务集),并且计算出各个阶段之间的依赖关系,然后把一个个“任务集”提交给底层的任务调度器(TaskScheduler)进行处理;Executor向SparkContext申请任务,任务调度器将任务分发给Executor运行,同时,SparkContext将应用程序代码发放给Executor;
- 任务在Executor上运行,把执行结果反馈给任务调度器,然后反馈给DAG调度器,运行完毕后写入数据并释放所有资源。
总体而言,Spark运行架构具有以下特点:
- 每个应用都有自己专属的Executor进程,并且该进程在应用运行期间一直驻留。Executor进程以多线程的方式运行任务,减少了多进程任务频繁的启动开销,使得任务执行变得非常高效和可靠;
- Spark运行过程与资源管理器无关,只要能够获取Executor进程并保持通信即可;
- Executor上有一个BlockManager存储模块,类似于键值存储系统(把内存和磁盘共同作为存储设备),在处理迭代计算任务时,不需要把中间结果写入到HDFS等文件系统,而是直接放在这个存储系统上,后续有需要时就可以直接读取;在交互式查询场景下,也可以把表提前缓存到这个存储系统上,提高读写IO性能;
- 任务采用了数据本地性和推测执行等优化机制。数据本地性是尽量将计算移到数据所在的节点上进行,即“计算向数据靠拢”,因为移动计算比移动数据所占的网络资源要少得多。而且,Spark采用了延时调度机制,可以在更大的程度上实现执行过程优化。比如,拥有数据的节点当前正被其他的任务占用,那么,在这种情况下是否需要将数据移动到其他的空闲节点呢?答案是不一定。因为,如果经过预测发现当前节点结束当前任务的时间要比移动数据的时间还要少,那么,调度就会等待,直到当前节点可用。