Hadoop学习笔记和总结(七)

走远了吗. 提交于 2020-01-25 09:41:11

 

目录

第七章 HDFS的四个机制与两个核心功能

7.1 HDFS 机制

7.1.1 心跳机制

7.1.2 安全模式

7.1.3 机架策略

7.1.4 负载均衡

7.2 HDFS文件上传流程

7.3 HDFS文件下载流程


第七章 HDFS的四个机制与两个核心功能

HDFS提供的是高容错性的分布式数据存储方案,其包括四个主要的机制:(1)心跳机制(2)安全模式(3)机架策略(4)负载均衡;并作为一个文件系统两大核心功能包括:(1)文件上传(2)文件下载(3)元数据的管理

当Hadoop集群启动时,各个进程启动的顺序如下:NameNode --> DataNode --> SecondaryNameNode

7.1 HDFS 机制

HDFS机制中需要重点掌握心跳机制、安全模式和机架策略并理解负载均衡。

7.1.1 心跳机制

集群节点必须做时间同步。

NameNode是集群的Boss,负责集群中任务的分工。如果要进行分工,则必须知道各个DataNode的存活状况。NameNode是如何知道各DataNode的存活状态的呢?

利用心跳机制,即:DataNode定期向NameNode发送心跳报告所确定的。

具体实现:DataNode会每隔3秒(默认)向NameNode发送一次心跳报告,目的是告诉NameNode自己的存活状况。

可以通过修改hdfs-site.xml配置文件,修改发送心跳报告间隔,如下所示:

<property>
  <name>dfs.heartbeat.interval</name>
  <value>3</value>
  <description>Determines datanode heartbeat interval in seconds.</description>
</property>

说完了DataNode主动汇报,但NameNode是如何判定DataNode死亡(宕机)的呢?

NameNode连续10次接收不到心跳报告,则初步认为DataNode可能死亡(宕机),但没断定死亡(有可能是网络延时等原因)。此时,NameNode会主动向DataNode发送一次检查,发送一次检查的时间间隔是5min,一次检查不成功,再检查一次,一共两次机会。若两次都获取不到DataNode返回的信息,才会判定该DataNode死亡。

发送时间间隔也可以通过以下配置修改:

<property>
  <name>dfs.namenode.heartbeat.recheck-interval</name>
  <value>300000</value>
  <description>
    This time decides the interval to check for expired datanodes.
    With this value and dfs.heartbeat.interval, the interval of
    deciding the datanode is stale or not is also calculated.
    The unit of this configuration is millisecond.
  </description>
</property>

所以NameNdoe最终判断DataNode死亡(宕机),需要10*3s + 2*5min = 630s。也就是说NameNode若在连续的630s中没有得到DataNode的信息才判定该DataNode死亡(宕机)。

7.1.2 安全模式

在了解安全模式之前,先复习一下元数据的相关知识。

元数据包括以下三部分:

(1)抽象目录树

(2)数据和数据块的映射关系(如:temp.tar.gz à blk_1,blk_2)

(3)数据块存储的位置信息。

元数据存储的位置有两种:内存和磁盘。其中,内存存储具有读写快,但一旦关机就会造成数据丢失,所以元数据既在内存也在磁盘存储。

(1)内存中存储的元数据有:抽象目录树、数据和数据块的映射关系和数据块存储的位置信息。(三部分都有)

(2)磁盘存储的元数据:抽象目录树、数据和数据块的映射关系。

思考:当集群启动时,集群内部发生了什么事情?

当集群启动时,首先将元数据由磁盘加载到内存中。

如果磁盘中的元数据过大,会造成加载时间过长。所以磁盘中的元数据只存储了抽象目录树、数据和数据块的映射关系两部分。而数据块存储的位置信息,则是通过DataNode的心跳报告获取的。

集群启动时,NameNode会接收DataNode的心跳报告,这个心跳报告中还包含数据块的存储位置信息。这时候NameNode就可获取DataNdoe的数据块的存储状况。

所以,当集群启动时,NameNode需要做以下事情:

(1)NameNode将元数据从磁盘加载内存中

(2)NameNode接收DataNode的心跳报告(获取DataNode存活状况、获取数据块的存储信息)

(3)启动SecondaryNameNode

在集群启动过程中,不允许外界对集群进行操作的,这个时候集群处于安全模式。通俗来讲,集群处于安全模式的时候是在加载元数据和获取DataNode的心跳报告。

如果集群处于维护或升级期间,也可以手动将集群设置安全模式状态。

hdfs dfsadmin -safemode enter    进入安全模式

hdfs dfsadmin -safemode leave    离开安全模式

hdfs dfsadmin -safemode get        获取安全模式的状态是否开启(on:开启;off:关闭)

hdfs dfsadmin -safemode wait       等待自行退出安全模式

在安全模式中可执行的操作:

ls(查询),get(下载),cat(查看)等,即:不对元数据进行修改的操作(主要是抽象目录树)

7.1.3 机架策略

机架策略实质是副本存放机制;默认配置是每个数据块有三个副本(可修改)

思考:这些副本是如何存放的呢?(以三个副本为例)

副本存放策略如下:

(1)第一个副本存储在客户端所在节点上

(2)第二个副本存储在与第一个副本不同机架上的任意一个节点上

目的是:防止同一个机架断电时,数据访问不到

(3)第三个副本存储在和第一个副本相同机架不同的节点上

原因是:在断电风险度相同的情况下,优先选择网络传输少的

在真实生产环境中,可以自定义策略:不同节点,不同机制,不同数据中心

7.1.4 负载均衡

定义:对于HDFS来说每个节点上存储的数据的百分比相差不大,即磁盘利用率相差不多。能力越大,责任越大。硬盘容量大,就多存点儿;磁盘容量小,就少存点儿; 

在进行文件上传时,HDFS会将文件有限存储在客户端所在节点,如果习惯性的使用同一个客户端上传文件,则会造成客户端所在节点存储的数据较多。但集群会有一个自动的负载均衡的操作,只不过这个负载均衡的操作比较慢。

默认配置如下:

<property>
  <name>dfs.datanode.balance.bandwidthPerSec</name>
  <value>1048576</value>
  <description>
        Specifies the maximum amount of bandwidth that each datanode
        can utilize for the balancing purpose in term of
        the number of bytes per second.
  </description>
</property>

在集群空闲的情况下,默认带宽为1M/s。集群自动的负载均衡,对于小规模(集群节点比较少)的时候,是可以的。如果集群较大,需要手动负载均衡。

(1)start-balancer.sh:开启负载均衡;该指令不会立刻执行,需要等到集群空闲时候执行。

(2)stop-balancer.sh:停止负载均衡;

由于不存在绝对的负载均衡,所以在手动负载均衡时,可以指定一个参数,如:

指令:start-balancer.sh –t 10%:任意两个节点之间存储数据量的百分比不超过10%,则认为达到了负载均衡。

思考:负载均衡什么时候发生的概率比较高?

解释:集群中添加了新的节点的时候~

7.2 HDFS文件上传流程

详细步骤说明:

(1)客户端向远程的NameNode发起RPC请求;请求数据上传,请求中包含一个数据长度信息,即文件多少兆。

(2)NameNode接收到请求后,会进行一系列的检查工作。其中包括:文件是否存在、上传的路径是否存在、检查创建者是否具有权限操作等。

(3)NameNode检查通过后,会向客户端返回节点信息;返回节点信息遵循就近原则。(优先返回客户端所在节点—>同机架的节点—>不同机架的节点)

节点信息例如:blk1:datanode01、datanode02、datanode03;blk2:datanode01、datanode03、datanode04

(4)客户端接收到NameNode返回的响应后,会进行一次逻辑切块。(概念上的切分,可理解为物理切分前的准备,即切块规划)

blk1:0-127、blk2:128-200

(5)开始准备文件上传

(6)构建通道(pipeline),根据块ID(Block_ID)依次进行构建。将同一个块的所有存储节点构建成一个数据流通道。如客户端:01-02-04;

(7)当客户端开始写入文件时,客户端会将文件切分成多个packet(边进行上传边进行文件切分,并以packet为单位上传(大小为512KB);并在内部以数据队列(Data Queue)的形式管理这些packet,并向NameNode申请Blocks,获取用来存储副本的的合适的packet列表(如:01-02-04);

(8)将文件先上传到DataNode-01中,在DN-01中,数据会先写到内存(缓存)中,缓存中每当接收完一个packet,则向下一个DataNode传递该packet,同时缓存中的数据还会持续向磁盘中写。

(8)当第一个块的数据上传完成,则通道关闭。

(9)开始上传第二个块,并重复(6)(7)(8)步骤。

(10)所有的块上传完成之后,会返回一个确认队列(ack queue),在pipeline里传递至客户端,告诉客户端数据上传成功。

(11)客户端向NameNode返回信息,告知数据上传成功

(12)NameNode更新元数据。

思考:如果上传过程中,有一个文件块上传失败,会怎么办?

解析:

HDFS会立即进行一次重试,如果还是失败,则将失败节点从pipeline中删除,并将失败节点报告给NameNode;

例如:Client-DataNode-01-DataNode-02-DataNode-04(hadoop02出问题了),如果重试一次还是失败,则将DataNode-02从pipeline中删除,变为:Client-DataNode-01-DataNode-04

HDFS最终可以忍受的最大极限是:至少有一个节点上传成功;若三个节点都失败,这时候会向NameNode重新申请三个节点,重新构建pipeline。

最终文件上传过程中保证的是至少一份就可以,剩下的副本可在文件上传集群成功后,进行异步复制得到的。(自动负载均衡)

其实,在数据上传时,一般情况下肯定会返回一个客户端所在节点,因为客户端节点不存在网络传输,上传失败的可能性小。这个时候保证数据至少上传成功一个节点的可能性大。

7.3 HDFS文件下载流程

Hadoop fs –get,其流程与文件上传正好相反,步骤如下:

(1)客户端向NameNode发送文件下载请求

(2)NameNode在元数据库中进行查询,如果查询到,则会返回给客户端数据的块及副本存储节点;如果查询不到,则会报错;

Blk-1:datanode01、datanode02、datanode03

Blk-2:datanode01、datanode02、datanode04

(3)客户端拿到数据块的存储节点,会先进行第一个数据块的下载;下载时,遵循就近原则。

(4)第一个数据块下载完成后,会生成crc文件;该文件与上传时候的.meta文件,进行文件完整度校验(checkSum);校验的是起始偏移量和末尾偏移量之间的内容。如果检验通过,则认为第一个块下载成功。

(5)进行第二个块下载,重复(3)、(4)步骤。

(6)所有的数据块下载成功之后,向NameNode发送数据下载成功的响应。

思考:文件下载中,某个节点读取不到数据怎么办?

解析:

如果数据块的某一个节点读取不到数据,此时DataNode会向NameNode进行汇报;NameNode会对该DataNode做一个标记,记录该节点是问题节点,然后接着读取该块的其他DataNode中的数据。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!