欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

HDFS笔记

程序员文章站 2022-06-13 16:36:08
HDFS 基于流数据模式访问和处理超大文件的需求而开发的。 低延时的数据访问 HDFS是为高吞吐数据传输设计的,因此可能牺牲延时HBase更适合低延时的数据访问。 大量小文件 文件的元数据保存在NameNode的内存中, 整个文件系统的文件数量会受限于NameNode的内存大小。 多方读写,需要任意 ......

hdfs

基于流数据模式访问处理超大文件的需求而开发的。

hdfs不适合的应用类型
  • 低延时的数据访问 

    hdfs是为高吞吐数据传输设计的,因此可能牺牲延时hbase更适合低延时的数据访问。

  • 大量小文件 

    文件的元数据保存在namenode的内存中, 整个文件系统的文件数量会受限于namenode的内存大小。 

  • 多方读写,需要任意的文件修改 

    hdfs采用追加的方式写入数据。不支持文件任意修改。不支持多个写入器(writer)。

相关概念

块(block)

hdfs文件系统的文件被分成块进行存储;hdfs被设计出来就是处理大文件的;

块默认大小:64m;小于一个块大小的文件不会占据整个块的空间;

好处:

  1. 它将超大文件分成众多块,分别存储在集群的各个机器上;

  2. 简化存储系统:块的大小固定,更利于管理,复制,备份,容错,并且便于元数据去统计、映射;

块的大小可以自行设置,但是必须是64m的整数倍(hdfs-site.xml)

<property>
    <name>dfs.block.size</name>
    <value>512000</value>
</property>

为什么块要设置这么大?

目的是:最小化寻址开销
比如:寻址时间需要10ms
1.块=1m,寻址64m文件,需要640ms
2.块=64m,需要10ms

块的设置不能太大,因为mapreduce任务是按块来处理的,块太大,任务少,作业效率就低了;

从用户角度看,存储一个文件在hdfs上,是通过namenode看到的

从内部角度看,文件被切分之后存储在多个datanode上,元数据存储在namenode;

块存储位置:在datanode目录下

每个块由两个文件组成:文件信息和meta校验信息

-rw-r--r-- 1 root root    355 9月  10 18:21 blk_1073741839
-rw-r--r-- 1 root root     11 9月  10 18:21 blk_1073741839_1015.meta

namenode

namenode、datanode分别承担master、worker的角色;

作用:
  1. 维护元数据信息(内存);即:管理文件的命名空间(哪个文件在哪个datanode)

  2. 维护文件系统树及整棵树内的所有文件和目录(磁盘);通过这两个文件来管理

    • 命名空间镜像文件(namespace image)

    • 编辑日志文件(edit log):只有4m

    (存放目录:hadoop/data/tmp/dfs/name/current/)

  3. 响应客户端请求(内存);

元数据形式:

存放目录:

# 目录     副本数   block数          每个block及副本位置,h为主机名
/test/a.log, 3, {blk_1,blk_2}, [{blk_1:[h1,h1,h2]}, {blk_2:[h0,h2,h4]}]
元数据记录过程:
  1. 首先记录在内存中,因为内存响应速度块;

  2. 然后追加到edit log文件中;

  3. 定期再将edit log文件内容,持久化到fsimage磁盘文件中;

checkpoint:(安全机制的一种考虑)

即:edit log文件持久化到fsimage中的操作;此动作是在secondary namenode中进行的;

secondary namenode一般运行在一台单独的机器上,因为合并需要大量的cpu和内存,并且会一直存储合并过的命名空间镜像,以免nn宕机;

  1. edit log文件快满了,nn通知sn,进行checkpoint;

  2. nn停止写入edit log,并生成新的new edit log文件,来继续记录日志;

  3. sn拿到old edit log和fsimage副本,并进行合并;

  4. 合并完成,再上传给nn,并删除old edit log;

HDFS笔记

datanode

即:工作节点;

作用:
  1. 执行具体的任务:存储文件块,被客户端和namenode调用;

  2. 通过心跳(heartbeat)定时向namenode发送所存储的文件的块信息

工作机制
  1. datanode启动,对本地磁盘扫描,上报block信息给namenode

  2. 通过心跳机制(heartbeat.interval=3s)与namenode保持联系,心跳的返回带有namenode命令信息;

  3. 如果namenode 10分钟(2* heartbeat.recheck.interval)没有收到datanode的心跳,则认为lost,复制其block到其他datanode

  4. 参考图片,看别人博客那里拿的,后来忘了记下链接了,侵删
  5.   HDFS笔记
数据的完整性
  1. 创建block的同时创建checksum,并周期性验证checksum值;

  2. 当datanode读取block的时候,会计算checksum值,与创建时的值对比;

  3. 如果值不一样,认为block损坏;会继续读取副本block

目录结构

datanode文件不需要格式化;

  1. datanode版本号:./data/tmp/dfs/data/current

    [root@hadoop1 current]# cat version 
    #tue sep 10 17:51:35 cst 2019
    storageid=ds-cc66bc73-0d4d-47a3-8727-69f323c7ae89   # 存储id
    clusterid=cid-39e1d84b-8dad-4578-8fdf-f2207368b981  # 集群id,全局唯一
    ctime=0 # 记录创建时间
    datanodeuuid=b5c00298-fbc8-4666-8f35-cc27cb7316b1   # 此node唯一标识码
    storagetype=data_node   # 存储类型
    layoutversion=-56   # 版本号
  2. 数据块block版本号:

    data/tmp/dfs/data/current/bp-1551134316-192.168.238.129-1568108968205/current

    [root@hadoop1 current]# cat version 
    #tue sep 10 17:51:35 cst 2019
    namespaceid=1573478873  # namenode通过此id区分不同的datanode
    ctime=0 #
    blockpoolid=bp-1551134316-192.168.238.129-1568108968205 # 唯一标识一个block pool
    layoutversion=-56   # 版本号
在集群中添加新的datanode

参考:

hdfs工作流程

读写流程

下面提到的filesystem是distributedfilesystem的一个实例对象

HDFS笔记

  1. client调用filesystem.open()方法:

    filesystem通过rpc与nn通信,nn返回该文件的部分block列表(需要的每一个块在哪个datanode);

    hadoop会自动算出client与各个datanode的距离,选出最短距离的datanode;

    读取到fsdatainputstream输入流中,并返回给客户端;

  2. client调用fsdatainputstream.read()方法:

    开始读取block,读取完一个block,进行checksum验证,如果出现错误,就从下一个有该拷贝的datanode中读取;

    每读取一个block,就关闭此datanode的输入流连接,并找到下一个最近的datanode继续读取;

    如果block列表读完了,总文件还没有结束,就继续从nn获取下一批block列表,重复调用read;

  3. client调用fsdatainputstream.close()方法;结束读取

HDFS笔记

  1. client调用filesystem的create()方法:

    filesystem向nn发出请求,在nn的namespace里面创建一个新的文件,但是并不关联任何datanode;

    nn检查文件是否已经存在、操作权限;如果检查通过,nn记录新文件信息,并在某一个datanode上创建数据块;

    nn返回一个fsdataoutputstream对象,用于client写入数据;

  2. client调用输出流的fsdataoutputstream.write()方法:

    开始写入数据,首先fsdataoutputstream会将数据分割成一个个包,放入数据队列;

    根据nn返回的副本数,以及datanode列表,先写入第一个datanode,此datanode会推送给下一个datanode,以此类推,直到副本数创建完毕;(每次都会向队列返回确认信息)

  3. client调用输出流的fsdataoutputstream.close()方法:

    完成写入之后,调用close方法,flush数据队列的数据包,nn返回成功信息;

hdfs基本命令

命令行键入:hadoop fs 即可查看命令

1.创建目录:(/ 为根目录)
hadoop fs -mkdir /test
hadoop fs -mkdir /test/input (前提test目录必须存在)
2.查看文件列表:(查看根目录的文件列表)
hadoop fs -ls /
3.上传文件到hdfs:
hadoop fs -put /home/whr/a.dat /test/input/a.dat 
# 复制:
hadoop fs -copyfromlocal -f /home/whr/a.dat /test/input/a.dat 
4.下载文件到本地:
hadoop fs -get /test/input/a.dat /home/whr/a.dat
# 复制:
hadoop fs -copytolocal -f /test/input/a.dat /home/whr/a.dat
5.查看hdfs 文件内容:
hadoop fs -cat /test/input/a.dat 
6.删除hdfs文件:
hadoop fs -rm /test/input/a.dat
7.修改hdfs文件的用户:用户组
hadoop fs -chown user_1:group_1 /a.txt
8.查看/test磁盘空间
hadoop fs -df /test
9.删除全部
hadoop fs -rm -r hdfs://whr-pc:9000/*