• HDFS储存模型


    1. HDFS储存模型

    1. 文件按线性切割成block,每个block具有offset和id
    2. 文件与文件的block大小可以不一样
    3. 一个文件除最后一个block,其它block的大小都一样
    4. block的大小根据硬件的I/O特性调整
    5. block被分散到集群的各个节点中,具有location
    6. block具有副本replication,没有主从概念,副本不能出现在同一个节点
    7. 副本是满足可靠性和性能的关键
    8. 文件上传可以指定block大小和副本数,上传后只能修改副本数
    9. 一次写入多次读取,不支持修改,只支持追加数据

    2. 角色功能

    Namenode

    • 完全基于内存储存文件元数据、目录结构、文件block的映射
    • 需要持久化方案保证数据可靠性
    • 提供副本放置策略

    DataNode

    • 基于本地磁盘储存block
    • 保存block的校验,保证block的可靠性
    • 与Namenode保持心跳,汇报block状态列表

    3. Namenode元数据持久化

    对内存中的数据进行持久化有两种方案:

    方案一:

    • 以log的形式,保持每一次数据变更的记录,比如mkdir /a、put text.txt /a等
    • 优点:完整性好;缺点:恢复数据慢

    方案二:

    • 对内存中的数据,定期进行snapshot,保存到磁盘
    • 优点:恢复数据快;缺点:容易丢失数据

    HDFS结合了两种方案的优点:

    • 任何对文件系统元数据产生修改的操作,Namenode都会保存到EditLog事务日志中
    • 使用FsImage储存内存所有的元数据状态
    • 滚动将增量的EditLog更新到FsImage中,保证更近实时点的FsImage和更小的EditLot日志

    4. SecondNameNode

    • 在非HA模式下,周期完成对Namode的EditLog向FsImage的合并,减少EditLog大小,减少Namenode启动时间
    • 合并策略是满足如下的条件之一:
      1. 根据配置文件设置的时间间隔fs.checkpoint.period,默认3600秒
      2. 根据配置文件设置的EditLog大小fs.checkpoint.size,规定EditLog文件的最大大小,默认值是64MB

    一次合并过程如下:

    1. SecondNameNode从Namenode拉取FsImage和增量的EditLog,然后进行合并,产生新的FsImage
    2. 同时Namenode产生新的增量EditLog
    3. SecondNameNode将新的FsImage上传到Namenode,然后Namenode用新的FsImage对旧的进行替换

    5. 安全模式

    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上

    6. Block的放置策略

    • 第一个副本:如果客户端位于集群内部,则放置在客户端所在服务器的Datanode;如果客户端位于集群外部,则随机挑选一台磁盘不太满、CPU不忙的节点
    • 第二个副本:放置在和第一个副本不同的机架上的节点
    • 第三个副本:与第二个副本相同机架的节点
    • 更多副本:随机节点

    机架的概念:

    • 服务器性能:塔式服务器 < 机架服务器 < 刀片式服务器
    • 机架服务器:一个机架由多台服务器组成,共用一个备用电源,在同一个路由器下。多个机架通过另一个路由器进行连接

    7. HDFS写流程

    1. 客户端和Namenode连接创建元数据
    2. Namenode判断元数据是否有效
    3. Namenode触发副本放置策略,返回一个有序的Datanode列表
    4. 客户端与Datanode建立pipeline连接
    5. 客户端将block切分成packet(64KB),并使用chunk(512B) + chucksum(4B)填充
    6. 客户端将packet放入到发送队列dataqueue中,并向第一个Datanode发送
    7. 第一个Datanode收到packet后进行本地保存,并发送给第二个Datanode
    8. 第二个Datanode收到packet后进行本地保存,并发送给第三个Datanode
    9. 上游的Datanode收到packet后进行本地保存,并发送给下游的Datanode。各个Datanode之间数据传输是并行的。副本数对于客户端是透明的
    10. 如果某个Datanode传输失败,则跳过该Datanode,向下一个Datanode传输
    11. 当block传输完成,Datanode各自向Namenode汇报,同时客户端继续传输下一个block

    8. HDFS读流程

    • 为了降低整体的带宽消耗和读取延时,HDFS会尽量读取离它更近的副本
    • 下载文件过程如下:
      1. 客户端和Namenode交互文件元数据,获取fileBlockLocation
      2. Namenode按距离策略排序返回
      3. 客户端下载block,并验证数据完整性
      4. 其实多个block的下载是并行的
  • 相关阅读:
    FreeRTOS自我救赎1之基本知识
    Uniapp 酷炫钱包页面模板 直接引用
    在数据库插入大量不同数据
    【每日OJ —— 232.用栈实现队列(栈)】
    JavaScript的垃圾回收机制
    OSPF高级配置——NSSA区域与地址汇总
    大数据Spark面试题2023
    1004 成绩排名
    从零开始:Django项目的创建与配置指南
    动态内存精讲
  • 原文地址:https://blog.csdn.net/yy8623977/article/details/123969988