理解HDFS
HDFS
HDFS (Hadoop Distributed FileSystem) 是 Hadoop 分布式文件系统,以流式数据访问模式来存储超大文件,运行与商业硬件集群上,管理网络中跨多台计算机存储的文件系统,是分布式计算中数据管理的的基础。
流式数据访问模式 : 指的是数据不是一次性获取过来,而是一点一点获取,处理流式数据也会一点一点处理。(全部接收在处理的话,延迟会很大)
(1)HDFS优点
- 高容错性:数据自动保存多个副本。它通过增加副本的形式,提高容错性,某一个副本丢失以后,它可以自动恢复
- 适合批处理
- 适合处理大数据
- 易于构建在廉价的机器上
- 流式数据访问
(2)HDFS不适合的领域
1.低延时数据访问
比如毫秒级的来存储数据,这是不行的,它做不到。它适合高吞吐率的场景,就是在某一时间内写入大量的数据。但是它在低延时的情况下是不行的,比如毫秒级以内读取数据,这样它是很难做到的。
HDFS是单Master的,所有的对文件的请求都要经过它,当请求多时,肯定会有延时。
2.小文件存储
存储大量小文件的话,它会占用 NameNode大量的内存来存储文件、目录和块信息(元信息)。这样是不可取的,因为NameNode的内存总是有限的。小文件存储的寻道时间会超过读取时间,它违反了 HDFS的设计目标。
3、并发写入、文件随机修改
一个文件只能有一个写,不允许多个线程同时写。仅支持数据 append(追加),不支持文件的随机修改。
(3)HDFS针对缺点的改善措施
- HDFS不适合低延时数据访问,可以使用缓存或者多Master节点设计降低Client的数据访问压力
- 存储小文件问题
1、利用SequenceFile、MapFile、Har等方式归档小文件,这个方法的原理就是把小文件归档起来管理,HBase就是基于此的。对于这种方法,如果想找回原来的小文件内容,那就必须得知道与归档文件的映射关系。
2、横向扩展,一个Hadoop集群能管理的小文件有限,那就把几个Hadoop集群拖在一个虚拟服务器后面,形成一个大的Hadoop集群。google也是这么干过的。
3、多Master设计,正在研发中的GFS II也要改为分布式多Master设计,还支持Master的Failover,而且Block大小改为1M,有意要调优处理小文件。(Alibaba DFS的设计,也是多Master设计,它把Metadata的映射存储和管理分开了,由多个Metadata存储节点和一个查询Master节点组成。
(4)HDFS概念
1、数据块(block)
每个磁盘都有默认的数据块大小,是磁盘进行读写的最小单位,构建与单个磁盘之上的文件系统通过磁盘数据块进行管理文件系统的块。类似于磁盘文件系统,HDFS中也有数据块的概念,HDFS文件系统也被划分为多个块,块作为独立单元。
HDFS数据块特点:HDFS中的块大小比文件系统的块大,一般默认64MB(Hadoop2中默认为128MB),而文件系统为几千字节。HDFS小于一个块大小的文件不会占据整个块的空间
2、namenode
HDFS集群上有两类节点:管理节点namenode和工作节点datanode。
4、secondarynamenode
secondarynamenode辅助后台程序,与namenode通信,以便定期保存namenode的元数据快照。(namenode的备份容错机制)
5、联邦HDFS
namenode在内存中保存着每个文件和每个数据块的引用关系(元数据信息),对于一个拥有大量数据的集群来说,namenode节点上的内存将成为限制横向扩展的瓶颈。在Hadoop2中,引入的联邦HDFS系统允许系统添加namenode实现扩展。每个namenode管理着系统文件命名空间的一部分(例如一个namenode管理着 /usr目录下的所有文件,另一个namenode管理着 /share目录下的所有文件)
在联邦环境下,每个namenode维护一个命名空间卷(包括数据源和文件的所有数据块的数据块池),命名空间卷之间是相互独立的,一个namenode的失效不会影响另外一个namenode,因此集群中的datanode需要注册每个namenode。
(6)HDFS结构
HDFS 采用的是Master/Slave架构存储数据,其中主要的组件:Client、namenode、datanode、secondarynamenode
Client:客户端
- 切分文件:文件上传 HDFS 的时候,Client 将文件切分成 一个一个的Block,然后进行存储
- 与 NameNode 交互,获取文件的位置信息
- 与 DataNode 交互,读取或者写入数据
- Client 提供一些命令来访问或者管理 HDFS,比如启动或者关闭HDFS
Namenode:Master节点(管理节点)
- 管理着HDFS文件系统的命名空间,维护整个文件系统的目录和文件(以命名空间镜像文件fsimage和编辑日志文件edits存在在本地)
- 记录每个数据库所在你节点的信息(不是永久存储,数据启动时由数据节点重新创建)
- 作为一个管理节点,监控datanode节点的运行状况
Datanode:Slave节点(工作节点)
- 文件存储的地方。
- 定期发送节点中所存储的节点信息给namenode,让namenode了解datanode是否健康运行(默认3s)
secondarynamenode:namenode辅助节点,做日志合并,备份namenode节点作用(并非热备份),secondarynamenode和namenode同时运行,一般来说都是运行在不同的机器上,namenode宕机, secondarynamenode并不能马上替换namenode提供服务。
- 辅助 NameNode,分担其工作量。
- 定期合并 fsimage和fsedits,并推送给NameNode。
- 在紧急情况下,可辅助恢复 NameNode。
(7)HDFS读写流程
Client端将数据写入到HDFS
- 使用HDFS提供的客户端Client, 向远程的Namenode发起RPC请求
- Namenode会检查要创建的文件是否已经存在,创建者是否有权限进行操作,成功则会为文件创建一个记录, 否则会让客户端抛出异常。Namenode创建一些元数据信息(datanode和数据块的引用信息)
- 当客户端开始写入文件的时候, 客户端会将文件切分成多个packets, 并在内部以数据队列“data queue( 数据队列) ”的形式管理这些packets, 并向Namenode申请blocks, 获取用来存储replications的合适的datanode列表, 列表的大小根据Namenode中replication的设定而定
- 客户端开始以pipeline( 管道) 的形式将packet写入所有的replications中。 客户端把packet以流的方式写入第一个datanode, 该datanode把该packet存储之后, 再将其传递给在此pipeline中的下一个datanode, 直到最后一个datanode, 这种写数据的方式呈流水线的形式
- 最后一个datanode成功存储之后会返回一个ack packet( 确认队列) , 在pipeline里传递至客户端, 在客户端的开发库内部维护着”ack queue”, 成功收到datanode返回的ack packet后会从”ack queue”移除相应的packet
- 如果传输过程中, 有某个datanode出现了故障, 那么当前的pipeline会被关闭, 出现故障的datanode会从当前的pipeline中移除, 剩余的block会继续剩下的datanode中继续以pipeline的形式传输, 同时Namenode会分配一个新的datanode, 保持replications设定的数量
- 客户端完成数据的写入后, 会对数据流调用close()方法, 关闭数据流
- 只要写入了dfs.replication.min的复本数( 默认为1),写操作就会成功, 并且这个块可以在集群中异步复制, 直到达到其目标复本数(replication的默认值为3),因为namenode已经知道文件由哪些块组成, 所以它在返回成功前只需要等待数据块进行最小量的复制
客户端读取HDFS数据
- 使用HDFS提供的客户端Client, 向远程的Namenode发起RPC请求
- Namenode会视情况返回文件的部分或者全部block列表, 对于每个block, Namenode都会返回有该block拷贝的DataNode地址。(返回block信息)
- 客户端Client会选取离客户端最近的DataNode来读取block; 如果客户端本身就是DataNode, 那么将从本地直接获取数据
- 读取完当前block的数据后, 关闭当前的DataNode链接, 并为读取下一个block寻找最佳的DataNode
- 当读完列表block后, 且文件读取还没有结束, 客户端会继续向Namenode获取下一批的block列表
- 读取完一个block都会进行checksum验证, 如果读取datanode时出现错误, 客户端会通知Namenode, 然后再从下一个拥有该block拷贝的datanode继续读
(8)Namenode结构
在了解Namenode结构之前,我们先看下存储在namenode节点上的元数据信息。
上图的元数据信息描述为有一个文件a.log,有三个备份,文件a.log分为两个数据块,数据块blk_1、blk_2,blk_1块在{h0,h1,h3}三个datanode 上,blk_2在{h0,h2,h4}三个datanode上
namenode在格式化之后,会在l临时文件夹(hadoop.tmp.dir 设置,默认在/tmp/hadoop-${user.name}
)目录下创建一个dfs目录,如下:
VERSION:是一个java properties文件,包含HDFS版本信息。
1、Namenode始终在内存中保存metedata,用于处理“读请求。当namenode启动的时候,加载fsimage文件到内存,并且将editslog文件逐条加载到内存。然后生成新的空的editslog和新的数据最全的fsimage文件。
2、当客户端进行读写操作时,首先将日志记录到editslog,然后将日志加载到内存。
3、成功后,editslog同步到文件系统。
4、Fsimage是映像文件,是内存中元数据的checkpoint点,是一个序列化文件,不能在硬盘上直接修改。
SecondaryNameNode日志合并(创建检查点)
在core-site.xml中配置fs.checkpoint.period 指定两次checkpoint的最大时间间隔,默认3600秒。fs.checkpoint.size 规定edits文件的最大值,一旦超过这个值则强制checkpoint,不管是否到达最大时间间隔。默认大小是64M。
(9)Datanode结构
DataNode职责:
提供真实文件数据的存储服务。
文件块(block):最基本的存储单位。默认64M。(Hadoop2默认128MB)
对于文件内容而言,一个文件的长度大小是size,那么从文件的0偏移开始,按照固定的大小,顺序对文件进行划分并编号,划分好的每一个块称一个Block。HDFS默认Block大小是64MB,以一个256MB文 件,共有256/64=4个Block.
不同于普通文件系统的是,HDFS中,如果一个文件小于一个数据块的大小,并不占用整个数据块存储空间。
在Hadoop集群中,默认是有三个副本(dfs.replication配置的是HDFS存储时的备份数量),HDFS创建副本的策略一般是:
- 第一块:本地
- 第二块:同一机架上的不同机器
- 第三块:同一机房的不同机架上的机器
如果备份的副本设置的更多,例如备份4个的话,可能第四块在不同机房的机器上...
datanode目录结构
VERSION文件和namenode的VERSION文件差不多
namespaceID是datanode首次访问namenode时获取的。
storageID,对每个datanode是唯一的,可以根据这个属性区分datanode
块文件的目录扩展
hdfs dfsadmin -safemode get //hdfs dfsadmin是hdfs管理员命令
2、退出安全模式
在执行修改和写入操作的时候,需要先退出安全模式
hdfs dfsadmin -safemode wait
#command to read or write
hdfs dfsadmin -safemode enter
4、 离开安全模式
hdfs dfsadmin -safemode leave
安全模式的下属性
属性名称 | 类型 | 默认值 | 说明 |
dfs.replication.min | int | 1 | 最小副本级别:成功执行写操作的最小副本数目 |
dfs.safemode.threshold.pct | float | 0.999 | 最小副本条件:在namenode退出安全模式之前,满足最小副本级别的比例。设置高于1,永远不会退出安全模式,设置为0或者过小,可能会使得namenode无法启动安全模式 |
dfs.safemode.extention | int | 30 000 | 在满足最小副本条件之后,namenode还需要处于安全模式的时间(毫秒),对于小集群来说,可以设置为0 |
(11)HDFS 命令行
HDFS有很多接口可以和HDFS交互(java API等),命令行是最简单的,也是入门学习需要了解的。
常用命令:
hadoop fs 和 hdfs dfs 都可以,但是推荐使用hdfs dfs
通过hadoop fs -help 查看
Usage: hadoop fs [generic options] [-appendToFile <localsrc> ... <dst>] [-cat [-ignoreCrc] <src> ...] [-checksum <src> ...] [-chgrp [-R] GROUP PATH...] [-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...] [-chown [-R] [OWNER][:[GROUP]] PATH...] [-copyFromLocal [-f] [-p] [-l] [-d] <localsrc> ... <dst>] [-copyToLocal [-f] [-p] [-ignoreCrc] [-crc] <src> ... <localdst>] [-count [-q] [-h] [-v] [-t [<storage type>]] [-u] [-x] <path> ...] [-cp [-f] [-p | -p[topax]] [-d] <src> ... <dst>] [-createSnapshot <snapshotDir> [<snapshotName>]] [-deleteSnapshot <snapshotDir> <snapshotName>] [-df [-h] [<path> ...]] [-du [-s] [-h] [-x] <path> ...] [-expunge] [-find <path> ... <expression> ...] [-get [-f] [-p] [-ignoreCrc] [-crc] <src> ... <localdst>] [-getfacl [-R] <path>] [-getfattr [-R] {-n name | -d} [-e en] <path>] [-getmerge [-nl] [-skip-empty-file] <src> <localdst>] [-help [cmd ...]] [-ls [-C] [-d] [-h] [-q] [-R] [-t] [-S] [-r] [-u] [<path> ...]] [-mkdir [-p] <path> ...] [-moveFromLocal <localsrc> ... <dst>] [-moveToLocal <src> <localdst>] [-mv <src> ... <dst>] [-put [-f] [-p] [-l] [-d] <localsrc> ... <dst>] [-renameSnapshot <snapshotDir> <oldName> <newName>] [-rm [-f] [-r|-R] [-skipTrash] [-safely] <src> ...] [-rmdir [--ignore-fail-on-non-empty] <dir> ...] [-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]] [-setfattr {-n name [-v value] | -x name} <path>] [-setrep [-R] [-w] <rep> <path> ...] [-stat [format] <path> ...] [-tail [-f] <file>] [-test -[defsz] <path>] [-text [-ignoreCrc] <src> ...] [-touchz <path> ...] [-truncate [-w] <length> <path> ...] [-usage [cmd ...]]
HDFS管理员命令
hdfs dfsadmin
可参照:https://blog.csdn.net/jjshouji/article/details/79087601
笔摘主要是对HDFS理论的上的了解,具体的操作还是需要多多实战操作...
参考:https://blog.csdn.net/dpengwang/article/details/79297435
《Hadoop权威指南》