早在 Hadoop1.x 版本,当时采用的是 MRv1 版本的 MapReduce 编程模型。MRv1 版本的实现 都封装在 org.apache.hadoop.mapred 包中,MRv1 的 Map 和 Reduce 是通过接口实现的。MRv1 包括三个部分: 运行时环境(JobTracker 和 TaskTracker) 编程模型(MapReduce) 数据处理引擎(MapTask 和 ReduceTask)
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 和 ReduceTask 使用。有时会因为作业刚刚启动等原因导致 MapTask 很多,而 Reduce Task 任 务还没有调度的情况,这时 Reduce slot 也会被闲置。
不能支持多种 MapReduce 框架:无法通过可插拔方式将自身的 MapReduce 框架替换为其 他实现,如 Spark、Storm 等。
Apache 为了解决 MRv1 中的缺陷,对 Hadoop 进行了升级改造。MRv2 就诞生了。
MRv2 中,重用了 MRv1 中的编程模型和数据处理引擎。但是运行时环境被重构了。JobTracker 被拆分成了通用的 资源调度平台(ResourceManager,简称 RM)、 节点管理器(NodeManager)、 负责各个计算框架的任务调度模型(ApplicationMaster,简称 AM)。
Stay hungry Stay foolish --马中华-- http://blog.csdn.net/zhongqi2513
ResourceManager 依然负责对整个集群的资源管理,但是在任务资源的调度方面只负责将资 源封装为 Container 分配给 ApplicationMaster 的一级调度,二级调度的细节将交给 ApplicationMaster 去完成,这大大减轻了 ResourceManager 的压力,使得 ResourceManager 更加轻量。NodeManager 负责对单个节点的资源管理,并将资源信息、Container 运行状态、 健康状况等信息上报给 ResourceManager。ResourceManager 为了保证 Container 的利用率, 会监控 Container,如果 Container 未在有限的时间内使用,ResourceManager 将命令 NodeManager杀死Container,以便于将资源分配给其他任务。MRv2的核心不再是MapReduce 框架,而是 YARN。在以 YARN 为核心的 MRv2 中,MapReduce 框架是可插拔的,完全可以替 换为其他分布式计算模型实现,比如 Spark、Storm 等。
Hadoop MRv2 虽然解决了 MRv1 中的一些问题,但是由于对 HDFS 的频繁操作(包括计算结 果持久化、数据备份、资源下载及 Shuffle 等)导致磁盘 I/O 成为系统性能的瓶颈,因此只 适用于离线数据处理或批处理,而不能支持对迭代式、交互式、流式数据的处理。
重点概念: 离线处理,批处理,实时处理,流式处理
Spark 看到 MRv2 的问题,对 MapReduce 做了大量优化,总结如下:
减少磁盘 I/O: 随着实时大数据应用越来越多,Hadoop 作为离线的高吞吐、低响应框架已不 能满足这类需求。Hadoop MapReduce 的 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 和排序:Hadoop MapReduce 在 Shuffle 之前有着固定的排序操作(只能对 key 排字典顺序),而 Spark 则可以根据不同场景选择在 map 端排序或者 reduce 端排序。
灵活的内存管理策略 Spark 将内存分为堆上的存储内存、堆外的存储内存、堆上的执行内 存、堆外的执行内存 4 个部分。Spark 既提供了执行内存和存储内存之间是固定边界的实现, 又提供了执行内存和存储内存之间是“软”边界的实现。Spark 默认使用“软”边界的实现, 执行内存或存储内存中的任意一方在资源不足时都可以借用另一方的内存,最大限度的提高 资源的利用率,减少对资源的浪费。Spark 由于对内存使用的偏好,内存资源的多寡和使用 率就显得尤为重要,为此 Spark 的内存管理器提供的 Tungsten 实现了一种与操作系统的内存 Page 非常相似的数据结构,用于直接操作操作系统内存,节省了创建的 Java 对象在堆中占 用的内存,使得 Spark 对内存的使用效率更加接近硬件。Spark 会给每个 Task 分配一个配套 的任务内存管理器,对 Task 粒度的内存进行管理。Task 的内存可以被多个内部的消费者消 费,任务内存管理器对每个消费者进行 Task 内存的分配与管理,因此 Spark 对内存有着更细 粒度的管理。
基于以上所列举的优化,Spark 官网声称性能比 Hadoop 快 100 倍。即便是内存不足需要磁 盘 I/O 时,其速度也是 Hadoop 的 10 倍以上。
Spark 会取代 Hadoop 么? Spark 是 MapReduce 的替代方案,而且兼容 HDFS、Hive,可融入 Hadoop 的生态系统,以 弥补 MapReduce 的不足。