目录
1. HDFS储存模型
- 1. HDFS储存模型
- 2. 角色功能
- 3. Namenode元数据持久化
- 4. SecondNameNode
- 5. 安全模式
- 6. Block的放置策略
- 7. HDFS写流程
- 8. HDFS读流程
- 文件按线性切割成block,每个block具有offset和id
- 文件与文件的block大小可以不一样
- 一个文件除最后一个block,其它block的大小都一样
- block的大小根据硬件的I/O特性调整
- block被分散到集群的各个节点中,具有location
- block具有副本replication,没有主从概念,副本不能出现在同一个节点
- 副本是满足可靠性和性能的关键
- 文件上传可以指定block大小和副本数,上传后只能修改副本数
- 一次写入多次读取,不支持修改,只支持追加数据
Namenode
- 完全基于内存储存文件元数据、目录结构、文件block的映射
- 需要持久化方案保证数据可靠性
- 提供副本放置策略
DataNode
- 基于本地磁盘储存block
- 保存block的校验,保证block的可靠性
- 与Namenode保持心跳,汇报block状态列表
对内存中的数据进行持久化有两种方案:
方案一:
- 以log的形式,保持每一次数据变更的记录,比如mkdir /a、put text.txt /a等
- 优点:完整性好;缺点:恢复数据慢
方案二:
- 对内存中的数据,定期进行snapshot,保存到磁盘
- 优点:恢复数据快;缺点:容易丢失数据
HDFS结合了两种方案的优点:
- 任何对文件系统元数据产生修改的操作,Namenode都会保存到EditLog事务日志中
- 使用FsImage储存内存所有的元数据状态
- 滚动将增量的EditLog更新到FsImage中,保证更近实时点的FsImage和更小的EditLot日志
- 在非HA模式下,周期完成对Namode的EditLog向FsImage的合并,减少EditLog大小,减少Namenode启动时间
- 合并策略是满足如下的条件之一:
- 根据配置文件设置的时间间隔fs.checkpoint.period,默认3600秒
- 根据配置文件设置的EditLog大小fs.checkpoint.size,规定EditLog文件的最大大小,默认值是64MB
一次合并过程如下:
- SecondNameNode从Namenode拉取FsImage和增量的EditLog,然后进行合并,产生新的FsImage
- 同时Namenode产生新的增量EditLog
- SecondNameNode将新的FsImage上传到Namenode,然后Namenode用新的FsImage对旧的进行替换
HDFS启动时的正常流程:
- HDFS部署时会进行格式化,产生一个空的FsImage
- 当Namenode启动时,从磁盘读取EditLog和FsImage,将EditLog和FsImage进行合并产生一个新的FsImage
- 将新的FsImage保存到磁盘,然后删除旧的FsImage
HDFS启动时的安全模式:
- 处于安全模式的Namenode不会进行block的复制
- Namenode从所有的Datanode接收心跳信号和block状态列表(启动的时候Namenode没有block的location信息)
- 每当Namenode检测某个block的副本数量是否达到设置的最小值,如果达到则认为该副本是安全的
- 当安全的副本数量达到设置的百分比时,Namenode等待30秒后,退出安全模式
- 如果某个副本未达到设置的最小值,则会将该block的复制到其它Datanode上
- 第一个副本:如果客户端位于集群内部,则放置在客户端所在服务器的Datanode;如果客户端位于集群外部,则随机挑选一台磁盘不太满、CPU不忙的节点
- 第二个副本:放置在和第一个副本不同的机架上的节点
- 第三个副本:与第二个副本相同机架的节点
- 更多副本:随机节点
机架的概念:
- 服务器性能:塔式服务器 < 机架服务器 < 刀片式服务器
- 机架服务器:一个机架由多台服务器组成,共用一个备用电源,在同一个路由器下。多个机架通过另一个路由器进行连接
- 客户端和Namenode连接创建元数据
- Namenode判断元数据是否有效
- Namenode触发副本放置策略,返回一个有序的Datanode列表
- 客户端与Datanode建立pipeline连接
- 客户端将block切分成packet(64KB),并使用chunk(512B) + chucksum(4B)填充
- 客户端将packet放入到发送队列dataqueue中,并向第一个Datanode发送
- 第一个Datanode收到packet后进行本地保存,并发送给第二个Datanode
- 第二个Datanode收到packet后进行本地保存,并发送给第三个Datanode
- 上游的Datanode收到packet后进行本地保存,并发送给下游的Datanode。各个Datanode之间数据传输是并行的。副本数对于客户端是透明的
- 如果某个Datanode传输失败,则跳过该Datanode,向下一个Datanode传输
- 当block传输完成,Datanode各自向Namenode汇报,同时客户端继续传输下一个block
- 为了降低整体的带宽消耗和读取延时,HDFS会尽量读取离它更近的副本
- 下载文件过程如下:
- 客户端和Namenode交互文件元数据,获取fileBlockLocation
- Namenode按距离策略排序返回
- 客户端下载block,并验证数据完整性
- 其实多个block的下载是并行的