适应的场景
1,存储非常大的文件:这里非常大指的是几百M、G、或者TB级别,需要高吞吐量,对延时没有要求。
2,采用流式的数据访问方式: 即一次写入、多次读取,数据集经常从数据源生成或者拷贝一次,然后在其上做很多分析工作 ,且不支持文件的随机修改。
3,正因为如此,HDFS适合用来做大数据分析的底层存储服务,并不适合用来做.网盘等应用,因为,修改不方便,延迟大,网络开销大,成本太高。
4,运行于商业硬件上: Hadoop不需要特别贵的机器,可运行于普通廉价机器,可以处节约成本
5,需要高容错性
6,为数据存储提供所需的扩展能力
不适应的场景
1,低延时的数据访问 对延时要求在毫秒级别的应用,不适合采用HDFS。HDFS是为高吞吐数据传输设计的,因此可能牺牲延时
2,大量小文件 文件的元数据保存在NameNode的内存中, 整个文件系统的文件数量会受限于NameNode的内存大小。 经验而言,一个文件/目录/文件块一般占有150字节的元数据内存空间。如果有100万个文件,每个文件占用1个文件块,则需要大约300M的内存。因此十亿级别的文件数量在现有商用机器上难以支持。
3,多方读写,需要任意的文件修改 HDFS采用追加(append-only)的方式写入数据。不支持文件任意offset的修改,HDFS适合用来做大数据分析的底层存储服务,并不适合用来做.网盘等应用,因为,修改不方便,延迟大,网络开销大,成本太高。
HDFS的四大组件
HDFS Client:就是客户端
- 文件切分。文件上传 HDFS 的时候,Client 将文件切分成 一个一个的Block,然后进行存储
- 与 NameNode 交互,获取文件的位置信息
- 与 DataNode 交互,读取或者写入数据。
- Client 提供一些命令来管理 和访问HDFS,比如启动或者关闭HDFS。
NameNode:就是 master,它是一个主管、管理者 - 管理 HDFS 的名称空间
- 管理数据块(Block)映射信息
- 配置副本策略
- 处理客户端读写请求
DataNode: 就是Slave。NameNode 下达命令,DataNode 执行实际的操作 - 存储实际的数据块。
- 执行数据块的读/写操作。
- 定时向namenode汇报block信息
Secondary NameNode:并非 NameNode 的热备。当NameNode 挂掉的时候,它并不能马上替换 NameNode 并提供服务 - 辅助 NameNode,分担其工作量。
- 定期合并 fsimage和fsedits,并推送给NameNode。
- 在紧急情况下,可辅助恢复 NameNode
HDFS的写数据流程
1、client发起文件上传请求,通过RPC与NameNode建立通讯,NameNode检查目标文件是否已存在,父目录是否存在,返回是否可以上传;
2、client请求第一个 block该传输到哪些DataNode服务器上;
3、NameNode根据配置文件中指定的备份数量及副本放置策略进行文件分配,返回可用的DataNode的地址,如:A,B,C;
4、client请求3台DataNode中的一台A上传数据(本质上是一个RPC调用,建立pipeline),A收到请求会继续调用B,然后B调用C,将整个pipeline建立完成,后逐级返回client;
5、client开始往A上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet为单位(默认64K),A收到一个packet就会传给B,B传给C;A每传一个packet会放入一个应答队列等待应答。
6、数据被分割成一个个packet数据包在pipeline上依次传输,在pipeline反方向上,逐个发送ack(命令正确应答),最终由pipeline中第一个DataNode节点A将pipeline ack发送给client;
7、当一个block传输完成之后,client再次请求NameNode上传第二个block到服务器。
HDFS的读数据流程
1、Client向NameNode发起RPC请求,来确定请求文件block所在的位置;
2、NameNode会视情况返回文件的部分或者全部block列表,对于每个block,NameNode都会返回含有该block副本的DataNode地址;
3、这些返回的DN地址,会按照集群拓扑结构得出DataNode与客户端的距离,然后进行排序,排序两个规则:网络拓扑结构中距离Client近的排靠前;心跳机制中超时汇报的DN状态为STALE,这样的排靠后;
4、Client选取排序靠前的DataNode来读取block,如果客户端本身就是DataNode,那么将从本地直接获取数据;底层上本质是建立Socket Stream(FSDataInputStream),重复的调用父类DataInputStream的read方法,直到这个块上的数据读取完毕;
5、当读完列表的block后,若文件读取还没有结束,客户端会继续向NameNode获取下一批的block列表;
6、读取完一个block都会进行checksum验证,如果读取DataNode时出现错误,客户端会通知NameNode,然后再从下一个拥有该block副本的DataNode继续读。
7、read方法是并行的读取block信息,不是一块一块的读取;NameNode只是返回Client请求包含块的DataNode地址,并不是返回请求块的数据;
最终读取来所有的block会合并成一个完整的最终文件。
FsImage和Edits
edits:
edits 是在NameNode启动时对整个文件系统的快照存放了客户端最近一段时间的操作日志
客户端对 HDFS 进行写文件时会首先被记录在 edits 文件中。
edits 修改时元数据也会更新
文件查看:
使用hife命令:
cd /export/server/hadoop-2.7.5/hadoopDatas/namenodeDatas/current
hdfs oiv -i fsimage_0000000000000000138 -p XML -o hello.xml
fsimage:
fsimage是在NameNode启动时对整个文件系统的快照。
NameNode 中关于元数据的镜像, 一般称为检查点, fsimage 存放了一份比较完整的元数据信息
因为 fsimage 是 NameNode 的完整的镜像, 如果每次都加载到内存生成树状拓扑结构,这是非常耗内存和CPU, 所以一般开始时对 NameNode 的操作都放在 edits 中,随着edits 内容增大, 就需要在一定时间点和 fsimage 合并
文件查看:
cd /export/server/hadoop-2.7.5/hadoopDatas/nn/edits/current
hdfs oev -i edits_0000000000000000865-0000000000000000866 -p XML -o myedit.xml
SecondaryNameNode的作用
SecondaryNameNode的作用是合并fsimage和edits文件。
NameNode的存储目录树的信息,而目录树的信息则存放在fsimage文件中,当NameNode启动的时候会首先读取整个fsimage文件,将信息装载到内存中。
Edits文件存储日志信息,在NameNode上所有对目录的最新操作,增加,删除,修改等都会保存到edits文件中,并不会同步到fsimage中,当NameNode关闭的时候,也不会将fsimage和edits进行合并。
所以当NameNode启动的时候,首先装载fsimage文件,然后按照edits中的记录执行一遍所有记录的操作,最后把信息的目录树写入fsimage中,并删掉edits文件,重新启用新的edits文件。
但是如果NameNode执行了很多操作的话,就会导致edits文件会很大,那么在下一次启动的过程中,就会导致NameNode的启动速度很慢,慢到几个小时也不是不可能,所以出现了SecondNameNode。
SecondaryNameNode唤醒合并的规则
SecondaryNameNode 会按照一定的规则被唤醒,进行fsimage和edits的合并,防止文件过大。
合并的过程是,将NameNode的fsimage和edits下载到SecondryNameNode 所在的节点的数据目录,然后合并到fsimage文件,最后上传到NameNode节点。合并的过程中不影响NameNode节点的操作
SecondaryNameNode被唤醒的条件可以在core-site.xml中配置:
fs.checkpoint.period:单位秒,默认值3600(1小时),检查点的间隔时间,当距离上次检查点执行超过该时间后启动检查点
fs.checkpoint.size:单位字节,默认值67108864(64M),当edits文件超过该大小后,启动检查点
[core-site.xml]
<!-- 多久记录一次 HDFS 镜像, 默认 1小时 -->
<property>
<name>fs.checkpoint.period</name>
<value>3600</value>
</property>
<!-- 一次记录多大, 默认 64M -->
<property>
<name>fs.checkpoint.size</name>
<value>67108864</value>
</property>
SecondaryNameNode一般处于休眠状态,当两个检查点满足一个,即唤醒SecondaryNameNode执行合并过程。
SecondaryNameNode工作过程
第一步:将hdfs更新记录写入一个新的文件——edits.new。
第二步:将fsimage和editlog通过http协议发送至secondary namenode。
第三步:将fsimage与editlog合并,生成一个新的文件——fsimage.ckpt。这步之所以要在secondary namenode中进行,是因为比较耗时,如果在namenode中进行,或导致整个系统卡顿。
第四步:将生成的fsimage.ckpt通过http协议发送至namenode。
第五步:重命名fsimage.ckpt为fsimage,edits.new为edits。
第六步:等待下一次checkpoint触发SecondaryNameNode进行工作,一直这样循环操作。
注意:SecondaryNameNode 在合并 edits 和 fsimage 时需要消耗的内存和 NameNode 差不多, 所以一般把 NameNode 和 SecondaryNameNode 放在不同的机器上
NameNode元数据恢复
当NameNode发生故障时,我们可以通过将SecondaryNameNode中数据拷贝到NameNode存储数据的目录的方式来恢复NameNode的数据
操作步骤:
1、杀死NameNode进程
kill -9 NameNode进程号
2、删除NameNode存储的数据
rm /export/server/hadoop-2.7.5/hadoopDatas/namenodeDatas/* -fr
3、在node2主机上,拷贝SecondaryNameNode中数据到原NameNode存储数据目录
cd /export/server/hadoop-2.7.5/hadoopDatas/snn/name/
scp -r current/ node1:/export/server/hadoop-2.7.5/hadoopDatas/namenodeDatas
4、重新启动NameNode
hadoop-daemon.sh start namenode