分布式文件系统HDFS
需要实现以下的一些目标:
1. 廉价的硬件设备
2. 流数据读写(和传统系统区别的地方,全部的数据一股脑的读取)
3. 大数据集(一个文件可能有时候大到好几个T)
4. 简单的文件模型(获取了批量处理的特性,只能追加,不可以修改)
5. 强大的跨平台特性(java开发的)
HDFS的一些局限性:
1. 不适合低延迟的数据访问(不能满足实时的处理需求)
2. 无法高效存储大量的小文件(小文件目录索引太大会让内存数据变大)
3. 不支持多用户写入及任意修改文件
HDFS块:
块要比普通文件大很多,面向大规模存储,为了减少寻址时候的开销。
优点:
1. 支持大规模文件的存储,将一个大文件切割,放到不同的机器上面
2. 简化系统的设计,块的大小是固定的,方便管理元数据
3. 方便数据的备份
NameNode | DataNode |
存储元数据(数据目录) | 存储文件内容 |
元数据保存在内存中 | |
NameNode的数据结构:
FsImage:用于维护文件系统树以及文件树中所有的文件和文件夹的元数据
(文件的复制等级,修改和访问时间,访问权限,块大小,组成文件的块)
EditLog:操作日志文件,记录了所有对文件的创建,删除,重命名等操作
NameNode的启动:
FsImage加载到内存,然后与EditLog合并,得到一个新的FsImage,然后创建一个空的EidtLog。这样做的原因是,FsImage太大,数据的修改会让系统变慢,所以文件的修改操作会在EditLog中执行,这样就快多了。
当EditLog变大怎么办?
SecondaryNameNode!!!!
(1) SecondaryNameNode会定期和NameNode通信,请求其停止使用EditLog文件,暂时将新 的操作写到一个新的edit.new上面,这个操作是瞬间完成的
(2) SecondaryNameNode通过HTTP GET从NameNode上获取FsImage和EditLog文件,下载到本地对应的目录下
(3) 将下载的FsImage载入内存,一条条执行EditLog文件中的更新,这个过程就是FsImage和EditLog的合并操作
(4) SecondaryNameNode执行完(3)之后,通过POST方式将新的FsImage文件发送给NameNode
(5)NameNode替换FsImage,edit.new替换EditLog
DataNode负责具体数据的存储:
每个数据节点的数据保存到本地的linux文件系统当中
通信协议:
所有的HDFS协议都是构建在TCP/IP协议上面的
客户端通过一个可配置的端口向名称节点发起TCP链接,使用客户端协议与名称节点交互
名称节点和数据节点之间使用数据节点协议交互
客户端与数据节点的交互是通过RPC(Remote Procedure Call)实现。
HDFS设置唯一的名称节点的局限性:
1. 命名空间的限制,所有的元数据保存在内存中,内存有上线,所以容纳的对象也有了上限
2. 性能的限制
3. 隔离的问题,命名空间只有一个
4. 集群的可用性,一旦故障怎么办(第二名称节点是冷备份,不是热备份,需要停止一段时间才能启动,在后来的HDFS 2.0进行了改善)
存储原理
冗余数据的保存:
1. 冗余会加快数据的传输速度,可以并行的访问
2. 容易检查数据错误
3. 保证数据的可靠性,一旦一个坏了,被系统周期性探测到会自动生成一个新的。
数据的存放:
第一个副本:如果是集群内部请求的,放在上传文件的数据节点,如果是集群外提交的放在一个磁盘不太满,cpu不太忙的节点
第二个副本:与第一个副本不同的机架上
第三个副本:第一个副本相同的机架上
第四个副本:随机
数据的读取:
读取数据的时候,从名称节点获取不同的副本存放位置的列表,列表包含了副本所在的数据节点,可以调用API来确定客户端和这个数据节点所属的机架ID,如果ID相同就选择这个副本,不同就随机找一个。
数据的错误与恢复:
名称节点出错:
在1.0当中需要停止用第二名称节点恢复(在2.0中已经不需要停机)
数据节点出错:
数据节点会定期向名称节点发送“心跳”信息。
发生故障,或者网络中断的时候,没有收到心跳节点的数据会被标记为“宕机”,节点上面所有的数据都会标记“不可读”,名称节点不会再给他们发送请求
一旦发现数据块备份数量小于冗余因子,就会启动数据冗余复制,生成新的副本
HDFS和其他发你不是文件系统最大区别是可以调整冗余数据的位置。
数据出错:
当磁盘损坏的时候,数据出错。
客户端在读取到数据的时候会使用md5和sha1校验码,去顶读取到正确的数据
如果校验出错将会客户端请求另一个数据节点读取该文件块,并且向名称节点报告文件快错误。
数据的读写过程
FileSystem 通用的文件系统抽象基类