设计理念
HDFS专为存储大文件而设计,通常以集群模型运行于普通的商业服务器上,基于流式数据访问模型完成数据存取。HDFS将所有文件的元数据存储于名称节点(NameNode)的内存中,能够利用分布式特性高效地管理“大”文件(GB级别甚至更大的文件),对于有着海量小文件的应用场景则会给名称节点的内存空间带去巨大压力并使得其很可能成为系统性能瓶颈。再者,HDFS为MapReduce的计算框架而设计,存储下来数据主要用于后续的处理分析,其访问模型为“一次写入、多次读取”;因此,数据在HDFS中存储完成后,仅能在文件尾部附加新数据,而不能对文件进行修改。另外,HDFS专为了高效地传输大文件进行了优化,其为了完成此目标,在“低延迟”特性上做出了很大让步,因此,其不适用于较小访问延迟的应用。
HDFS是工作于用户空间的文件系统,它的树状文件系统是独立的,不能像传统上工作于内核空间的文件系统一样挂载至当前操作系统的目录树上对HDFS进行访问,传统上实现文件或目录管理的命令如ls、cat等此处也无法正常使用。
名称节点(NameNode)和数据节点(DataNode)
名称节点负责管理HDFS的名称空间,即以树状结构组织的目录及文件的元数据信息,这些信息持久存储于名称节点本地磁盘上并保存为名称“空间镜像(namespace image)”和“编辑日志(edit log)”两个文件。名称节点并不存储数据块,它仅需要知道每个文件对应数据块的存储位置,即真正存储了数据块的数据节点。然而,名称节点并不会持久存储数据块所与其存储位置的对应信息,因为这些信息是在HDFS集群启动由名称节点根据各数据节点发来的信息进行重建而来。
数据节点的主要任务包括根据名称节点或客户的要求完成存储或读取数据块,并周期性地将其保存的数据块相关信息报告给名称节点。
默认情况下,HDFS会在集群中为每个数据块存储三个副本以确保数据的可靠性、可用性及性能表现。在一个大规模集群中,这三个副本一般会保存至不同机架中的数据节点上以应付两种常见的故障:单数据节点故障和导致某机架上的所有主机离线的网络故障。另外,如前面MapReduce运行模型中所述,为数据块保存多个副本也有利于MapReduce在作业执行过程中透明地处理节点故障等,并为MapReduce中作业协同处理以提升性能提供了现实支撑。名称节点会根据数据节点的周期性报告来检查每个数据块的副本数是否符合要求,低于配置个数要求的将会对其进行补足,而多出的将会被丢弃
访问HDFS文件系统
HDFS用户接口:
1.hadoop dfs命令行接口;
2.hadoop dfsadmin命令行接口;
3.web接口;
4.HDFS API;
写数据
当需要存储文件并写数据时,客户端程序首先会向名称节点发起名称空间更新请求,名称节点检查用户的访问权限及文件是否已经存在,如果没有问题,名称空间会挑选一个合适的数据节点分配一个空闲数据块给客户端程序。客户端程序直接将要存储的数据发往对应的数据节点,在完成存储后,数据节点将根据名称节点的指示将数据块复制多个副本至其它节点。
1. 向HDFS集群中保存数据之前,HDFS客户端需要事先知悉目标文件系统使用的“块大小”以及“复制因子(Replication Factor,即每一个块需要保存的副本数目)”。在提交数据至HDFS之前,HDFS客户端需要将要保存的文件按块大小进行分割,并将其逐个向名称节点发起块存储请求,此时,根据复制因子,客户端会要求名称节点给出与复制因子相同个数的空闲块,这里假设为3个;
2. 名称节点需要从找出至少3个具有可用空闲块的数据节点(同复制因子),并将这3个节点的地址以距客户端的距离由近及远的次序响应给客户端;
3. 客户端仅向最近的数据节点(假设为DN1)发起数据存储请求;当此最近的数据节点存储完成后,其会将数据块复制到剩余的数据节点中的一个(假设为DN2),传输完成后,由DN2负责将数据块再同步至最后一个数据节点(假设为DN3);这个也称为“复制管道(replication pipeline);
4. 当三个数据节点均存储完成后,它们会将“存储完成(DONE)”的信息分别通知给名称节点;而后,名称节点会通知客户端存储完成;
5. 客户端以此种方式存储剩余的所有数据块,并在全部数据块存储完成后通知名称节点关闭此文件,名称节点接着会将此文件的元数据信息存储至持久存储中;
读数据
HDFS提供了POSIX风络的访问接口,所有的数据操作对客户端程序都是透明的。当客户端程序需要访问HDFS中的数据时,它首先基于TCP/IP协议与名称节点监听的TCP端口建立连接,接着通过客户端协议(Client Protocol)发起读取文件的请求,而后名称节点根据用户请求返回相关文件的块标识符(blockid)及存储了此数据块的数据节点。接下来客户端向对应的数据节点监听的端口发起请求并取回所需要数据块。
1. 客户端向名称节点请求访问某文件;
2. 名称节点向客户端响应两个列表:(a)此文件包含的所有数据块,(b)此文件的每个数据块所在的数据节点列表;
3. 客户端将每一个数据块从存储列表中最近的数据节点读取,而后在本地完成合并;
名称节点的可靠性
名称节点的宕机将会导致HDFS文件系统中的所有数据变为不可用,而如果名称节点上的名称空间镜像文件或编辑日志文件损坏的话,整个HDFS甚至将无从重建,所有数据都会丢失。因此,出于数据可用性、可靠性等目的,必须提供额外的机制以确保此类故障不会发生,Hadoop为此提供了两种解决方案。
最简单的方式是将名称节点上的持久元数据信息实时存储多个副本于不同的存储设备中。Hadoop的名称节点可以通过属性配置使用多个不同的名称空间存储设备,而名称节点对多个设备的写入操作是同步的。当名称节点故障时,可在一台新的物理主机上加载一份可用的名称空间镜像副本和编辑日志副本完成名称空间的重建。然而,根据编辑日志的大小及集群规模,这个重建过程可能需要很长时间。
另一种方式是提供第二名称节点(Secondary NameNode)。第二名称节点并不真正扮演名称节点角色,它的主要任务是周期性地将编辑日志合并至名称空间镜像文件中以免编辑日志变得过大。它运行在一个独立的物理主机上,并需要跟名称节点同样大的内存资源来完成文件合并。另外,它还保存一份名称空间镜像的副本。然而,根据其工作机制可知,第二名称节点要滞后于主节点,因此名称节点故障时,部分数据丢失仍然不可避免。
Hadoop 0.23引入了名称节点的高可用机制——设置两个名称节点工作于“主备”模型,主节点故障时,其所有服务将立即转移至备用节点。在大规模的HDFS集群中,为了避免名称节点成为系统瓶颈,在Hadoop 0.23版本中引入了HDFS联邦(HDFS Federation)机制。HDFS联邦中,每个名称节点管理一个由名称空间元数据和包含了所有块相关信息的块池组成名称空间卷(namespace volume),各名称节点上的名称空间卷是互相隔离的,因此,一个名称节点的损坏并不影响其它名称节点继续提供服务。
在HDFS集群中,各数据节点周期性地(每3秒钟)向名称节点发送心跳信息(HEARTBEAT)以通告其“健康”状况;相应地,名称节点如果在10分钟内没有收到某数据节点的心跳信息,则认为其产生了故障并将其从可用数据节点列表中移除,无论此故障产生的原因是节点自身还是网络问题。
客户端与数据节点之间的数据传输基于TCP协议进行,客户端每发送一个报文给数据节点,数据节点均会返回一个响应报文给客户端;因此,如果客户端重试数次后仍未能正常接收到来自数据节点的响应报文,其将放弃此数据节点转而使用名称节点提供的列表中的第二个数据节点。
网络传输中的噪声等都有可能导致数据讹误,为了避免数据节点存储错误的数据,客户端发送数据至数据节点时会一并传送此数据的校验和,而数据节点会连同数据一起存储此校验和。HDFS集群中,数据节点周期性地每将自己持有的所有数据块信息报告给名称节点,但在发送每个数据块的相关信息之前,其会根据校验和检验此数据块是否出现了讹误,如果检验出错,数据节点将不再向名称节点通告自己持有此数据块,名称节点从而可以得知此数据节点有数据块损坏。
MapReduce
MapReduce是一个编程框架,它为程序员提供了一种快速开发海量数据处理程序的编程环境,并能够让基于这种机制开发出的处理程序以稳定、容错的方式并行运行于由大量商用硬件组成的集群上。同时,MapReduce又是一个运行框架,它需要为基于MapReduce机制开发出的程序提供一个运行环境,并透明管理运行中的各个细节。每一个需要由MapReduce运行框架运行的MapReduce程序也称为一个MapReduce作业(mapreduce job),它需要由客户端提交,由集群中的某专门节点负责接收此作业,并根据集群配置及待处理的作业属性等为其提供合适的运行环境。其运行过程分为两个阶段:map阶段和reduce阶段,每个阶段都根据作业本身的属性、集群中的资源可用性及用户的配置等启动一定数量的任务(也即进程)负责具体的数据处理操作。
在MapReduce集群中,负责接收客户端提交的作业的主机称作master节点,此节点上具体负责接收作业的进程称作JobTracker。负责运行map任务或reduce任务的节点称作slave节点,其运行的作业处理进程为TaskTracker。默认情况下,一个slave节点可同时运行两个map任务和两个reduce任务。
MapReduce逻辑架构
MapReduce运行框架
MapReduce程序也称作为MapReduce作业,一般由mapper代码、reducer代码以及其配置参数(如从哪儿读入数据,以及输出数据的保存位置)组成。准备好的作业可通过JobTracker(作业提交节点)进行提交,然后由运行框架负责完成后续的其它任务。这些后续任务主要包括如下几个方面。
1. 调度
每个MapReduce作业都会划分为多个称作任务(task)的较小单元,而较大的作业划分的任务数量也可能会超出整个集群可运行的任务数,此时就需要调度器程序维护一个任务队列并能够追踪正在运行态任务的相关进程,以便让队列中处于等待状态的任务派送至某转为可用状态的节点运行。此外,调度器还要负责分属于不同作业的任务协调工作。
对于一个运行中的作业来说,只有所用的map任务都完成以后才能将中间数据分组、排序后发往reduce作业,因此,map阶段的完成时间取决于其最慢的一个作业的完成时间。类似的,reduce阶段的最后一个任务执行结束,其最终结果才为可用。因此,MapReduce作业完成速度则由两个阶段各自任务中的掉队者决定,最坏的情况下,这可能会导致作业长时间得不到完成。出于优化执行的角度,Hadoop和Google MapReduce实现了推测执行(Speculative execution)机制,即同一个任务会在不同的主机上启动多个执行副本,运行框架从其最快执行的任务中取得返回结果。不过,推测执行并不能消除其它的滞后场景,比如中间键值对数据的分发速度等。
2. 数据和代码的协同工作(data/code co-location)
术语“数据分布”可能会带来误导,因为MapReduce尽力保证的机制是将要执行的代码送至数据所在的节点执行,因为代码的数据量通常要远小于要处理的数据本身。当然,MapReduce并不能消除数据传送,比如在某任务要处理的数据所在的节点已经启动很多任务时,此任务将不得不在其它可用节点运行。此时,考虑到同一个机架内的服务器有着较充裕的网络带宽,一个较优选择是从数据节点同一个机架内挑选一个节点来执行此任务。
3. 同步(Synchronization)
异步环境下的一组并发进程因直接制约而互相发送消息而进行互相合作、互相等待,使得各进程按一定的速度执行的过程称为进程间同步,其可分为进程同步(或者线程同步)和数据同步。就编程方法来说,保持进程间同步的主要方法有内存屏障(Memory barrier),互斥锁(Mutex),信号量(Semaphore)和锁(Lock),管程(Monitor),消息(Message),管道(Pipe)等。MapReduce是通过在map阶段的进程与reduce阶段的进程之间实施隔离来完成进程同步的,即map阶段的所有任务都完成后对其产生的中间键值对根据键完成分组、排序后通过网络发往各reducer方可开始reduce阶段的任务,因此这个过程也称为shuffle and sort。
4. 错误和故障处理(Error and fault handling)
MapReduce运行框架本身就是设计用来容易发生故障的商用服务器上了,因此,其必须有着良好的容错能力。在任何类别的硬件故障发生时,MapReduce运行框架均可自行将运行在相关节点的任务在一个新挑选出的节点上重新启动。同样,在任何程序发生故障时,运行框架也要能够捕获异常、记录异常并自动完成从异常中恢复。另外,在一个较大规模的集群中,其它任何超出程序员理解能力的故障发生时,MapReduce运行框架也要能够安全挺过。
Hadoop集群
Hadoop的核心组件为MapReduce和HDFS,HDFS提供大数据的存储能力,而MapReduce则为程序员开发处理大数据的程序提供了一个开发和运行环境.
在调度运行一个作业时,将map任务等直接运行于要处理的数据所存储的HDFS的数据节点上,可避免大量的数据传输,实现数据处理的本地性,进而大大提高整个过程的完成效率,这也正是Hadoop集群的部署方式。
在一个小于50个节点的小规模集群中,可以将NameNode与JobTracker合并于同一个节点上运行。而整个集群共有5类运行的核心进程,它们是MapReduce集群的JobTracker和TaskTracker,以及HDFS集群的NameNode、DataNode和SecondaryNameNode。
Hadoop生态圈
运行环境
Hadoop 运行环境
Hadoop基于Java语言开发,因此其运行严重依赖于JDK(Java Development Kit),并且Hadoop的许多功能依赖于Java 6及以后的版本才提供的特性,除了JDK之外,Hadoop集群的正常运行还可能根据实际环境依赖于其它的一些软件以实现集群的维护、监控及管理等。这些软件诸如cron、ntp、ssh、postfix/sendmail及rsync等。cron通常用于在Hadoop集群中过期的临时文件、归档压缩日志等定期任务的执行;ntp则用于为集群的各节点实现时间同步;ssh并非是必须的,但在MapReduce或HDFS的master节点上一次性启动整个集群时通过要用到ssh服务;postfix/sendmail则用于将cron的执行结果通知给管理员;rsync可用于实现配置文件的同步等。
1. 节点的主机名
Hadoop在基于主机引用各节点时会有一些独特的方式,这已经让很多的Hadoop管理员为此头疼不已。实际使用中,应该避免集群中的各节点尤其是从节点(DataNode和TaskTracker)使用localhost作为本机的主机名称,除非是在伪分布式环境中。
2. 用户、组及目录
一个完整的Hadoop集群包含了MapReduce集群和HDFS集群,MapReduce集群包含JobTracker和TaskTracker两类进程和许多按需启动的任务类进程(如map任务),HDFS集群包含NameNode、SecondaryNameNode和DataNode三类进程。安全起见,应该以普通用户的身份启动这些进程,并且MapReduce集群的进程与HDFS集群的进程还应该使用不同的用户,比如分别使用mapred和hdfs用户。使用CDH的RPM包安装Hadoop时,这些用户都会被自动创建,如果基于tar包安装,则需要手动创建这些用户。
Hadoop通常有三种运行模式:本地(独立)模式、伪分布式(Pseudo-distributed)模式和完全分布式(Fully distributed)模式
hadoop的配置共有四种级别:集群、进程、作业和单独操作,前两类由集群管理员负责配置,后面的两类则属于程序员的工作范畴。
Hadoop的配置文件
hadoop 的配置文件中core-site.xml、mapred-site.xml和hdfs-site.xml三个配置文件最为关键。
hadoop-env.sh: 用于定义hadoop运行环境相关的配置信息,比如配置JAVA_HOME环境变量、为hadoop的JVM指定特定的选项、指定日志文件所在的目录路径以及master和slave文件的位置等;
core-site.xml: 用于定义系统级别的参数,如HDFS URL、Hadoop的临时目录以及用于rack-aware集群中的配置文件的配置等,此中的参数定义会覆盖core-default.xml文件中的默认配置,用于配置hadoop集群的特性,它作用于全部进程及客户端;
hdfs-site.xml: hdfs集群工作属性的相关设定,如文件副本的个数、块大小及是否使用强制权限等,此中的参数定义会覆盖hdfs-default.xml文件中的默认配置;
mapred-site.xml:配置mapreduce集群工作属性的相关设定,如reduce任务的默认个数、任务所能够使用内存的默认上下限等,此中的参数定义会覆盖mapred-default.xml文件中的默认配置;
slaves:Hadoop集群的slave主机列表,master启动时会通过SSH连接至此列表中的所有主机并为其启动DataNode和taskTracker进程;