一HDFS
什么是HDFS?
当数据集大小超过一台独立的物理计算机的存储能力时,就有必要对它进行分区并存储到若干台独立的计算机上.
管理网络中跨多台计算机存储的文件系统成为分布式文件系统.
该系统架构于网络之上,势必会引入网络编程的复杂性.因此分布式文件系统比普通文件系统更为复杂.
二内部原理
1.NameNode职责
NameNode集群有两类节点,一个NameNode管理节点和多个DataNode工作节点.
(1)NameNode是HDFS的元数据服务器,管理并协调数据节点DataNode的工作.
(2)接收客户端的请求
2.NameNode元数据
(1)内存有一份完整的元数据:metadata内存元数据,包括:
[1]系统目录树;该类元数据在NameNode上定期持久化.保存为镜像文件. 恢复该类元数据需要fsimage和edites
[2]数据块副本与DataNode的映射,即副本位置.副本的位置信息没有实现持久化,而是在
NameNode启动时,接收DataNode的BlockReport(块报告)获得.
(2)fsimage:磁盘元数据镜像文件.它是一个准完整的元数据.
(3)edits操作日志
用于衔接内存元数据metadata和持久的元数据镜像文件fsimage.
客户端对HDFS文件系统目录树进行的任何修改,都会被记录到edits操作日志中,以保证系统出现故障后,能根据这些日志进行恢复.
3.SecondaryNameNode职责
(1)合并元数据edits和fsimage
NameNode在恢复元数据时可能要加载大量操作日志,如果这个操作在NameNode上进行,则消耗大量的资源.NameNode的服务将会暂停.所以把这个任务交给SecondaryNameNode.
但随着日志的不断增加,这意味着需要进行修复的时间也就越长.为了避免这一情况发生,HDFS引入了检查点(checkpoint)机制.
(2)备份fsimage
4.checkpoint机制
(1)执行checkpoint进程的条件
#两次checkpoint之间的时间间隔3600秒=1h
dfs.namenode.checkpoint.check.period=3600
#两次两次checkpoint之间最大操作记录为100万次
dfs.namenode.checkpint.txns=1000000
不管先达到哪个都会触发checkpoint
(2)SecondaryNameNode通过远程接口启动一次checkponint检查点进程.
这时NameNode需要创建一个新的edits操作日志:edits.new.后续对文件系统的任何修改都记录在这个新的操作日志里(即edits操作日志的回滚)
(3)SecondaryNameNode将NameNode上的edits下载到本地,将它和本地存储的fsimages在内存进行合并.合并的结果输出为fsimage.checkpoint.将这个文件上传给NameNode,NameNode要对这个文件进行校验.校验成功后改名.fsimage序号递增.
5.DataNode职责
(1)存储和管理用户的文件块数据.
(2)通过心跳定期向NameNode汇报自身所持有的block信息(默认3秒)
(3)DataNode进程死亡或者网络故障造成DataNode无法与NameNode通信,NameNode不会立即把该节点判定为死亡.要经过一段时间,这段时间成为超时时长.HDFS默认的超时时长为10分钟+30秒.
6.HDFS读流程
(1)客户端向NameNode发送请求下载资源.
(2)NameNode判断文件是否存在,如果存在返回文件的元数据信息:文件有多少块,块的顺序,块的存储的位置等.
(3)客户端按顺序和DataNode建立连接,下载块.
下载的过程:DataNode先把块读到内存(FileInputStream),再写到SocketOutputStream中,客户端从这里写到内存中(SocketInputputStream),然后写入到磁盘FileOutoutStream.
注:每个块读完都会有一个结束标识
7.HDFS写流程
(1)客户端向NameNode发送请求
hdfs dfs -put /etc/profile /juruo/data
(2)NameNode检查看它的目录树中是否存在客户端指定的路径/juruo/data
如果不存在直接报错"no such file or directory".
检查在用户指定的目录下该文件是否存在,如果存在给出提示.
如果目录存在文件不存在,NameNode给客户端一个同意上传文件的响应,将操作写入操作日志.
(3)客户端发送rpc请求,请求上传第一块文件.
(4)NameNode根据DataNode的块报告得到DataNode的磁盘使用情况列表,选择三个节点返回给客户端,通过:
[1]负载均衡(空间)
[2]距离(距离越近越快,距离通过机架感知得到)
找三台DataNode返回给客户端.上传数据时,DataNode选择策略:
第一个副本优先选择跟客户端距离最近的机架(同机架).
第二个副本选择跨机架的一台机器,增加副本的安全性.
第三个副本选择跟第二个副本同机架的不同机器.
(5)客户端和第一个DataNode请求建立块传输通道(pipeline管道)第一个DataNode和第二个DataNode请求建立pipeline,第二个DataNode和第三个DataNode请求建立pipeline.
(6)三返回应答成功给二,二返回应答成功给一,一返回应答成功给客户端.
(7)客户端将块读入到内存.然后存到包中,包的大小为64kb,包在网络上传输.包先到DataNode1,然后DataNode1复制转发到DataNode2,DataNode2转发到DataNode3,每次成功传输一个包都会给前面的节点一个成功的响应.
(8)一个块传输成功后,客户端会向NameNode发送请求上传第二个块,直到整个文件上传完为止.
(9)当整个文件上传成功,客户端会返回一个状态.NameNode会写入元数据.
8.HDFS存储小文件
HDFS一个块的元数据大小为150kb,存储一个小文件(远远小于128m)的元数据占用150kb的内存.如果存储大量的小文件,很快就会将Name
Node内存耗尽.而整个集群没存多少东西,失去了HDFS的意义.
处理方式:
(1)可以将数据合并再上传到hdfs
(2)mr 使用CombineFileInputFormat
(3)如果是hive有很多小文件,可以将数据插入到临时表,然后再将这个临时表改名为原表(会自动合并)
# ---方法1最后开启一个mr单独处理数据 # 控制每个任务合并小文件后的文件大小(默认256000000,256MB): set
hive.merge.size.per.task=2048000000; # 告诉 hive 什么样的文件属于小文件(默认16000000,小于16MB):
set hive.merge.smallfiles.avgsize=512000000; # 是否合并Map的输出文件(默认true): set
hive.merge.mapfiles=true; # 是否合并Reduce的输出文件(默认false): set
hive.merge.mapredfiles=true; #---方法2通过读入的切片大小来设置 set
mapred.max.split.size=1682000000; --切片的最大值 set
mapred.min.split.size=1346000000; --切片的最小值 set
mapred.min.split.size.per.node=1346000000; --每个节点切片的最小值 set
mapred.min.split.size.per.rack=1346000000; --每个机架切片的最小值
(4)使用hdfs自带的archive命令
对某目录/foo/bar下的所有小文件存档成/outputdir/zoo.bar
hadoop archive -archiveName zoo.har -p /foo/bar /outputdir
9.安全模式
安全模式是一种HDFS的工作状态.
处于安全模式下,只能读数据.
同时NameNode也不会进行数据块的复制和删除.
进入安全模式的情况
(1)block块的占比低于阈值0.999f
(2)DataNode启动数量不足(默认为0)
退出安全模式:
(1)调低阈值
这里设置的是副本数达到最小要求的block占系统总block数的百分比.
当实际比例超过该配置时才能离开安全模式
hdfs-site.xml中
<name>dfs.namenode.safemode.threshold</name>
<value>0.999f</value>
(2)强制离开
hdfs dfsadmin --safemode leave
(3)重新格式化集群
(4)修复损坏的块文件
10.NameNode启动流程
1.加载镜像文件,还原了checkpoint检查点的元数据(包含目录结构,文件大小,块的大小,块的id等信息).
2.加载edits操作日志,还原checkpoint时间点到集群停止的元数据.
3.BlockReport块报告阶段,DataNode启动,向NameNode报告自己所管理的块位置及块的id,NameNode根据块的ID还原块的存储位置.
4.在BlockReport结束后,集群会判断DataNode的启动数量(可设置,默认为0),块的占比(可设置,默认为0.999f)是否满足退出安全模式的条件,如果满足,30秒后退出安全模式.在退出安全模式后,NameNode会删除多余的块,还会复制低于副本数的块.