Apache Hadoop 是最早开源并且最具影响力的大数据储存与处理框架。Hadoop 的前身是 Nutch 项目,Nutch 致力于开发一个开源的网络爬虫软件,或者说搜索引擎。Nutch 受 Google 发布的两篇论文的启发开发出了一个分布式文件系统和一个数据处理框架,最终这两部分都被纳入了 Hadoop 项目中,而 Nutch 继续它的网络爬虫的开发。

本文我们将结合 Hadoop 的发展历程了解 Hadoop 的组件及它们在整个项目中扮演的角色。

大数据系统

任何数据系统,都会有以下的必要流程:

  • 采集数据
  • 存储数据
  • 分析与处理数据
  • 展示分析和处理后的结果(表格、图表、图形)

当数据量比较小时,一台计算机就足以单独完成以上的所有工作,但是,当我们想要处理来着网络的大量数据时,一台计算机是远远不够的,这时候我们就需要组合多台计算机分布式地处理这些大量的数据。

2003 年,Google 发布了一篇论文 The Google File System,描述了如何使用软件存储并管理 Google 搜索引擎要处理的大量数据。紧接着,2004 年,Google 又发布了另一篇论文 MapReduce: Simplified Data Processing on Large Clusters,描述了如何使用 MapReduce 算法来简化大量集群里的数据处理。

而深受这两篇论文影响的 Hadoop 1.0 版本在 2007 正式发布,这是第一个大数据存储与处理的开源框架,这是基于 Java 的编程框架。第一代的 Hadoop 主要由两层构成:

  • HDFS:全名为 Hadoop Distributed File System(Hadoop 分布式文件系统),负责将数据存储在多台计算机上。
  • MapReduce:这是一个并行数据处理框架,它让每台计算机都能并行地执行同一个任务,除此之外,它还负责任务调度,任务状态监控以及出现错误时重启任务。

HDFS 1.0

Hadoop 分布式文件系统,HDFS 是 Hadoop 用来扩展数据的分布式存储层,它能够确保存储数据的高可用性。

HDFS 1.0 的工作原理

HDFS 使用数据块复制(block replication)在多台计算机上存储数据,其中有两个不同的软件协作完成这一操作:

  • NameNode 服务器,负责管理文件系统命名空间(namespace)和客户端访问请求。
  • DataNode,复杂响应读写请求,以及数据块的创建、删除和复制。

HDFS 会把每一个文件都保存成大小相同的序列数据块(最后一个数据块的大小不定)。默认情况下,每个数据块都会复制三次(即备份到三台不同的计算机上),但可以自行调整数据块的大小和复制次数。文件都是一次性写入到文件系统,并且保证每一个时刻只会有一个节点执行写入操作,这样可以提高数据吞吐量和简化数据一致化问题。

NameNode 服务器会接收集群里每一个 DataNode 发送的健康度报告,用来衡量各个 DataNode 的健康度,还会接收数据块报告,记录了每个 DataNode 上的所有数据块列表。

当新的数据块被创建时,HDFS 会把该数据块的第一个复制备份放在当前执行写入操作的节点(即写者)上。第二个复制备份会从其他节点里随机选择一个进行存储,第三个复制备份也会从剩下的节点里(不包括之前已保存数据块备份的两个节点)随机选择一个节点。

HDFS 1.0 的限制

HDFS 1.0 为 Hadoop 的早期成功立下了汗马功劳,这主要是因为 HDFS 1.0 的架构相对简单,移除了分布式存储的一些复杂特性,但这种放弃也带来了以下限制:

  • 无法控制数据块的分布。
    HDFS 的数据块复制是数据高复用性的核心,它使得集群管理人员和开发人员不需要再关注数据块级别的存储,但是它没有考虑空间利用率和节点的实时情况,集群管理人员需要使用一个均衡器实用程序(balancer utility program)来重新分配数据块。

  • NameNode 无法避免单点故障。
    如果进程或机器发生故障,整个集群都将不可用,直到 NameNode 服务器重新启动,甚至在重新启动时,它必须从集群的每个节点接收心跳消息(heartbeat messages),这将延长停机时间,特别是部署大型集群时。

    MapReduce 1.0

Hadoop 的第二层是 MapReduce,负责批处理存储在 HDFS 上的数据。Hadoop 实现了谷歌的 MapReduce 编程模型,哪怕开发人员没有使用并行和分布式系统的经验也可以使用 HDFS 提供的资源。

MapReduce 1.0 的工作原理

假设我们有一个文本集合,我们想知道每个单词在这个集合中出现的次数。这些文本数据分布在许多服务器上,因此在集合中具有数据块的集群中的所有节点上都要运行映射任务。每个 Mapper 会加载适当的文件,处理它们,并为每个出现的单词创建一个键值对。

这些映射只有来自单个节点的数据,所以它们必须被混排(shuffled)到一起,这样所有具有相同键名的值都可以被发送到一个化简器(reducer)。当化简器完成化简时,输出被写入到化简器所在的磁盘上。这种隐式通信模型使 Hadoop 用户不必显式地将信息从一台机器转移到另一台机器上。

我们可以用一个例子来说明,假设对下面两个句子执行 MapReduce:

要处理的句子
She sells seashells by six seashores.
She sure sells seashells well.
处理流程
映射 混排 化简
MAPPING SHUFFLING REDUCING
{she, 1} {she, 1, 1} {she, 2}
{sells, 1} {sells, 1, 1} {sells, 2}
{seashells, 1} {seashells, 1, 1} {seashells, 2}
{by, 1} {by, 1} {by, 1}
{six, 1} {six, 1} {six, 1}
{seashores, 1} {seashores, 1} {seashores, 1}
{she, 1} {sure, 1} {sure, 1}
{sure, 1} {well, 1} {well, 1}
{sells, 1}
{seashells, 1}
{well, 1}

如果数据集特别大的,执行上面的流程就会花费太多的时间,而如果并行执行映射,再化简,就可以加快整个任务的完成时间。

除此之外,Hadoop 还允许插入其他的组件或工具到 MapReduce 层中提供额外的功能。

Apache Pig 为开发人员提供了一种编写数据分析程序的语言,将 Java MapReduce 习语抽象到更高的级别,类似于 SQL 为关系数据库所做的工作。

Apache Hive 支持数据分析,并向 HDFS 提供类似sql的接口。它抽象了 MapReduce Java API查询,为开发人员提供高级查询功能。

Hadoop 1.x 还可以使用许多其他组件,但是 MapReduce 1.0 的限制还是制约了 Hadoop 生态系统的发展。

MapReduce 1 的限制

  • MapReduce 和 HDFS 之间紧密耦合。
    在 MapReduce 1.0 的实现中,MapReduce 层的职责扩展到数据处理之外,包括集群资源管理,并与 HDFS 紧密耦合。这意味着为 MapReduce 1 的开发扩展程序的开发人员必须编写多余的 MapReduce 程序代码,不管它是否适合执行任务。这都只是因为 MapReduce 是访问文件系统的唯一方法。
  • 数据分析只能执行静态任务。
    每个节点上执行映射和化简操作是处理大数据的关键,但在每个 DataNode 上只能执行有限的、静态的单用途的任务。映射任务只能执行映射操作,化简任务只能执行化简操作。而且只能在配置文件里设置运行任务的数量,却不能动态调度。这样的话,当某些任务空闲时就只会浪费集群的工作负载(workload)。这种静态配置,也让其他非 MapReduce 的程序来进行调度变得不可能。

  • JobTracker 也有单点故障的问题。
    Hadoop 应用程序会将 MapReduce 任务提交给 JobTracker,而 JobTracker 则将这些任务分配给特定的集群节点。JobTracker 会定位一个具有可分配任务槽的 TaskTracker ,或者就在数据附近的 TaskTracker。如果任务执行失败,TaskTracker 会通知 JobTracker。JobTracker 可能会重新提交作业,标记该 TaskTracker 为将来不执行,或者可能将一个不可靠的 TaskTracker 加入黑名单,但由于只要 JobTracker 出现了错误,所有 MapReduce 任务都会被停止。

Hadoop 2.x 的改进

2011 年 9 月份,Hadoop 2.x 版本发布了,引入了四个主要的改进,并且允许其他非 MapReduce 的处理模型直接和 HDFS 交互,可集成各种各样的插件。

  • HDFS 联邦(Federation),解决了 NameNode 的性能问题和单点故障问题。
  • NameNode 的主动/被动配置,提高了 NameNode 的可用性,提供快速故障恢复。
  • YARN(Yet Another Resource Negotiator),解耦了 MapReduce 和 HDFS,单独负责资源管理。
  • 激活/备用架构(Active/Standby architecture),解决了资源管理器的单点故障问题。

HDFS 联邦/联合

HDFS 联合引入了名称空间和存储之间的明确分离,使集群中的具有多个名称空间成为可能。这提供了一些关键的改进:

  • 命名空间可扩展
    允许添加更多的 NameNode 到集群中实现水平扩展。

  • 性能提升
    Hadoop 1.x 的单 NameNode 模式限制了文件系统的读写吞吐量,而多个 NameNode 模式则减轻了对文件系统操作的限制。

  • 命名空间相互独立
    在具有单个 NameNode 的多租户环境中,一个用户的不良操作可能会影响系统中的其他用户。但有了联邦,就有可以隔离不同用户。目前的云计算服务都会将一个节点租赁给多个用户使用。

HDFS 联邦的工作原理

联合起来的 NameNodes 管理文件系统命名空间。它们各自独立运作,互不协调。相反,集群中的 DataNodes 在每个 NameNode 服务器上都会进行注册,发送心跳和阻塞报告,并处理 NameNode 服务器发送的命令。

在 Hadoop 1.x 中我们已经了解了数据块的随机复制特性。所有的属于同一个命名空间的数据块合称数据块池。这些数据块池都是独立管理的,允许一个命名空间在不与其他命名空间协调的情况下为新块生成数据块ID。命名空间和它的块池的组合称为命名空间卷(Namespace Volume),它形成一个自包含(self-contained)的单元,这样当一个联邦 NameNodes 被删除时,它的块池也会被删除。

NameNode 高可用性

在 Hadoop 2.0 之前,如果 NameNode 失败,那么整个集群都是不可用的,直到重新启动或在新机器上启动。升级到 NameNode 的软件或硬件,同样也创建了宕机窗口。为了防止这种情况发生,Hadoop 2.0 实现了一个主动/被动配置,以允许快速故障转移。

工作原理

两个独立的机器都配置了 NameNodes 服务器,一个是活动的,另一个是备用的。它们共享共享存储设备上的公共目录,当活动节点执行修改时,它会将修改操作记录在该公共目录中的日志文件中。备用节点不断地监视目录,当编辑发生时,它将这些编辑应用到它自己的名称空间中。如果活动节点失败,备用节点将从共享存储中读取未应用的修改,然后转换成活动节点。

YARN

Hadoop 2.0 将 MapReduce 与 HDFS 分离。工作负载、多租户、安全控制和高可用性特性的管理被分离成 YARN (Yet Another Resource Negotiator,另一个资源协商者)。在本质上,YARN 是一种大型数据应用程序的大规模分布式操作系统,它使得 Hadoop 不仅仅只能执行 MapReduce 批处理计算模型,也支持其他数据处理计算模型。YARN 移除了只能使用 I/O 密集的、高延迟 MapReduce 框架进行数据处理的限制,使新的处理模型能够与 HDFS 一起使用。分离后的 MapReduce 仍然是一个很有用的框架,专门用于执行它擅长的任务——批处理

下面是 Hadoop 2.x 用户可用的一些处理模型:

  • 批处理
    批处理系统是非交互式的,在处理开始之前,可以访问所有数据。此外,在处理过程中要解决的问题必须在处理开始之前就安排好。批处理通常是高延迟,大数据批作业的速度通常在几分钟或更长时间内测量。
    批处理的应用场景:索引数据,网络爬虫,数据分析
    Hadoop 支持的程序:MapReduce、Tez、Spark、Hive 和 Flink

  • 交互式处理
    当你不清楚输入数据时,就需要用户交互式地输入数据,一般来说,响应速度要求比批处理要快。
    交互式处理的应用场景:数据开发(data exploration)
    Hadoop 支持的程序:Impala、Drill、HAWQ、Presto、Vortex、Vertica SQL 和 Tez

  • 流处理
    流处理系统接收大量离散的数据点,在新数据到达系统的同时执行连续查询,以产生接近实时的结果。
    流处理的的应用场景:社交媒体监控,系统日志监控
    Hadoop 支持的程序:Spark Stream 和 Storm

  • 图处理
    图形算法通常需要在顶点(vertices )或跃点(hops)之间进行通信,以便将边缘(edge)从一个顶点移动到另一个顶点,当你使用 MapReduce 1.x 进行处理时,往往需要大量不必要的开销。
    图处理的应用场景:社交媒体的社交关系追踪
    Hadoop 支持的程序:Apache Giraph 和 Apache Spark’s GraphX、Hama 和 Titan

这里只列举了一些可用的处理模型和工具,你可以在这里查看完整的清单。

资源管理高可用性

YARN 刚开始发布时也存在瓶颈——资源管理器的单点故障问题。MapReduce 1.x 使用唯一的 JobTracke 来处理资源管理、作业调度和作业监控。YARN 早期将这些任务分成了全局的资源管理器(ResourceManage)和每个应用程序特定的应用管理器(ApplicationMaster),从而改善了原来的问题。ResourceManager 跟踪了集群资源和调度应用程序,例如 MapReduce 作业。但直到 Hadoop 2.4 引入主从架构( Active/Standby architecture)之前,单点故障的问题都没有得到解决。

在 Hadoop 2.4 中,单个资源管理器可以被一个主资源管理器和一个或多个从资源管理器取代。在主资源管理器发生故障的情况下,管理员可以手动切换到从资源管理器。它们还可以通过将 Apache Zookeeper 添加到技术栈来启用自动故障转移。在 Zookeeper 的其他任务协调职责中,它可以跟踪 YARN 节点的状态,在发生故障时自动切换到从资源管理器。

Hadoop 3.x

在撰写本文时,Hadoop 3.0-alpha1 可用于测试。Hadoop 3.0 目标是提供一些改进工作,例如 HDFS 擦除编码,以节省磁盘空间,改进纱线的时间轴服务,以提高其可伸缩性、可靠性和可用性,支持两个以上的 NameNodes 和内部 DataNode 的均衡器等。要了解更多,请参阅官网说明。

参考阅读

Melissa Anderson,An Introduction to Hadoop