Spark 是一个通用的并行计算框架,由加州伯克利大学(UC Berkeley)的 AMP 实验室开发于 2009 年,并于 2010 年开源,2013 年成长为 Apache 旗下在大数据领域最活跃的开源项目之一。
Spark 目前已经走过了 0.x 和 1.x 两个时代,现在正在 2.x 时代稳步发展。
Spark 也是基于 map reduce 算法模型实现的分布式计算框架,拥有 Hadoop MapReduce 所具有的优点,并且解决了 Hadoop MapReduce 中的诸多缺陷。
Hadoop MRv1 的局限
早在 Hadoop 1.0 版本,当时采用的是 MRv1 版本的 MapReduce 编程模型。MRv1 版本的实现都封装在 org.apache.hadoop.mapred 包中,MRv1 的 Map 和 Reduce 是通过接口实现的。MRv1 包括以下三个部分。
- 运行时环境(JobTracker 和 TaskTracker)。
- 编程模型(MapReduce)。
数据处理引擎(Map 任务和 Hadoop MRv2 虽然解决了 MRv1 中的一些问题,但是由于对 HDFS 的频繁操作(包括计算结果持久化、数据备份、资源下载及 Shuffle 等),导致磁盘 I/O 成为系统性能的瓶颈,因此只适用于离线数据处理或批处理,而不能支持对迭代式、流式数据的处理。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 等。
![](https://i-blog.csdnimg.cn/blog_migrate/df163f3bd377afaeac3b575910ca2c3b.png)
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 的核心不再是 MapReduce 框架,而是 YARN。在以 YARN 为核心的 MRv2 中,MapReduce 框架是可插拔的,完全可以替换为其他 MapReduce 实现,比如 Spark、Storm 等。
![](https://i-blog.csdnimg.cn/blog_migrate/5f65536901fe9531168f6550a8f80edc.png)
Spark 的特点
减少磁盘 I/O
随着实时大数据应用越来越多,Hadoop 作为离线的高吞吐、低响应框架已不能满足这类需求。Hadoop MapReduce 的 map 端将中间输出和结果存储在磁盘中,reduce 端又需要从磁盘读写中间结果,势必造成磁盘 I/O 成为瓶颈。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 排序
Hadoop MapReduce 在 Shuffle 之前有着固定的排序操作,而 Spark 则可以根据不同场景选择在 map 端排序还是 reduce 端排序。
灵活的内存管理策略
Spark 将内存分为堆上的存储内存、堆外的存储内存、堆上的执行内存、堆外的执行内存 4 个部分。Spark 既提供了执行内存和存储内存之间固定边界的实现,又提供了执行内存和存储内存之间「软」边界的实现。Spark 默认使用「软」边界的实现,执行内存或存储内存中的任意一方在资源不足时都可以借用另一方的内存,最大限度地提高资源的利用率,减少对资源的浪费。Spark 由于对内存使用的偏好,内存资源的多寡和使用率就显得尤为重要,为此 Spark 的内存管理器提供的 Tungsten 实现了一种与操作系统的内存 Page 非常相似的数据结构,用于直接操作操作系统内存,节省了创建的 Java 对象在堆中占用的内存,使得 Spark 对内存的使用效率更加接近硬件。Spark 会给每个 Task 分配一个配套的任务内存管理器,对 Task 粒度的内存进行管理。Task 的内存可以被多个内部的消费者消费,任务内存管理器对每个消费者进行 Task 内存的分配与管理,因此 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 依赖 Spark Streaming 对数据进行实时的处理,其流式处理能力还要强于 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 与其他数据处理平台的对接。