Hdfs原理
HDFS是Hadoop应用程序使用的主要分布式存储。全称是Hadoop Distributed File System。
带着问题学习
问题
1、主从同步
主从同步的方式是什么?
文件的一致性状态如何控制?
2、文件系统
可以修改文件吗?修改的方式是什么
3、数据分布
数据的分布体现了为数据计算服务这个原则吗?
分布的算法是什么?有没有按文件块存储?
4、扩容
横向扩容增加备份数有意义吗?
纵向扩容是不是挂载节点就可以了?
5、应用场景
适合网盘类应用吗?
6、部署
部署的时候hdfs往往是跟yarn、mapred一起配置的
hdfs可以独立启动,启动后再启动yarn等服务
7、checkpoit为什么拆分成两个文件?
是跟不支持随机读写有关系吗?
答案
1、主从同步
NN的主从需要ZK的支持。
NN Federation 模式下,NN之间是同等地位。
DN之间的同步可以理解为没有主从的,客户端选中的一个DN向其它DN同步。
2、文件系统
不可以修改文件,支持增删文件。
个人理解内存块较大修改比较耗费内存,最主要还是hdfs设计的场景就是为了读多写少的场景,数据应用与计算(可以变相理解为修改)
3、数据分布
机架感知(rack-aware)的策略。
副本系数是3,HDFS的存放策略是将一个副本存放在本地机架的节点上,一个副本放在同一机架的另一个节点上,最后一个副本放在不同机架的节点上。这种策略减少了机架间的数据传输,这就提高了写操作的效率。
读取的时候应用程序会判断与数据的距离:通过机架区分远近,HDFS会尽量让读取程序读取离它最近的副本。
4、扩容
DN扩容增加数据可用容量。
NN扩容增加并发度。
5、应用场景
适合读多写少,文本类存储(适合按顺序加载)。
不适合网盘类应用1、网盘会有大量的小文件 2、hdfs不支持修改
6、部署
7、checkpoint为什么拆分成两个文件?
checkpoint的目的是防止内存元数据丢失。内存dump到文件的方式来保证数据落地。
假设dump到一个文件上,当数据量比较大的时候dump的时间是无法忍受的,所以周期性的分成两个文件减少了dump时间,提高了数据落地的可靠性。
概念
-
block
block是最大的一个单位,它是最终存储于DataNode上的数据粒度。
由dfs.block.size参数决定,默认是64M;
注:这个参数由客户端配置决定; -
packet
packet是中等的一个单位,它是数据由DFSClient流向DataNode的粒度。
以dfs.write.packet.size参数为参考值,默认是64K;
注:这个参数为参考值,是指真正在进行数据传输时,会以它为基准进行调整,调整的原因是一个packet有特定的结构,调整的目标是这个packet的大小刚好包含结构中的所有成员,同时也保证写到DataNode后当前block的大小不超过设定值; -
chunk
chunk是最小的一个单位,它是DFSClient到DataNode数据传输中进行数据校验的粒度.
由io.bytes.per.checksum参数决定,默认是512B;
注:事实上一个chunk还包含4B的校验值,因而chunk写入packet时是516B;数据与检验值的比值为128:1,所以对于一个128M的block会有一个1M的校验文件与之对应; -
命名空间
文件系统命名空间:表示文件名称分组或者文件层级结构,文件系统文件目录的组织方式。
hdfs命名空间是树状结构。 -
元数据
元数据包含文件所有者,权限位,块位置,大小等文件基本信息。 -
fsImage
存储命名空间目录结构,元数据的文件。
NameNode启动时上次整个文件系统已经保存的快照。 -
editlog
它是在NameNode启动后,对文件系统的改动序列。
组件
架构图
客户端
功能
1、跟Namenode通信
写入文件前,客户端向Namenode请求可用的节点。
2、切分大文件
文件上传前,把大文件切分成多个block。
NameNode
元数据节点。
功能
1、元数据的管理
维护文件目录树、文件数据块索引、数据节点和数据块关系。
管理名称空间和数据块映射信息。
2、管理DataNode
接收DataNode的注册、心跳以及数据块信息。
3、处理客户端请求
客户端读写文件的第一步都要先访问Namenode
流程
启动流程
启动的时候会合并eidtlog文件到fsimage。
注意:编辑文件过大会导致合并时间过长而导致启动花费时间过长。
检查点导入流程
checkpoint节点从NN下载fsimage和edit文件并进行本地合并。
DataNode
数据存储节点
功能
1、数据存储
2、处理客户端实际读写
通过数据块的方式提供数据读写服务
3、跟Namenode通信
汇报存储信息给NN
4、datanode之间同步数据
在客户端写入数据时,客户端只与第一个datanode直接连接,而后是datanode之间串行的方式传递数据。
相比客户端一对多个datanode,datanode之间内网传输效率更高。
流程
客户端上传时各个datanode之间的同步流程
在客户端和第一个datanode建立连接开始流式的传输数据,这个datanode会一小部分一小部分(4K)的接收数据然后写入本地仓库,同时会把这些数据传输到第二个datanode,第二个datanode也同样一小部分一小部分的接收数据并写入本地仓库,同时传输给第三个datanode,依次类推。这样逐级调用和返回之后,待这个数据块传输完成客户端后告诉namenode数据块传输完成,这时候namenode才会更新元数据信息记录操作日志。
Secondary NameNode
它不是NameNode的备份节点,只是NameNode的一个助手节点,在社区内被认为是Checkpoint Node节点。
Secondary NameNode主要负责合并NameNode的editlog到FSImage文件。
这两个文件各有作用:fsimage保存了最新的元数据检查点,editlog记录增量的更新操作进行记录。
注意:在hadoop 2.x 版本,当启用 hdfs ha 时,将没有这一角色。
功能
1、合并fsimage和fsedits
本来editlog到FSImage文件的合并工作应该有NN负责,而SNN负责了该工作。
查询edits文件,如果有改动则更新到fsimage中,并把新的fsimage拷贝到NameNode中。
合并期间会生成新的edits.new文件,不阻塞客户端的更新操作。
dfs.namenode.checkpoint.period,指定连续两次检查点的最大时间间隔, 默认值是1小时。
dfs.namenode.checkpoint.txns, 定义了edits日志文件的最大事务数量,一旦超过这个值会导致强制执行检查点(即使没到检查点的最大时间间隔)。默认值是100万。
注意:hdfs 1.0中是通过文件大小阈值来判断是否执行检查点,而不是事务数。
2、备份NameNode
跟NN一样,SNN也存储了最新的检查点
流程
checkpoint流程
checkpoint节点从NN下载fsimage和edit文件并进行本地合并。
高可用
Datanode失败
客户端读写数据失败后,会向NN报告并重新请求可用的DN节点。
Metadata Disk Failure
元数据磁盘故障。
FsImage和EditLog是HDFS核心的数据。这些文件损坏可能导致HDFS实例无法正常运行。
可以把NameNode配置为支持维护FsImage和EditLog的多个副本。
注意:多副本的文件会造成每秒命名空间事务数降低,但是这种降低是可以接收的,元数据的更新并不是数据密集型的。
Namenode主备切换
Hadoop 2.0以后NN支持两个节点,如果活跃节点失败,备份节点会称为活跃节点并接管服务。
HDFS NameNode 高可用整体架构
故障转移组件
1、Active NameNode 和 Standby NameNode:
两台 NameNode 形成互备,一台处于 Active 状态,为主 NameNode,另外一台处于 Standby 状态,为备 NameNode,只有主 NameNode 才能对外提供读写服务。
使用的硬件配置相同。
2、共享存储系统
共享存储系统保存了 NameNode 在运行过程中所产生的 HDFS 的元数据,也就是editlog文件。
主备 NameNode 都对此有读写访问权限。
共享存储有两种方式:
支持NFS的远程文件管理器,以挂载的方式使用。
或者Quorum Journal Manager(QJM)。
3、主备切换控制器 ZKFailoverController:
ZKFailoverController 作为独立的进程运行,对 NameNode 的主备切换进行总体控制。
ZKFailoverController 能及时检测到 NameNode 的健康状况,在主 NameNode 故障时借助 Zookeeper 实现自动的主备选举和切换。 NameNode 目前也支持不依赖于 Zookeeper 的手动主备切换。
4、Zookeeper 集群:
为主备切换控制器提供主备选举支持。
5、DataNode 节点:
除了通过共享存储系统共享 HDFS 的元数据信息之外,主 NameNode 和备 NameNode 还需要共享 HDFS 的数据块和 DataNode 之间的映射关系。
DataNode 会同时向主 NameNode 和备 NameNode 上报数据块的位置信息。
NameNode 的主备切换
NameNode 主备切换主要由 ZKFailoverController、HealthMonitor 和 ActiveStandbyElector 这 3 个组件来协同实现:
1、ZKFailoverController 作为 NameNode 机器上一个独立的进程启动 (在 hdfs 启动脚本之中的进程名为 zkfc)
启动的时候会创建 HealthMonitor 和 ActiveStandbyElector 这两个主要的内部组件。
ZKFailoverController 在创建 HealthMonitor 和 ActiveStandbyElector 的同时,也会向 HealthMonitor 和 ActiveStandbyElector 注册相应的回调方法。
2、HealthMonitor 主要负责检测 NameNode 的健康状态
如果检测到 NameNode 的状态发生变化,会回调 ZKFailoverController 的相应方法进行自动的主备选举。
3、ActiveStandbyElector 主要负责完成自动的主备选举
内部封装了 Zookeeper 的处理逻辑,一旦 Zookeeper 主备选举完成,会回调 ZKFailoverController 的相应方法来进行 NameNode 的主备状态切换。
主备切换流程图
NameNode 实现主备切换的流程如上图所示,有以下几步:
1、HealthMonitor对NameNode健康监测
HealthMonitor 初始化完成之后会启动内部的线程来定时调用对应 NameNode 的 HAServiceProtocol RPC 接口的方法,对 NameNode 的健康状态进行检测。
2、检测到 NameNode 的健康状态发生变化,并回调
HealthMonitor 如果检测到 NameNode 的健康状态发生变化,会回调 ZKFailoverController 注册的相应方法进行处理。
3、进行主备选举
如果 ZKFailoverController 判断需要进行主备切换,会首先使用 ActiveStandbyElector 来进行自动的主备选举。
4、完成主备选举
ActiveStandbyElector 与 Zookeeper 进行交互完成自动的主备选举。
5、通知主备切换
ActiveStandbyElector 在主备选举完成后,会回调 ZKFailoverController 的相应方法来通知当前的 NameNode 成为主 NameNode 或备 NameNode。
6、执行主备切换
ZKFailoverController 调用对应 NameNode 的 HAServiceProtocol RPC 接口的方法将 NameNode 转换为 Active 状态或 Standby 状态。
流程
启动流程
读写流程
读流程【2】
写流程【2】
ack queue 与 data queue:
当所有datanode完成一个packet的写入之后,会返回给客户端一个ack,客户端收到后会从data queue中移出对应的packet。
三层buf:
chunk、packet及packet queue三个粒度从小到大可以看成三层缓存。【3】
扩容
HDFS Federation(NN联邦)
使用多个独立的NN/namespace,对NN的水平扩展。
NN之间是相互独立的。
DN被所有NN用作通用的存储,DN向所有NN注册。
每个NameNode分管一部分namespace,NN之间的数据是独立无备份的。
优点:
命名空间可伸缩性-会添加命名空间水平伸缩。
性能-文件系统吞吐量不受单个Namenode的限制。
隔离-单个Namenode在多用户环境中不提供隔离。可以将不同类别的应用程序和用户隔离到不同的名称空间。
DataNode扩容
两种方式,增加节点(横向扩容)或者在单个节点上增加磁盘(纵向扩容)。
扩容后可以使用命令让数据分配更均衡(负载均衡)
内存数据结构
NameNode
数据结构图
组件介绍:
Namespace:维护整个文件系统的目录树结构,及目录树上的状态变化;
BlocksManager:维护整个文件系统中与数据块相关的信息,及数据块的状态变化;
NetworkTopology:维护机架拓扑及DataNode信息,机架感知的基础;
LeaseManager:读写的互斥同步就是靠Lease实现,支持HDFS的Write-Once-Read-Many的核心数据结构;
CacheManager:Hadoop 2.3.0引入的集中式缓存新特性,支持集中式缓存的管理,实现memory-locality提升读性能;
SnapshotManager:Hadoop 2.1.0引入的Snapshot新特性,用于数据备份、回滚,以防止因用户误操作导致集群出现数据问题;
DelegationTokenSecretManager:管理HDFS的安全访问;
其他:临时数据信息、统计信息metrics等等。
以上组件都是常驻内存的。
内存管理组件
一下组件用来管理内存结构,维护文件系统的信息。
Namespace
INodeDirectory标识的是目录树中的目录,INodeFile标识的是目录树中的文件。二者均继承自公共信息INodeWithAdditionalFields和INode。INodeFile下包含了BlockInfo块数组信息。INodeDirectory下可以有INode数组,是典型的的树状文件系统结构。
Namespace 会定期 生成FsImage 文件。
BlockManager
管理BlockInfo信息:单个文件的块按序存放。
管理BlocksMap结构:每个块对应一个key存在于Map结构中。
Namespace与BlockManager之间通过INodeFile类让文件与块以Blocks数组的方式关联到一起。
BlocksMap中的块与INodeFile中的块:
前者会对后者的BlockInfo进行引用。
NetworkTopology
NameNode维护的整个机架拓扑NetworkTopology。
存储单元DatanodeStorageInfo对应的是不同的逻辑目录,也可以看成不同的物理存储介质。
这块数据与BlockManager管理的数据是有冗余的。
LeaseManager
Lease实际上是带时间的锁,其主要特点是排他性。客户端写文件时需要先申请一个Lease,一旦有客户端持有了某个文件的Lease,其他客户端就不可能再申请到该文件的Lease,这就保证了同一时刻对一个文件的写操作只能发生在一个客户端。
LeaseManager是Lease机制的核心,维护了文件与Lease、客户端与Lease的对应关系。
场景与内存数据结构设计
场景1:块的增删改查
通过命名空间找到文件,再找到具体的块,所以直接通过树状结构定位即可。
场景2:块的自我上报场景BlockReport
块的上报由DN发起,上报到NN。
直接通过块的id信息来定位块的元数据信息,所以使用了BlocksMap hash的方法来直接定位到块的元数据信息。
块汇报BlockReport有三种触发时机:DN启动首次全量汇报,周期性全量汇报(普通汇报),运行时更新汇报(增量汇报)。
参考
【1】漫画HDFS
【2】HDFS Read & Write Process
【3】HDFS写详解 block、packet与chunk
【4】HDFS Architecture
【5】深度剖析hdfs原理
【6】[Hadoop] HDFS 详解一(原理篇)
【7】HDFS为什么不支持随机写
【8】解读Secondary NameNode的功能
【9】Hadoop NameNode 高可用 (High Availability) 实现解析
【10】HDFS Federation
【11】简直不要太硬了!一文带你彻底理解文件系统
【12】namenode内存全景
【13】HDFS-BlockReport
【14】BlockManager解析:块的增删改与块汇报BlockReport
【15】深刻理解HDFS工作机制
【16】Hadoop分布式文件系统:架构和设计--数据复制
【17】Hadoop集群安装配置教程_Hadoop3.1.3