hadoop学习笔记


首先先介绍下Hadoop,来自维基百科:

Apache Hadoop是一款支持数据密集型分布式应用程序并以Apache 2.0许可协议发布的开源软件框架。它支持在商品硬件构建的大型集群上运行的应用程序。Hadoop是根据谷歌公司发表的MapReduce和Google文件系统的论文自行实现而成。所有的Hadoop模块都有一个基本假设,即硬件故障是常见情况,应该由框架自动处理。 Hadoop框架透明地为应用提供可靠性和数据移动。它实现了名为MapReduce的编程范式:应用程序被分区成许多小部分,而每个部分都能在集群中的任意节点上运行或重新运行。此外,Hadoop还提供了分布式文件系统,用以存储所有计算节点的数据,这为整个集群带来了非常高的带宽。MapReduce和分布式文件系统的设计,使得整个框架能够自动处理节点故障。它使应用程序与成千上万的独立计算的电脑和PB级的数据。现在普遍认为整个Apache Hadoop“平台”包括Hadoop内核、MapReduce、Hadoop分布式文件系统(HDFS)以及一些相关项目,有Apache Hive和Apache HBase等等。

Hadoop框架中最核心的设计就是:MapReduce和HDFS。MapReduce的思想是由Google的一篇论文所提及而被广为流传的,简单的一句话解释MapReduce就是“任务的分解与结果的汇总”。HDFS是Hadoop分布式文件系统(Hadoop Distributed File System)的缩写,为分布式计算存储提供了底层支持。下面来分别介绍下:

HDFS

HDFS基于一组特定的节点构建,包括名称节点(Name Node),第二名称节点(Second NameNode)以及数据节点(Data Node)。

  • 名称节点(Name Node)又称Master Node,主节点 通常在HDFS架构中单独机器上运行的组建,负责管理文件系统名称空间和控制外部客户机的访问,Name Node决定是否将文件映射到Data Node上的复制块上。
  • 数据节点(Data Node),又称slave Node。 数据节点也是一个通常在HDFS架构中单独机器上运行的组建,一般包括一个Name Node和大量的Data Node。 数据节点响应来自HDFS客户机的读写请求,还响应来自Name Node的创建,删除和复制块的命令。 名称节点依赖来自每个数据节点的定期心跳消息,每条消息都包括一个块报告,名称节点可以根据报告验证块映射和其他文件系统元数据。

HDFS系统的文件特征:

  • 存储极大数目的信息(terabytes or petabytes),将数据保存到大量的节点当中。支持很大单个文件。
  • 提供数据的高可靠性,单个或者多个节点不工作,对系统不会造成任何影响,数据仍然可用。
  • 提供对这些信息的快速访问,并提供可扩展的方式。能够通过简单加入更多服务器的方式就能够服务更多的客户端。
  • HDFS是针对MapReduce设计的,使得数据尽可能根据其本地局部性进行访问与计算。 与普通文件系统相比,其差异如下:
  • 文件量相对不大,不过单文件会比较大。
  • 文件中间内容不能修改,只能添加内容到文件结尾。
  • 只能对文件进行创建,删除,重命名,修改属性以及在文件尾部添加等操作。

HDFS文件操作主要流程:

  1. 客户端将要上传对文件按照128M的大小分块。
  2. 客户端向名称节点发送写数据请求。
  3. 名称节点记录各个Data Node信息,并返回可用的Data Node节点列表。
  4. 客户端直接向Data Node发送分割后的文件,以流的方式写入。
  5. 写入完成后,Data Node向Name Node发送消息,更新元数据。

在向每个Data Node写数据的时候,该Data Node会将文件副本数据发送给别的Data Node,这样就完成了备份存储。 在分布式文件系统的设计中,挑战之一是如何确保数据的一致性。对于HDFS来说,直到所有要保存数据的DataNodes确认它们都有文件的副本时,数据才被认为写入完成。因此,数据一致性是在写的阶段完成的。一个客户端无论选择从哪个DataNode读取,都将得到相同的数据。

HDFS文件读过程:

  1. 客户端询问NameNode它应该从哪里读取文件。
  2. NameNode发送数据块的信息给客户端。(数据块信息包含了保存着文件副本的DataNode的IP地址,以及DataNode在本地硬盘查找数据块所需要的数据块ID。)
  3. 客户端检查数据块信息,联系相关的DataNode,请求数据块。
  4. DataNode返回文件内容给客户端,然后关闭连接,完成读操作。 客户端并行从不同的DataNode中获取一个文件的数据块,然后联结这些数据块,拼成完整的文件。

在HDFS中,文件被切分成固定大小的数据块,默认128M,若文件不及128M则单独保存在一个block。文件在切分成若干个block后,存储在不同节点上,默认情况下每个block都有三个副本。

MapReduce

MapReduce的主要思想即:将一个大问题分割成多个小问题,处理完成之后在将数据汇总,在MapReduce中,尽量将数据存储在计算节点,这样访问本地数据会快很多,而就近存储数据也是MapReduce的一大特征。

主要步骤:

  1. Map所做的是将一个问题域中的所有数据在一个或多个节点中转化为Key-Value对,然后对这些Key-Value对进行Map操作,生成零个或多个新的Key-Value对,最后按key值进行排序,同样的Key值排在一起,合并生成一个新的Key-Value列表。
  2. Reduce做的是收集工作,按照Map中生成新的Key-Value列表按照key值放在一个或者多个子节点中,用便携的Reduce操作处理,归并合成一个列表,得到最终的结果。 其主要流程如下所示:

    (input) <k1, v1> -> map -> <k2, v2> -> combine -> <k2, v2> -> reduce -> <k3, v3> (output)

如下图所示,使用MapReduce来统计词频: MapReduce

  1. 用户程序调用MapReduce将输入文件分割成若干个小文件,假设我们的输入为{“Dear”,”Bear”,”River”,”Car”,”Car”,”River”,”Dear”,”Car”,”Bear”},则按规则每三个单词一个小文件可以把输入分割成三个小文件,分别是:{“Dear”,”Bear”,”River”},{“Car”,”Car”,”River”}和{“Dear”,”Car”,”Bear”}
  2. 在map阶段创建key-value列表,key是每个单词,而value我们都初始化为1,这样,对于第一行(Deer Bear River)我们就得到了三个键值对,分别是Dear,1;Bear,1;River,1。对于其他节点进行同样对操作,这个阶段对处理逻辑其实就是我们程序所编写的Map函数。而这个阶段的操作都是数据本地的操作,也就是所谓的移动计算而不是移动数据。
  3. Shuffing阶段,MapReduce的核心就是在这个阶段,其原理就是将Map的输出进行整合,然后作为Reduce的输入发送给Reduce,简单理解就是把所有的Map的输出按照键进行排序,并且将相对键的键值对整合在同一个组中,Bear、Car、Deer、River是排序的,并且Bear这个键有两个键值对。
  4. Reduce阶段,这个阶段也是我们编写程序的地方,可以针对分组后的键值对进行处理,针对同一个键Bear的所有值进行了一个加法操作,得到这样的键值对。
  5. 输出阶段,Reduce的输出结果是直接写入HDFS上,同样这个输出文件也是分块的。

MapReduce的过程可以解析为如下所示:

  1. 文件在HDFS上被分块存储,DataNode存储文件的实际块。
  2. 在Map阶段,针对每个文件块建立一个Map任务,Map任务直接在Data Node上进行,即移动计算,而非数据。
  3. 每个Map任务处理自己的文件块,然后输出新的键值对。
  4. Map输出的键值对经过Shuffle/Sort阶段后,相同的key的记录会被输送到同一个Reducer中,同事键值对排序的值被放在一个列表中。
  5. 每个Reducer处理从Map输送过来的键值对,然后输出新的键值对,一般输出在HDFS上。

所以MapReduce的本质就是把一组键值对经过Map阶段映射成新的键值对;接着经过Shuffle/Sort阶段进行排序和“洗牌”,把键值对排序,同时把相同的键的值整合;最后经过Reduce阶段,把整合后的键值对组进行逻辑处理,输出到新的键值对。这样的一个过程,其实就是MapReduce的本质。