基本概念
Block
1.Block是HDFS中数据存储的基本形式,即在HDFS中,所有数据都是以Block形式来存储
2.从Hadoop2.x开始,如果不指定,那么Block的默认大小是134217728B(128M)。可以通过dfs.blocksize
来修改,单位是字节
3.如果一个文件不足一个Block的默认大小,那么这个文件是多大,所对应的Block就是多大。例如一个文件是50M,上传到HDFS上之后对应的Block就是50M
4.HDFS会为每一个Block分配一个递增的编号,称之为BlockId,从1073741825开始递增
5.Block的意义
①能够存储超大文件
②能够进行快速备份
6.经过经验计算,当数据往磁盘上写的时候,寻址时间/传出时间=1%,效率是最高的。实际过程中,服务器基本上使用的是机械磁盘,市面上大部分机械磁盘的寻址时间在10ms左右,也就是意味传输时间=10ms/0.01=1000ms=1s。市面上大部分机械磁盘的读写速度是100M/s150M/s,因此希望数据块大小是100M150M
NameNode
1.NameNode是HDFS的主/核心节点,在Hadoop1.x中,NameNode只能有一个,容易产生单点故 障;在Hadoop2.x中,允许存在2个NameNode;在Hadoop3.x中,不再限制NameNode的数量
2.NameNode负责对外接受请求,对内负责记录元数据(metadata)以及管理DataNode
3.元数据是用于描述数据的数据,HDFS中的元数据会包含三十几项属性,例如:
1.上传的文件名
2.文件的大小
3.上传的用户和用于组
4.文件的权限
5.Block的大小
6.文件和BlockID的映射关系
7.Block和DataNode的映射关系
8.副本数量
-
NameNode会将元数据维系在内存以及磁盘中
- 维系在内存中的目的是为了查询快
- 维系在磁盘中的目的是为了持久化
-
元数据在磁盘上的存储位置由属性dfs.namenode.dir来决定,如果不指定,那么这个属性的默认值是file://${hadoop.tmp.dir}/dfs/name
-
和元数据相关的文件
- edits文件:写操作文件。用于记录NameNode接受到的写操作的
- fsimage文件:元数据映像文件。用于记录元数据的,但是需要注意的是,fsimage文件中的元数据和内存中的元数据不同步
-
当NameNode接受到写操作之后,试图将这个命令记录到edits_inprogress文件中,如果记录成功,则修改内存中的元数据,修改完成之后,会给客户端一个ACK信号。注意,此时fsimage文件中的元数据并没有发生变化
-
当达到指定条件的时候,edits_inprogress文件会产生滚动,滚动生成一个edits文件,同时会产生一个新的edits_inprogress,新的写操作会记录到新的edits_inprogress文件。滚动生成edits文件之后,会将edits文件中的命令一一取出,按照命令更新fsimage文件中的元数据
-
edits_inprogress文件的滚动条件
- 空间:当edits_inprogress文件达到指定大小(默认是64M,则通过属性
dfs.namenode.checkpoint.size
来指定)的时候,会产生滚动生成edits文件 - 时间:当距离上一次滚动达到指定时间间隔(默认是3600s,则通过属性
dfs.namenode.checkpoint.period
来指定),那么edits_inprogress文件也会产生滚动 - 重启:当NameNode被重启的时候,edits_inprogress自动进行滚动
- 强制:通过命令来强制
hdfs dfsadmin -rollEdits
来强制edits_inprogress文件的滚动
- 空间:当edits_inprogress文件达到指定大小(默认是64M,则通过属性
-
HDFS会将每一个写操作看作是一个事物,分配一个递增的事物id,简称为txid
-
edits文件的查看命令
hdfs oev -i edits_0000000000000000035-000000000000000042 -o edits.xml
-
HDFS会将开始记录日志以及结束记录日志也看作是一个写操作,也会分配一个事物id。所以edits文件都是以OP_START_LOG_SEGMENT开头;edits文件是以OP_END_LOG_SEGMENT来作为结尾
-
上传操作
- OP_ADD:在HDFS的对应目录下生成文件名.__COPYING__文件
- OP_ALLOCATE_BLOCK_ID:分配BlockID
- OP_SET_GENSTAMP_V2:设置时间戳编号
- OP_ADD_BLOCK:上传对应的数据块
- OP_CLOSE:关流
- OP_RENAME_OLD:重命名
-
HDFS中,一但上传就无法修改
-
fsimages文件的查看命令
hdfs oiv -id fsimage_00000000000000000016 -o f.xml -p XML
-
每一个fsimage文件都对应一个md5文件,md5文件的作用是对fsimage文件进行校验
-
HDFS第一次启动1min之后,会自动触发一次edits_inprogress文件的滚动
-
NameNode通过心跳机制管理DataNode。DataNoda定时(默认是3s,通过
dfs.heartbeat.interval
来修改,单位是秒)会给NameNode来发送心跳信号,如果超过一定时间,NameNode没有收到DataNode的心跳,才会认为这个DataNode已经lost(丢失),那么此时NameNode会将这个DataNode上的数据复制一份放到其他节点上,来保证整个集群中的副本数量 -
心跳的超时时间由属性
dfs.namenode.heartbeat.recheck-interval
来影响,默认值是300000,单位是毫秒,即5min。心跳的超时时间=2*dfs.namenode.heartbeat.recheck-interval
+10*dfs.heartbeat.interval
=2\5min+10*3s=10min30s,即为210心跳未收到判断为丢失 -
心跳信号
- clusterid - 集群编号
- 当NameNode被格式化(
hdfs namenode -format
)的时候,会自动计算产生一个clusterid。每一次格式化都会重新计算生成一个新的clusterid - DataNode会第一次给NameNode发送心跳,此时NameNode会在心跳响应中将clusterid返回给DataNode
- DataNode收到clusterid之后,此后给NameNode的每一次请求中都必须携带clusterid
- NameNode收到DataNode的请求后,会先校验clusterid是否一致。如果一致,则处理这个请求;如果不一致,则启动之后会发现缺少NameNode或者DataNode
- 当NameNode被格式化(
- 当前DataNode的状态(预服役、服役、预退役)
- DataNode的Block信息
- clusterid - 集群编号
-
安全模式(safe mode)
- 当NameNode被重新启动的时候,会自动的进入安全模式
- 在安全模式中,NameNode会触发edits_inprogress文件的滚动,滚动完成之后会更新fsimage文件。更新完fsimage文件之后,NameNode会将元数据加载到内存中。加载完成之后,NameNode会等待DataNode的心跳
- 如果NameNode没有收到DataNode的心跳,说明NameNode在宕机重启期间,DataNode也产生了故障,此时NameNode会试图将这个DataNode上的数据备份到其他节点上以保证集群中副本的数量
- 如果NameNode收到了DataNode的心跳,会对心跳信息进行检验(clusterid检验,还会对这个节点上的Block信息进行校验),如果校验失败,则NameNode会试图恢复这个数据,恢复完成之后会再次校验,直到校验成功为止,才会自动退出安全模式
-
在安全模式中,HDFS只能读不能写
-
如果HDFS集群在合理时间内没有退出安全模式,也就是某文件恢复不了,副本全部丢失,就意味着产生了不可逆的数据丢失
-
安全模式
命令 解释 hdfs dfsadmin -safemode enter
进入安全模式 hdfs dfsadmin -safemode leave
退出安全模式 hdfs dfsadmin -safemode get
获取安全模式的状态
DataNode
1.DataNode作为HDFS的从节点,负责存储数据。数据是以Block形式存储在磁盘上
2.Block在DataNode上的存储位置由属性dfs.datanode.data.dir
决定,如果不指定,默认值是file://${hadoop.tmp.dir}/dfs/data
3.DataNode会为每一个Block产生一个校验文件blk_xxxx_xxx.meta
4.DataNode的状态:预服役、服役、预退役、退役、丢失(lost)
SecondaryNameNode
- SecondaryNameNode并不是NameNode的备份,而是用于辅助NameNode完成edits_inprogress文件的滚动和fsimage文件的更新
- 如果是集群中,存在SecondaryNameNode,则edits_inprogress文件的滚动和fsimage文件的更新就是SecondaryNameNode;如果没有SecondaryNameNode,则上诉操作由NameNode自己完成
- 到目前为止,HDFS集群支持两种结构
- 1个NameNode+1个SecondaryNameNode+n个DataNode
- n个NameNode(1个Active NameNode + n个Standby NameNode)+n个DataNode
- 实际开发中,考虑到NameNode的核心作用,那么必须得对NameNode进行备份,因此一般采用的是上诉第二种结构
副本放置策略
- 默认情况下,HDFS中没有开启机架感知策略,此时也不会开启副本放置策略。此时,数据的多个副本是放在相对空闲的节点上
- 如果开启了机架感知策略,此时也会伴随自动开启副本放置策略
- 第一个副本
- 集群内部上传:谁上传就放谁身上
- 集群外部上传:谁空闲就放谁身上
- 第二个副本
- Hadoop2.7以前:第二个副本是放在和第一个副本不同机架的节点上
- Hadoop2.7开始:第二个副本是放在和第一个副本相同机架的节点上
- 第三个副本
- Hadoop2.7以前:第三个副本是放在和第二个副本相同机架的节点上
- Hadoop2.7开始:第三个副本是放在和第二个副本不同机架的节点上
- 更多副本:谁空闲就放在谁身上
- 第一个副本
机架感知策略
-
机架感知策略实际上通过脚本来进行映射。可以定义Shell/Python等脚本,在脚本中来定义一个Map,键是服务器的IP或者主机名,值表示机架。只要值一致,键对应的服务器就表示放在同一个机架上,例如
rack = { "hadoop01":"r1", "hadoop02":"r1", "hadoop03":"r2", "hadoop04":"r2" }
-
在HDFS中,如果不指定,默认是不开启机架感知策略的。如果需要开启机架感知策略,需要hadoop-site.xml中配置
<property> <name>topology.script.file.name</name> <value>脚本的路径</value> </property>
3.机架感知策略中的机架实际上指的不是物理机架而是逻辑机架,那么也就意味着可以将好多个物理机架上的节点映射到同一个逻辑机架上
命令
命令 解释 hadoop fs -put /a.txt /
或者hadoop fs -copyFromLocal /a.txt
上传文件 hadoop fs -get /a.txt /home
/或者hadoop fs -copyToLocal /a.txt /home/
下载文件 hadoop -mkdir /test
创建目录 hadoop fs -cp /a.txt /test
复制文件 hadoop fs -mv /nc.rpm /home
剪切/重命名 hadoop fs -rm /a.txt
删除文件 hadoop fs -rmdir /log
删除目录 hadoop fs -rm -r /home
递归删除 hadoop fs -checksum /test/a.txt
计算校验和 hadoop fs -chgrp tedu /test
改变用户组 hadoop fs -chmod 777 /test
改变权限 hadoop fs -chown tom /test
改变用户 hadoop fs -df /test
查看HDFS磁盘信息 回收站
1.在Hadoop中,回收站默认是不开启的
2.开启回收站(core-site.xml)
<!--指定文件在回收站中的存储实际,单位是min--> <!--如果超出指定时间没有将文件从回收站移出来,那么这个文件就会被清理--> <property> <names>fs.trash.interval</names> <value>1440</value> </property>
-
如果需要将文件从回收站中还原,那么使用
hadoop fs -mv /user/root/.Trash/Current/c.xml /c.xml
流程
删除流程
-
客户端发起RPC请求到NameNode,请求删除指定文件
-
NameNode在收到请求之后,会进行校验
-
校验知否有删除权限 -
AccessControlException
目录和文件权限代表含义
目录/log 解释 文件a.log 解释 r 获取子目录和子文件 --> ls /log r 获取文件内容 -->cat a.long w 创建/删除/修改子目录和子文件–> mkdir rm touch等 w 修改文件内容–> vi vim等 x 打开目录–> cd x 可执行命令 --> sh bash等 -
校验是否有指定文件 -
FileNotFoundException
-
-
如果校验失败,则抛出异常;如果校验成功,NameNode会将删除命令先记录到edits_inprogress文件中,记录成功之后,NameNode会修改内存中的元数据,修改完成之后,NameNode会给客户端返回一个ACK信号表示删除成功。注意,此时文件并没有从HDFS上移除,而仅仅是修改了元数据
-
NameNode会在等待DataNode的心跳,在收到心跳之后,NameNode在心跳响应中要求DataNode删除对应的Block
-
DataNode在收到心跳响应之后,会去磁盘删除对应的Block。注意,此时文件才真正从HDFS上移除
写/上传流程
- 客户端发起RPC请求到NameNode,请求上传文件
- NameNode在收到请求之后,会进行校验
- 校验是否有写入权限 -
AccessControlException
- 校验是否有同名文件 -
FileAlreadyExistsException
- 校验是否有写入权限 -
- 如果校验失败,则抛出异常;如果校验成功,NameNode会给客户端返回一个ACK信号表示允许上传。此时,文件还没有真正上传!
- 当客户端收到信号之后,再次发起请求到NameNode,请求第一个Block的请求位置
- NameNode在收到请求之后,会将存储位置(DataNode的主机名或者IP)放到队列中返回给客户端。默认情况下,NameNode会返回3个位置 - 副本数量默认为3
- 客户端收到队列之后,会将地址从队列中全部取出,然后从中选择一个较近(网络拓扑距离)的节点将这个Block的第一个副本写入
- 第一个副本写完之后,第一个副本所在节点会通过pipeline(管道,本质上是封装了NIO中的Channel)将第二个副本写入对应的节点。第二个副本写完之后,也会通过pipeline将第三个副本写入对应的节点,依此类推,直到将这个Block的所有副本都写完
- 当这个Block的最后一个副本写完之后,会给上一个副本所在节点返回一个ACK信号表示写入成功,依次前往返回,直到返回给第一个副本所在的节点。第一个副本所在节点收到ACK之后,会给客户端返回一个ACK表示写入成功
- 客户端在收到ACK之后,会再次给NameNode发送请求,请求获取下一个Blcok的存储位置,重复5、6、7、8四个步骤,直到所有Block全部写完
- 当所有的Block全部写完之后,客户端会给NameNode发送一个结束信号。NameNode收到信号之后,会关闭文件。文件一旦关闭就无法修改
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RDQfOf6j-1646391645832)(./images/HDFS写流程.png)]
读/下载流程
- 客户端发起RPC请求到NameNode,请求读取指定文件
- NameNode收到请求之后,会进行校验
- 校验是否有读取权限 - AccessControlException
- 校验是否有指定文件 - FileNotFoundException
- 如果校验失败,则抛出异常;如果校验成功,则NameNode会给客户端返回一个ACK信号表示允许下载
- 当客户端收到信号之后,会再次发起请求,请求获取第一个Block的存储位置
- NameNode收到请求之后,会将这个Block的存储位置放在队列中返回给客户端
- 客户端收到队列之后,会将Block的存储位置从队列中全部取出,之后会选取一个较近的节点来读取这个Block
- 客户端读取完这个Block之后,会对这个Block进行cheksum(校验和)的校验。如果校验失败,客户端会从剩余的位置中重新选取地址重新校验;如果校验成功,则客户端会给NameNode发送请求,请求获取下一个Block的存储地址,重复5、6、7三个步骤,直到所有的Block全部读完
- 客户端会给NameNode发送一个结束信号,NameNode收到信号之后会关闭文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A15l5JCe-1646391645834)(./images/HDFS读流程.png)]
其他
特点
- 能够存储超大文件。HDFS会对文件进行切块,因此HDFS的存储能力由集群规模来决定
- 能够快速的应对和检测故障。HDFS通过心跳机制来管理集群,可以通过心跳机制来快速锁定出现故障的节点
- 能够在相对廉价的机器上进行横向扩展
- 提供了流试访问模型。HDFS允许以IO流形式来操作数据,减少学习成本
- 不建议存储小文件。HDFS只是不建议存储小文件,不是不能存储。如果存储大量小文件会产生大量的元数据,导致查询效率变低。一般对小文件的定义是文件的大小<Block*0.8,所以一般默认是100M
- 不支持低延迟响应。HDFS不支持在毫秒或者亚秒级别内进行响应,一般是在秒级甚至分钟级别的响应 - 牺牲了响应速度来提高吞吐量
- 提供了简化的一致性模型。允许一次写入多次读取,不允许修改,允许追加写入
- 不支持事务或者弱事务。在样本量足够大的情况下,不允许产生容错误差