这是我参与「第四届青训营 」笔记创作活动的的第8天
一、HDFS基本介绍
haddop技术体系
HDFS功能特性
- 分布式:受GFS启发,用Java实现的开源系统,没有实现完整的POSIX文件系统语义
- 容错:自动处理,规避多种错误场景,例如常见的网络错误、机器宕机等
- 高可用:一主多备模式实现元数据高可用,数据多副本实现用户数据的高可用
- 高吞吐:Client直接从DataNode读取用户数据,服务端支持海量client并发读写
- 可扩展:支持联邦集群模式,DataNode数量可达10w级别
- 廉价:只需要通用硬件,不需要定制昂贵的硬件设备
二、架构原理
1.HDFS组件
- 从某台机器访问HDFS,这台机器就是client,命令行就是client
- NameNode:中枢节点,最为复杂,元数据管理
- DataNode:所有用户的数据持久化存储在DataNode硬盘上
2.Client写流程
需要和NameNode交互,可以写到哪个节点上,NameNode会在自己的DataNode选择三块返回给他,拿到列表后,客户端和NameNode建立连接,开始传输数据。第三步横跨三个链接,虽然每个块有3个副本,SDK链接的时候是跟第一个DataNode去交互,第一个DataNode再把数据复制到第二个节点,第二个节点再发给第三个节点,叫做pipeline写。
3.Client读流程
先问NameNode块存储在哪些节点上,返回给客户端,客户端选择第一个节点去读,只需要和第一个数据块的进行交互就可以读到内容。
4.源数据节点NameNode
- 维护目录树:维护目录树的增删改查操作,保证所有修改都能持久化,以便机器掉电不会造成数据丢失或不一致
- 维护文件和数据块的关系:文件被切分成多个块,文件以数据块为单位进行多副本存放,这些块存放在DataNode上,由NameNode来维护
- 维护文件快存放节点信息:通过接受DataNode的心跳汇报信息,维护集群节点的拓扑结构和每个文件块所有副本所在的DataNode等
- 分配新文件存放节点:Client创建新的文件时候,需要有NameNode来确定分配目标DataNode
5.数据节点DataNode
- 数据块存取:DataNode需要高效实现对数据块在硬盘上的存取
- 心跳汇报:把存放在本机的数据块列表发送给NameNode,以便NameNode能维护数据块的位置信息,同时让NameNode确定该节点处于正常存活状态
- 副本复制:1.数据写入时Pipeline IO操作 2.机器故障时补全副本
三、HDFS关键设计
分布式存储系统基本概念
- 容错能力:能够处理绝大部分异常场景,例如服务器宕机、网络异常、磁盘故障、网络超时等
- 一致性模型:为了实现容错,数据必须多副本存放,一致性要解决的问题时如何保障这不同机器多个副本的内容都是一致的
- 可扩展性:分布式存储系统需要具备横向扩张scale-out的能力,容量不够,可以通过加节点做一些扩展等
- 节点体系:常见的有主从模式、对等模式等,不管哪种模式,高可用是必须的功能
- 数据防止:系统是由多个节点组成,数据是多个副本存放时,需要考虑数据存放的策略
- 单机存储引擎:在绝大部分存储系统中,数据都是需要落盘持久化,单机引擎需要解决的时根据兄特点,如何高效的存取硬盘数据
1.NameNode目录树维护
fsimage
- 文件系统目录树
- 完整的存放在内存中
- 定时存放在硬盘上
- 修改时只会修改内存中的目录树
Editlog
- 目录树的修改日志,修改时实时的刷到硬盘上,掉电时可以通过Editlog构建出完整一致的目录树
- client更新目录树需要持久化Editlog后才能表示更新成功
- Editlog可循放在本地文件系统,也可存放在专用系统上
- NameNode HA方案一个关键点就是如何实现EditLog共享
2.NameNode数据放置
数据块信息维护
- 目录树保存每个文件的块id
- NameNode维护了每个数据块所在的节点信息
- NameNode根据DataNode回报的信息动态维护位置信息
- NameNode不会持久化数据块位置信息,启动时DataNode告诉NameNode我这里有这些块,NameNoede再去在内存中构建map信息
第二个更合理,第一个挂了之后所有数据都丢失,第二个挂了一个节点,还有两个副本可以读。
数据放置策略
- 新数据存放到哪写节点
- 数据均衡需要怎么合理搬迁数据
- 3个副本怎么合理放置
3.DataNode
数据块的硬盘存放
- 文件在NameNode已分割成block
- DataNode以block为单位对数据进行存取
这个块在DataNode上是怎么存放的
第一个绿框是硬盘盘符,第二三个绿色框是他的blockid 是通过某种哈希算法算出来的,红色的第一个框是他存的本身内容,第二个是元数据,描述块的校验码之类的。
启动扫盘
- DataNode需要知道本机存放了哪些数据块
- 启动时把本机硬盘上的数据块列表加载在内存中
4.HDFS写异常处理:Lease Recovery
情景:文件写了一半,client自己挂掉了。可能产生的问题:没有ACK,副本不一致;Lease无法释放
租约:Client要修改一个文件时,需要通过NameNode上锁,这个锁就是租约(Lease)
解决方法:Lease Recovery(租约恢复) 副本不一致,比较三个副本大小长度,选择最小的作为最终版本去更新,返回给NameNode作为最终结果 租约无法释放,客户端拿到租约需要定期续租,挂掉了无法续约,客户端就会判断他死了,如果有别的进程想拿租约,就会把原来的踢掉。
5.HDFS写异常处理:Pipeline Recovery
情景:文件写入过程中,DataNode侧出现异常挂掉了,服务端出错了 异常出现的时机:
- 创建连接时
- 数据传输时
- complete阶段
解决方法: Pipeline Recovery
6.Client读异常处理
情景:读取文件的过程,DataNode侧出现异常挂掉了
解决方法:节点Failover,和第二个节点连接读取副本
增强情景:节点半死不过,读取很慢(怎么检测是慢?)(客户端本身的网络环境导致的慢会导致无谓的切换)
7.旁路系统
Balancer:均衡DataNode的容量
Mover:确保副本放置符合策略要求
8.控制面建设
可观测性设施
- 指标埋点
- 数据采集
- 访问日志
- 数据分析
运维体系建设
- 运维操作需要平台化
- NameNode操作复杂
- DataNode机器规模庞大
- 组件控制面API