HDFS

一、HDFS节点角色:

(1)namenode:1、用来存储HDFS的元数据信息,这里的元数据信息指的是文件系统的命名空间。启动时,将这些信息加载到namenode内存。

         2、元数据信息也会在磁盘上保存成fsimage和edit log 文件。

                              3、namenode的内存中也会保存文件的具体信息,如:一个文件包含哪些数据块,分布在哪些节点上。这些信息在系统启动时从datenode上进行收集。

(2)secondary namenode:用于周期性的合并namenode中的fsimage文件和edit log文件。文件合并之后,会返回给namenode,同时secondary 里也会保存一份,用于namenode故障恢复。

(3)datenode:存储文件数据块数据。定时向namenode汇报存储的数据块信息。

补充:   

数据块:HDFS将文件分块存储,文件块默认大小为128M,可以设置。mapreduce的maptask数量和文件块的数量对应。其中,文件块不宜太小,增加寻址时间;

    同时文件也不宜过大,过大导致maptask太少,少于集群节点数量,没有充分利用集群资源,导致作业运行速度慢。

    文件分块的优势:a、存储文件大小可以大于任何一个集群中磁盘容量;

                 b、不使用整个文件进行存储,简化存储子系统设计,这点比较虚

                                          c、利于数据备份,有利于集群高可用。

 二、HDFS读写机制:

1、HDFS的读机制:客户端读hdfs文件

1、初始化 DistributedFileSystem 对象 ,clinet客户端调用 DistributedFileSystem中的 open() 方法打开文件。

2、DistributedFileSystem对象调用远程RPC服务,获取namenode上的文件的数据块信息,每个数据块 namenode 返回数据块的节点地址。

3、DistributedFileSystem 创建一个 FSDataIputStream 给 client 客户端,client 客户端调用 FSDataIputStream 中的 read() 方法开始读取数据。

4、FSDataIputStream 连接保存此文件的第一个数据块的 DataNode,读取数据。

5、数据读取完毕,关闭流连接,连接文件的下一个数据块的 DataNode。

6、client 客户端将文件读取完毕后,调用 FSDataInputStream 的 close() 方法关闭文件输入流连接。

注意:若在读数据的过程中,客户端和DataNode的通信出现错误,则会尝试连接下一个 包含次文件块的 DataNode。同时记录失败的 DataNode,此后不再被连接。

2、HDFS写机制:客户端向hdfs中写数据

1、client客户端调用DistributedFileSystem对象 分布式文件系统对象 的create()方法,创建一个文件输出流FSDataOutputStream对象。

2、DistributedFileSystem对象和Hadoop中的namenode进行一次远程RPC调用,在namenode中创建一个文件条目Entry,该条目没有任何的block。

3、client通过 FSDataOutputStream 文件输出流向datanode中写数据,数据首先被写入 FSDataOutputStream 内部的 buffer 中,然后被分成一个个的 packet 数据包。

4、以 packet 数据包为最小单位,向集群中的一个 DataNode 发送数据,在这组 DataNode 组成的Pipeline线管上依次传输 packet 数据包。

5、在Pipeline线管的反向上依次发送ack,最终由第一个DataNode发送ack给client客户端。

6、文件传输结束,客户端调用 FSDataOutputStream 的 close 方法关闭流。

7、客户端调用 DistributedFileSystem 的 complete() 方法,通知 namenode 文件写入成功。

 3、客户端从hdfs读写数据出错:

(1)Hdfs读数据出错:

  若在读数据的过程中,客户端和DataNode的通信出现错误,则会尝试连接下一个 包含次文件块的DataNode。同时记录失败的DataNode,此后不再被连接。

(2)Hdfs在写某一个副本数据的时候出错:

1)首先会关闭dataNode联通的线管。

2)将已发送至线管内,还没有收到确认消息的数据包重新写回到数据队列中,保证数据不丢失。

3)将当前正常工作的dataNode赋予新的版本号,这样保证即使故障dataNode节点恢复了,由于版本号不对,故障dataNode也将会被剔除。这个新的版本号是利用nameNode的租约信息获取。

4)在当前正常的dataNode中选择一个主dataNode,并与其他的dataNode进行通信,来获取每个dataNode的当前数据块的大小,然后选择出一个最小的值,将当前的所有dataNode都同步到该大小。再重新建立线管。

5)在线管中删除故障节点,将数据写入线管中正常的dataNode,即新管道。

6)当文件关闭后,若nameNode发现副本数不足,会在其他的dataNode上创建新的副本。

三、HDFS的HA高可用机制:

1、Hdfs的HA高可用:

  保证Hdfs高可用,其实就是保证namenode的高可用,保证namenode的高可用的机制有两个,edit log共享机制+ZKFC。ZKFC就是ZookeeperFailOverController,即zookeeper故障转移控制器。

2、nameNode的高可用机制:

(1)nameNode想要实现高可用,意味着集群中要存在多个nameNode,在nameNode出现故障的时候,能够进行快速切换。集群中平时只有一个nameNode在工作,这个nameNode就是active的,而其他nameNode是standby的。

(2)为了保证nameNode出现故障的时候,nameNode的切换速度。active nameNode将信息写入共享编辑日志文件,standby nameNode则读取共享文件,从而保持与active nameNode的同步。

(3)此外,集群中的dataNode要向所有的nameNode发送数据块处理报告。

(4)故障切换这个动作就需要ZKFC来保证,每个nameNode中都运行着一个ZKFC故障转移控制器,用于监视nameNode进程。而这个ZKFC是基于Zookeeper实现的,在启动的时候,会创建HealthMonitor和ActiveStandbyElector这两个组件,创建的同时,ZKFC也会向这两个组件中注册相应的回调方法。

(5)HealthMonitor初始化完成后会启动内部线程来定时调用nameNode的HAServiceProtocol Rpc接口,对nameNode进行健康监测。

(6)HealthMonitor如果检查到nameNode的健康状态发生了变化,就会回调ZKFC注册的相应方法进行处理。

(7)如果ZKFC经过判断后,认为需要进行主备切换话,会首先使用ActiveStandbyElector来进行自动的主备选举。

(8)ActiveStandbyElector完成了自动的主备选举后,会回调ZKFC的相应方法,通知相应的nameNode成为主nameNode或者备nameNode。

(9)ZKFC调用相应nameNode的HAServiceProtocol Rpc接口方法,将相应的nameNode设置成active或者standby。

3、Fencing实现:

  脑裂就是nameNode假死,Fencing就是防御脑裂。Hadoop公共库对外提供了两种Fencing实现,分别是sshfence和shellfence(缺省实现)。其中sshfence就是通过ssh登陆到目标nameNode节点上,用kill命令将其进程杀死;shellfence就是执行自定义的shell脚本。

4、如何判断是否发生了脑裂:

  判断持久化节点是否存在,持久化节点存在就是脑裂。

原文地址:https://www.cnblogs.com/guoyu1/p/11884456.html