HDFS基础知识(个人总结)

    声明: 1. 本文为我的个人复习总结, 并那种从零基础开始普及知识 内容详细全面, 言辞官方的文章
              2. 由于是个人总结, 所以用最精简的话语来写文章
              3. 若有错误不当之处, 请指出

HDFS存储优缺点:

  • 优点

    1. 高容错, 因为它有多个副本
    2. 可处理大数据, 文件数量可达百万
  • 缺点

    1. HDFS可以追加,但不能修改某一条数据,若实在想修改,只能下载下来原文件进行修改后重新上传覆盖

    2. 不适合低延迟数据访问,如毫秒级

    3. 无法高效存储大量小文件

      • 小文件导致数量太多, 浪费了NameNode存储文件目录和块信息(150K)等元数据
      • 小文件导致数量太多, 导致寻址时间很长, 甚至大于读取(传输)时间
      • 从MR计算的角度, 即便再小的一个切片, 也要启动一个MapTask

      解决办法:

      1. 从数据源头解决, 产生文件时,积压到一定量再进行输出, 或到了最后末尾不满足阈值了,也输出
      2. har归档
      3. combineInputformat 减少切片个数,进而减少的是maptask
      4. 开启JVM重用

HDFS组成架构:

  • NameNode(NN) 管理者,记录元数据信息(内存)

    1. 管理HDFS的名称空间
    2. 配置副本策略
    3. 管理数据块(Block)映射信息
  • DataNode 执行者,记录实际数据,也记录自身的元数据(磁盘)

  • Secondary NameNode 不常用,是NN的助手,当NN挂掉的时候它不能立即上任

    1. 分担NN的工作, 比如定期合并Fsimage和Edits,并推送给NN
    2. 对NN进行备份

    Client:

    1. 把文件切分成块
      2. 与NN交互获取文件的位置信息
      3. 与DataNode交互, 读写文件
      4. 管理HDFS, 比如对NN初次格式化
    

文件块:

​ 磁盘传输速率普遍为100MB/s, 寻址时间为读取(传输)时间的1%最好

  • 设置大了,在开的Map太少,并行度较低

  • 设置小了,小文件过多导致寻址时间较长

HDFS的Shell操作:

上传到HDFS:

  • 从本地剪切到HDFS: hadoop fs -moveFromLocal ./kongming.txt /sanguo/shuguo (/sanguo/shuguo文件夹需要提前建立)

  • 从本地拷贝到HDFS: hadoop fs -copyFromLocal README.txt /data

  • 在一个文件末尾追加另一个文件的数据: hadoop fs -appendToFile liubei.txt /sanguo/shuguo/kongming.txt

从HDFS下载:

  • 从HDFS拷贝到本地: hadoop fs **-copyToLocal **/sanguo/shuguo/kongming.txt ./

  • 合并下载多个文件: hadoop fs -getmerge /user/atguigu/test/* ./temp.txt

常用命令:

hadoop fs -ls /

hadoop fs -mkdir -p /sanguo/shuguo

hadoop fs -cat /sanguo/shuguo/kongming.txt

hadoop fs -chmod 666 /sanguo/shuguo/kongming.txt

hadoop fs -chown atguigu:atguigu /sanguo/shuguo/kongming.txt

hadoop fs -cp /sanguo/shuguo/kongming.txt /zhuge.txt

hadoop fs -mv /zhuge.txt /sanguo/shuguo/

hadoop fs -tail /sanguo/shuguo/kongming.txt

hadoop fs -rm /user/atguigu/test/jinlian2.txt

hadoop fs -rmdir /test

hadoop fs -du -s -h /user/atguigu/test

hadoop fs -setrep 10 /sanguo/shuguo/kongming.txt (设置副本数量, 只有3台机器3个DataNode,那么副本实际还是3,但在加机器后它会自动扩充直到10为止)

HDFS写数据流程

HDFS基础知识(个人总结)

如果Client一个人对应多个DN进行写,

​ 好处是可以并行写;

​ 坏处是若有一个DN阻塞卡住, 那么Client就会阻塞

做法: Client将一个400M的文件分块写到3个DN里, Client只连接DN1, DN1在一边写到自己磁盘,一边把不属于它的数据传下去传给DN2

Packet 64k(chunk 512Byte + chunksum校验 4Byte)

(1)客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在。

(2)NameNode返回是否可以上传。

(3)客户端请求第一个 Block上传到哪几个DataNode服务器上。

(4)NameNode返回3个DataNode节点,分别为dn1、dn2、dn3。

(5)客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道pipeline建立完成

(6)dn1、dn2、dn3逐级应答客户端。

(7)客户端开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,dn1收到一个Packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答

(8)当一个Block传输完成之后,客户端再次请求NameNode第二个Block上传到哪个DN。(重复执行3-7步)

注意:

  1. packet1发完了,才能发packet2

  2. 要是中途有的DataNode不可用了, 那么这个DataNode会被从pipeline里移除; 传完后NameNode知道这个数据备份数不够,再找个DataNode去同步这个数据,凑够备份数

HDFS读数据流程

HDFS基础知识(个人总结)

(1)客户端通过Distributed FileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址

(2)挑选一台多个副本间离的较近的DataNode服务器,请求读取数据。

(3)DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。

(4)客户端以Packet为单位接收,先在本地缓存,然后写入目标文件

单位:

  1. Block 128M, 物理上的文件数据块
  2. Packet 64k, Client发给DataNode, 以及pipeline的那一堆DataNode间传输用的数据包, 包含实际数据+Chunk+ChunkSum
  3. Chunk(512Byte) ChunkSum(4Byte), 用来验证数据是否损坏的
  4. 切片 InputFormat读入时, 逻辑上的文件数据块, 按Block大小来切块; 但还要看剩余部分是否在1.1倍Block范围内,不超过则剩余部分就按一块来切; 所以切片最大为1.1倍Block

网络拓扑-节点距离计算

​ 规则: NameNode会选择距离待上传数据最近距离的DataNode接收数据, 节点距离为两个节点到达最近的共同祖先的距离总和

机架感知(副本存储节点选择)

​ 存储副本时,如果 所有副本都在同一个机器,那么这台机器崩了所有副本就都没了,不安全;又考虑太远会通信延迟,所以采取以下这种做法

HDFS基础知识(个人总结)

NameNode和SecondaryNameNode

FsImage, Edits, SecondaryNameNode

NN的元数据在内存里, FsImage是对元数据的备份写到磁盘, 引发了问题:

  1. 内存中的元数据更新时,如果同时更新FsImage,就会导致效率过低
  2. 如果不更新,就会发生一致性问题
  3. 如果FsImage没来的及写完到磁盘, 一旦NameNode节点断电,就会产生数据丢失

解决方案:

引入Edits文件(只记录日志不执行接过,只进行追加操作,效率很高)。每当元数据有更新或者添加元数据时,修改内存中的元数据并追加到Edits中

一旦NameNode节点断电,可以通过FsImage和Edits的合并,FsImage+Edits=内存元数据, 来合成元数据,

引发新的问题:

  1. 如果长时间添加数据到Edits中,会导致该文件数据过大,效率降低

  2. 一旦断电,恢复元数据需要的时间过长

解决方案:

定期进行FsImage和Edits的合并, 引发新的问题

  • 如果这个操作由NameNode节点完成,又会效率过低

解决方案: 引入一个新的节点SecondaryNamenode,专门用于FsImage和Edits的合并, 以及备份NameNode的FsImage数据

工作机制:

HDFS基础知识(个人总结)

1)第一阶段:NameNode启动

(1)第一次启动NameNode格式化后,创建Fsimage和Edits文件。

​ 如果不是第一次启动,直接加载编辑日志和镜像文件到内存。

(2)客户端对元数据进行增删改的请求。

(3)NameNode记录操作日志,更新滚动日志。

(4)NameNode在内存中对元数据进行增删改。

2)第二阶段:Secondary NameNode工作

(1)Secondary NameNode询问NameNode是否需要CheckPoint。直接带回NameNode是否检查结果。

(2)Secondary NameNode请求执行CheckPoint。

(3)NameNode滚动正在写的Edits日志。

(4)将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode。

(5)Secondary NameNode加载编辑日志和镜像文件到内存,并合并。

(6)生成新的镜像文件fsimage.chkpoint。

(7)拷贝fsimage.chkpoint到NameNode。

(8)NameNode将fsimage.chkpoint重新命名成fsimage。

SecondaryNamaNode得不到最新的edits_inprogress的文件

FsImage只会合并序号比它大的Edits文件,小于等于的不会合并

Fsimage和Edits解析

HDFS基础知识(个人总结)

​ VERSION里存储的namespace,clusterID等信息

FsImage和Edits的合并:

  1. 开关机时
  2. 1小时到了
  3. Edits记录的操作日志超过一百万

FsImage:

查看命令:

hdfs oiv -p 文件类型 -i镜像文件 -o 转换后文件输出路径
hdfs oiv -p XML -i fsimage_0000000000000000025 -o /opt/module/hadoop-3.1.3/fsimage.xml

得到结果: 里面有父子node关系的记录

Fsimage中没有记录块所对应DataNode,为什么?

因为在集群启动后,要求DataNode上报数据块信息,并间隔1小时后再次上报

Edits:

查看命令:

hdfs oev -p 文件类型 -i编辑日志 -o 转换后文件输出路径
hdfs oev -p XML -i edits_0000000000000000012-0000000000000000013 -o /opt/module/hadoop-3.1.3/edits.xml

CheckPoint时间设置

1)通常情况下,SecondaryNameNode每隔一小时执行一次。

hdfs-default.xml

<property>
	<name>dfs.namenode.checkpoint.period</name>
	<value>3600</value>
</property>

2)一分钟检查一次操作次数,当操作次数达到1百万时,SecondaryNameNode执行一次。

<property>
     <name>dfs.namenode.checkpoint.txns</name>
     <value>1000000</value>
<description>操作动作次数</description>
</property>
<property>
     <name>dfs.namenode.checkpoint.check.period</name>
     <value>60</value>
<description> 1分钟检查一次操作次数</description>
</property >

NameNode故障处理

可以采用如下两种方法恢复数据

1)将SecondaryNameNode中数据拷贝到NameNode存储数据的目录

  1. kill -9 NameNode进程

  2. 删除NameNode存储的数据(/opt/module/hadoop-3.1.3/data/tmp/dfs/name)

    1. 拷贝SecondaryNameNode中数据到原NameNode存储数据目录
     scp -r atguigu@hadoop104:/opt/module/hadoop-3.1.3/data/tmp/dfs/namesecondary/*   $HADOOP_HOME/data/tmp/dfs/name/
    
  3. 重新启动NameNode

    hdfs --daemon start namenode
    

2)使用-importCheckpoint选项启动NameNode守护进程,从而将SecondaryNameNode中数据拷贝到NameNode目录中

  1. 修改hdfs-site.xml中的

    <property>
        <name>dfs.namenode.name.dir</name>
        <value>/opt/module/hadoop-3.1.3/data/tmp/dfs/name</value>
    </property>
    
  2. kill -9 NameNode进程

  3. 删除NameNode存储的数据(/opt/module/hadoop-3.1.3/data/tmp/dfs/name)

  4. 如果SecondaryNameNode不和NameNode在一个主机节点上,需要将SecondaryNameNode存储数据的目录拷贝到NameNode存储数据的平级目录,并删除in_use.lock文件

     scp -r atguigu@hadoop104:/opt/module/hadoop-3.1.3/data/tmp/dfs/namesecondary $HADOOP_HOME/data/tmp/dfs
     rm -rf  $HADOOP_HOME/data/tmp/dfsnamesecondary/in_use.lock
    
  5. 导入检查点数据(等待一会ctrl+c结束掉)

bin/hdfs namenode -importCheckpoint
  6.  启动NameNode
hdfs --daemon start namenode

安全模式

安全模式期间可读不可写

(1)bin/hdfs dfsadmin -safemode get (功能描述:查看安全模式状态)

(2)bin/hdfs dfsadmin -safemode enter (功能描述:进入安全模式状态)

(3)bin/hdfs dfsadmin -safemode leave (功能描述:离开安全模式状态)

(4)bin/hdfs dfsadmin -safemode wait (功能描述: 等待安全模式状态)

DataNode

工作机制:

HDFS基础知识(个人总结)

(1)一个数据块在DataNode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据: 包括数据块的长度,块数据的校验和,以及时间戳。

(2)DataNode启动后向NameNode注册,通过后,周期性(6小时)的向NameNode上报所有的块信息

(3)心跳是每3秒一次,心跳返回结果带有 “NameNode给该DataNode的命令”, 如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟30秒没有收到某个DataNode的心跳,则认为该节点不可用。

(4)集群运行中可以安全加入和退出一些机器。

副本默认有3个, 原件也是副本

数据完整性

DataNode节点上的数据损坏了,避免读取损坏信息

解决办法:

  • 当DataNode读取Block的时候,它会计算CheckSum; 如果计算后的CheckSum,与Block创建时值不一样,说明Block已经损坏, Client读取其他DataNode上的Block。然后此节点再将此Block数据 向别的节点副本进行同步修复

  • DataNode在其文件创建后周期验证CheckSum

  • 校验: 奇偶校验&crc校验

掉线时

HDFS基础知识(个人总结)

hdfs-default.xml参数

<property>
    <name>dfs.namenode.heartbeat.recheck-interval</name>
    <value>300000</value>    <!--毫秒-->
</property>
<property>
    <name>dfs.heartbeat.interval</name>
    <value>3</value>     <!--秒-->
</property>
上一篇:HDFS04 HDFS的读写流程


下一篇:Java API访问HDFS集群(HA)