理论知识点
存储模型
- 文件线性按字节切割成block,具有offset,id(所有的文件都可以看作字节数组)
- 文件与文件的block大小可以不一样
- 一个文件除了最后一个block,其他的block大小一致
- block的大小根据硬件的I/O特性调整(1.X默认是64M,2.X默认是128M)
- block被分散存放到集群的节点中,具有location
- block具有副本,没有主从概念,副本不能出现在同一节点(满足可靠性)
- 文件上传可以指定block大小和副本数量,上传后只能修改副本数量
- 不支持修改,支持追加数据
架构设计
- HDFS是一个主从架构
- 由一个NameNode和一些DateNode组成
- 面向文件包含:文件数据(data)和文件元数据(metadata)
- NameNode负责存储和管理元数据,并维护了一个层次型的文件目录树(不是物理的磁盘)
- DataNode负责存储文件数据,其中文件数据包括原始数据和数据的校验和。
- DateNode和NameNode维持心跳(默认是3秒),并汇报持有的block信息
- clint和NameNode交互文件元数据和DateNode交互文件的block数据
角色功能
角色即jvm进程
NameNode
- 完全基于内存存储文件元数据、目录结构、文件block映射
- 需要提供持久化方案保证数据的可靠性
所有基于内存存储的,都需要提供持久化方案。分两种,其一就是记录变换,记录每一步都干了什么,在HDFS中称之为Editlog,完整性比较好,加载恢复数据慢且占空间;第二种则是快照,也就是把当前时间点的内存数据记录下来,HDFS称之为FsImage,恢复速度快但是因为是间隔的,容易丢失数据。 - 提供副本放置策咯
DataNode
- 基于本地磁盘存储block(文件的形式)
- 保存block的校验和数据保证block可靠性
- 与NameNode保持心跳,汇报block列表状态
元数据持久化
在持久化的时候,文件属性会持久化,但是文件的每一个block不会持久化。因为如果启动的时候有的DateNode节点可能宕机,造成clint读取失败。
- 任何堆文件系统元数据产生修改的操作,NameNode都会使用一种称为EditLog的事务日志记录下来
- 使用FsImage存储内存所有的元数据状态
- 使用本地磁盘保存EditLog和FsImage
- EditLog具有完整性,数据丢失少,但是恢复速度慢、并有体积膨胀的风险
- FsImage具有恢复速度快,体积与内存数据相当,但不能实时保存,数据丢失多
- NameNode使用了FsImage+EditLog整合的方案
例如:系统当前磁盘里记录了8点钟的快照(FsImage)也记录了8-9点钟的各种操作(Editlog),那么HDFS想要在9点钟持久化,只需要在8点钟的FsImage上进行增量操作(Editlog),写回磁盘里。
安全模式
- HDFS搭建时会格式化,格式化操作会产生一个空的FsImage
- 当NmaeNode启动时,它从硬盘钟读取EditLog和FsImage
- 将所有EditLog中的事务作用在内存中的FsImage上
- 并将这个新版本的FsImage从内存中保存到本地磁盘上
- 然后删除旧的EditLog,因为这个旧的EditLog的事务都已经作用在FsImage上了
- NmaeNode启动后会进入安全模式,在安全模式中,NameNode不会进行数据块的复制。
- NameNode从所有的DateNode接收心跳信号和块状态报告,每当NameNode检测确认某个数据块的副本数达到最小值,那么该数据块会被认为是安全的。
- 在一定百分比的数据块被NameNode检测确认安全后,加上额外的30秒,NameNode将退出安全模式
- 剩下没确定的数据块的副本没有达到指定数目,会复制到其他DateNode上
副本放置策略
- 第一个副本:放置在上传文件的DataNode;如果是集群外提交,则随机挑选一台磁盘不太满,cpu不太忙的节点
- 第二个副本:放置在与第一个副本不同的机架节点上
- 第三个副本:放置在与第二个副本相同的机架节点上
- 更多的副本:随机节点
读写流程
安全策略
HDFS中的高可用
单点故障
- 高可用方案:HA(High Availiable)
- 多个NameNode,主备切换,主
压力过大,内存受限
- 联邦机制:Federation(元数据分片)
- 多个NameNode,管理不同的元数据
联邦机制
- 这些NameNode直接相互独立,各自分工管理自己的区域,且不需要互相协调,一个namenode挂掉了不会影响其他的NameNode
- Datanode被用作通用的数据存储设备,每个datanode要向集群中所有的namenode注册,且周期性的向所有NameNode发送心跳和报告,并执行来自所有NameNode的命令
- 一个Block Pool由属于同一个NameSpace的数据块组成,每个DataNode可能会存储集群中所有Block Pool数据块,Block Pool之间不会交流,各自管理
- NameNode和Block Pool一起被称作NameNode volume,它是管理的基本单位,当一个NameNode被删除后,所有DataNode上与其对应的Block Pool也会被删除。当集群升级时,每个NameNode volume作为一个基本单元进行升级