一、HDFS概述
1、HDFS的前提和设计目标
- 存储超大文件:大文件(单个在MB以上),海量文件(总存储量在PE、EB级别)
- 硬件容错:基于普通机器搭建,硬件错误是常态而不是异常,因此错误检测和快速、自动的恢复是HDFS最核心的架构目标
- 数据流式访问:为数据批处理而设计,关注数据访问的高吞吐量
- 简单的一致性模型:一次写入,多次读取,一个文件经创建写入关闭后就不需要再更改,可以进行追加
- 本地计算:讲计算移到数据本地
- 不适合低延时数据,无法存储大量小文件(文件块信息会存储在namenode节点内存里,小文件太多会占用内存)
2、HDFS基本构成
- 数据块:文件以块为单位切分存储,块大小默认128M;块越大寻址越快,相应的读取也更快,由于MapReduce任务也是以块切分,太大的块不利于数据计算;一个文件最少有一个块
- nameNode:负责维护整个文件系统的信息,包括:整个文件树,文件的块分布信息,文件系统的元数据,数据复制策略等
- dataNode:存储文件内容,负责文件实际的读写操作,保持与namenode的 通信,同步文件块信息
- secondaryNameNode:辅助合并NameNode的edits和fsimage文件,紧急情况下帮助nameNode恢复
- client:与namenode进行交互,包括文件上传下载和对hdfs的操作
二、NameNode和SecondaryNameNode
1、nameNode的启动流程
- 开启安全模式,不能执行任何数据修改操作
- 加载fsimage
- 逐个执行edits文件中的每一条操作,合并到fsimage中,执行完后生成一个空的edits文件
- 接收datanode发生的心跳信息和块信息
- 确定文件系统的状态释放正常
- 退出安全模式
2、HDFS写读流程
写流程:
- 客户段向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在,是否有写的权限,集群是否可以和检查文件租约
- NameNode返回是否可以上传
- 客户端请求第一个 Block上传到哪几个DataNode服务器上
- NameNode返回3个DataNode节点,分别为dn1、dn4、dn5
- 客户端请求dn1上传数据,dn1收到请求会继续调用dn4,然后dn4调用dn5,将这个通信管道建立完成
- 客户端开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,dn1收到一个Packet就会传给dn4,dn4传给dn5;dn1每传一个packet会放入一个应答队列等待应答。packet的数据以chunk作为累计,累计到一个packet就会放入等待应答队列,应答队列也在向hdfs进行数据写入
- 当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器
读流程:
- 客户端向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址
- 挑选一台DataNode(就近原则(先本节点>相邻节点>相邻机架),然后随机)服务器,请求读取数据
- DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)
- 客户端以Packet为单位接收,先在本地缓存,然后写入目标文件
3、NameNode和SecondaryNameNode工作机制
Fsimage:NameNode内存中元数据序列化后形成的文件。
Edits:记录客户端更新元数据信息的每一步操作(可通过Edits运算出元数据)。
NameNode启动时,先滚动Edits并生成一个空的edits.inprogress,然后加载Edits和Fsimage到内存中,此时NameNode内存就持有最新的元数据信息。Client开始对NameNode发送元数据的增删改的请求,这些请求的操作首先会被记录到edits.inprogress中(查询元数据的操作不会被记录在Edits中,因为查询操作不会更改元数据信息),如果此时NameNode挂掉,重启后会从Edits中读取元数据的信息。然后,NameNode会在内存中执行元数据的增删改的操作。
由于Edits中记录的操作会越来越多,Edits文件会越来越大,导致NameNode在启动加载Edits时会很慢,所以需要对Edits和Fsimage进行合并(所谓合并,就是将Edits和Fsimage加载到内存中,照着Edits中的操作一步步执行,最终形成新的Fsimage)。SecondaryNameNode的作用就是帮助NameNode进行Edits和Fsimage的合并工作。
SecondaryNameNode首先会询问NameNode是否需要CheckPoint(触发CheckPoint需要满足两个条件中的任意一个,定时时间到和Edits中数据写满了)。直接带回NameNode是否检查结果。SecondaryNameNode执行CheckPoint操作,首先会让NameNode滚动Edits并生成一个空的edits.inprogress,滚动Edits的目的是给Edits打个标记,以后所有新的操作都写入edits.inprogress,其他未合并的Edits和Fsimage会拷贝到SecondaryNameNode的本地,然后将拷贝的Edits和Fsimage加载到内存中进行合并,生成fsimage.chkpoint,然后将fsimage.chkpoint拷贝给NameNode,重命名为Fsimage后替换掉原来的Fsimage。NameNode在启动时就只需要加载之前未合并的Edits和Fsimage即可,因为合并过的Edits中的元数据信息已经被记录在Fsimage中。
checkPoint设置
hdfs-default.xml
<!-- 默认1小时合并fsimage和edits -->
<property>
<name>dfs.namenode.checkpoint.period</name>
<value>3600</value>
</property>
<!-- 操作动作次数 -->
<property>
<name>dfs.namenode.checkpoint.txns</name>
<value>1000000</value>
</property>
NameNode故障处理
1):删除旧的数据,将SecondaryNameNode的数据拷贝到对应的数据目录,完成后重启hdfs --daemon start namenode
2):删除旧数据,修改配置文件hdfs-site.xml,拷贝SecondaryNameNode目录,并删除in_use.lock文件,导入检查点数据hdfs namenode -importCheckpoint,等待一会儿后ctrl+c结束,再重启hdfs --daemon start namenode
<property>
<name>dfs.namenode.checkpoint.period</name>
<value>120</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/opt/module/hadoop-3.1.3/data/tmp/dfs/name</value>
</property>
三、DataNode
1、DataNode工作机制
- 一个数据块在DataNode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳
- dataNode启动后向NameNode注册,通过后,周期性(1小时)的向NameNode上报所有的块信息
- 心跳是每3秒一次,心跳返回结果带有NameNode给该DataNode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个DataNode的心跳,则认为该节点不可用
- 集群运行中可以动态的增加和删减机器
2、数据完整性、掉线参数、多目录存储
数据完整性:当DataNode读取Block的时候,它会计算CheckSum,读取节点上的checkSum如果和写入的时候值不一一致,说明文件损坏
掉线参数:当dataNode与nameNode由于网络不通或者dataNode死亡时,nameNode不会马上把dataNode下掉,要经过一段时间,默认为10min+3s;
计算公式为:TimeOut = 2 * dfs.namenode.heartbeat.recheck-interval + 10 * dfs.heartbeat.interval
hdfs-site.xml
<property>
<name>dfs.namenode.heartbeat.recheck-interval</name>
<value>300000</value>
</property>
<property>
<name>dfs.heartbeat.interval</name>
<value>3</value>
</property>
多目录:目录最好提前指定,新增需要提前指定
hdfs-site.xml
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///${hadoop.tmp.dir}/dfs/data1,file:///${hadoop.tmp.dir}/dfs/data2</value>
</property>
开启数据平衡
start-balancer.sh –threshold 10
对于参数10,代表的是集群中各个节点的磁盘空间利用率相差不超过10%,可根据实际情况进行调整。
平衡后要及时停止,避免一直平衡,导致系统变慢
stop-balancer.sh
3、节点服役和退役
节点服役
新增机器和已经服役的机器配置相同,直接启动当前节点的dataNode和nodeManager,执行hdfs --daemon start datanode、yarn-daemon.sh start nodemanager,如果数据不平衡执行平衡数据命令
节点退役
节点退役采用白名单退役和黑名单退役,不在白名单的机器为退役,黑名单的机器为退役
白名单
1):在NameNode的/opt/module/hadoop-3.1.3/etc/hadoop目录下创建dfs.hosts,文件中不包含需要退役的节点
2):在NameNode的hdfs-site.xml配置文件中增加dfs.hosts属性
<property>
<name>dfs.hosts</name>
<value>/opt/module/hadoop-3.1.3/etc/hadoop/dfs.hosts</value>
</property>
3):配置文件分发
4):更新nameNode和nodeManager,执行:
hdfs dfsadmin -refreshNodes
yarn rmadmin -refreshNodes
5):执行数据平衡命令
黑名单
1):在NameNode的/opt/module/hadoop-3.1.3/etc/hadoop目录下创建dfs.hosts.exclude文件,添加要退役的节点
2):在hdfs-site.xml增加一下配置
<property>
<name>dfs.hosts.exclude</name>
<value>/opt/module/hadoop-3.1.3/etc/hadoop/dfs.hosts.exclude</value>
</property>
3):刷新NameNode、刷新ResourceManager
hdfs dfsadmin -refreshNodes
yarn rmadmin -refreshNodes
4):进行数据平衡