HDFS原理|青训营笔记

346 阅读16分钟

这是我参与「第四届青训营 」笔记创作活动的第五天

HDFS原理

HDFS基础介绍

  1. Hadoop体系技术 HDFS在Hadoop生态中起到数据存储的角色 image.png
  2. 数据存储演变

Windows单机文件系统
Linux单机文件系统:BTRFS, ZFS, XFS, EXT4等(目前支持近100种文件系统)
分布式文件系统:大容量、高可靠、低成本
image.png 分布式存储系统:对象存储、文件系统、快存储、数据库

  1. HDFS功能特性
  • 分布式:收到GFS启发,用Java实现的开发系统,没有实现完整的POSIX文件系统语义
  • 容错:自动处理、规避多种错误场景,例如常见的网络错误,机器宕机等
  • 高可用:一主多备模式实现元数据高可用,数据多副本实现用户数据的高可用
  • 高吞吐:Client直接从DataNode读取用户数据,服务端支持海量client并行读写
  • 可扩展:支持联邦集群模式,DataNode数据可达10W级别
  • 廉价:只需要通用硬件,不需要定制高端的昂贵硬件设备

架构原理

  1. HDFS组件
  • Client/SDK

  • 数据块 HDFS中的文件是以数据块的形式存储的,默认最基本的存储单位是128MB的数据块,也就是说,存储在HDFS中的文件都会被分割成128MB一块的数据进行存储,如果文件本身小于128MB,则按照实际大小进行存储,并不占用整个数据库空间。
    HDFS的数据块之所以会设置这么大,其目的是减少寻址开销。数据块数量越多,寻址数据块所耗费的时间越多。当然也不会设置过大。
    HDFS的每一个数据块默认都有3个副本,分布存储在不同的DataNode中,以实现容错,所有如果某个数据块丢失并不影响数据块的访问。数据块的大小和副本数量可在配置文件中更改。

  • DataNode DataNode才是HDFS中真正存储数据的地方。客户端可以向DataNode请求写入或读取数据块,DataNode还在来自NameNode的指令下执行块的创建、删除和复制,并且周期性的向NameNode汇报数据块的信息。

  • NameNode NameNode是HDFS中存储元数据(元数据就是文件名称,大小和在电脑中的位置)的地方,它将所有文件和文件夹的元素据保存在一个文件系统目录树中,任何元数据的改变,NameNode都会记录。HDFS中的每个文件都会拆分为多个数据块存放,这种文件与数据块的对应关系也存储在文件系统目录树中,由NameNode维护。
    NameNode还存储数据块到DataNode的映射信息,这种映射信息包括:数据块存放在哪个DataNode中、每个DataNode保存了哪些数据块。
    NameNode会监听DataNode的“心跳”和“块报告”,通过心跳和NameNode保持通讯。

  • SecondNameNode SecondNamenode是对主Namenode的一个补充,对内存的需求和Namenode相同
    SecondNamenode会周期地进行fsimage文件的合并,防止edits文件过大,导致Namenode启动时间过长
    应该与Namenode部署到不同节点上 image.png

  1. 写数据流程

1)客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在。
2)NameNode返回是否可以上传。
3)客户端请求第一个 Block上传到哪几个DataNode服务器上。
4)NameNode返回3个DataNode节点,分别为dn08、dn01、dn06。
5)客户端通过FSDataOutputStream模块请求dn8上传数据,dn8收到请求会继续调用dn01,然后dn01调用dn06,将这个通信管道建立完成。
6)dn08、dn01、dn06逐级应答客户端。
7)客户端开始往dn8上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,dn08收到一个Packet就会传给dn01,dn01传给dn6;dn08每传一个packet会放入一个应答队列等待应答。
8)当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器。(重复执行3-7步)。 image.png

  1. 读数据流程 1)客户端通过Distributed FileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址。
    2)挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。
    3)DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。
    4)客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。 image.png

  2. 元数据节点NameNode

  • 维护目录树 维护目录树的增删改查操作,保证所有修改都能持久化,以便机器掉电不会造成数据丢失或不一致

  • 维护文件和数据快的关系 文件被切分成多个块,文件以数据块为单位进行多副本存放

  • 维护文件块存放节点信息 通过接收DataNode的心跳汇报信息,维护集群节点的拓扑结构和每个文件块所有副本所在的DataNode类表。

  • 分配新文件存放节点 clent创建新的文件时候,需要有NameNode来确定分配目标DataNode image.png

  1. 共享数据同步进程JouralNode
    两个NameNode为了数据同步,会通过一组称作JournalNodes的独立进程进行相互通信。当active状态的NameNode的命名空间有任何修改时,会告知大部分的JournalNodes进程。standby状态的NameNode有能力读取JNs中的变更信息,并且一直监控edit log的变化,把变化应用于自己的命名空间。standby可以确保在集群出错时,命名空间状态已经完全同步。 image.png

  2. NameNode工作机制 第一阶段:NameNode启动
    (1)第一次启动NameNode格式化后,创建Fsimage和Edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。
    (2)客户端对元数据进行增删改的请求。
    (3)NameNode记录操作日志,更新滚动日志。
    (4)NameNode在内存中对数据进行增删改。
    第二阶段:Secondary NameNode工作
    (1)Secondary NameNode询问NameNode是否需要CheckPoint。直接带回NameNode是否检查结果。
    (2)Secondary NameNode请求执行CheckPoint。
    (3)NameNode滚动正在写的Edits日志。
    (4)将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode。
    (5)Secondary NameNode加载编辑日志和镜像文件到内存,并合并。
    (6)生成新的镜像文件fsimage.chkpoint。
    (7)拷贝fsimage.chkpoint到NameNode。
    (8)NameNode将fsimage.chkpoint重新命名成fsimage。
    image.png

  3. 数据节点DataNode

  • 数据块存取 DataNode需要高效实现对数据在磁盘上的存取

-心跳汇报 把存放在本机的数据块列表发送给NameNode,以便NameNode能维护数据块的位置信息,同时让NameNode确定该节点处于正常存活状态

  • 副本复制 数据写入时Pipeline操作
    机器故障时补全副本 image.png

关键设计

  1. 分布式系统基础概念
  • 容错能力 能够处理绝大部分异常场景,例如服务器宕机、网络异常、磁盘故障、网络超时等。

  • 一致性模型 为了实现容错,数据必须多副本存放,一致性要解决的问题是如何保障这多个副本的内容都是一致的。

  • 可扩展性 分布式存储系统需要具有横向扩张scale-out的能力。

  • 节点体系 常见的有主从模式、对等模式等,不管那种模式,高可用是必须的功能。

  • 数据放置 系统是由多个节点组成,数据是多副本存放时,需要考虑数据存放的策略。

  • 单机存储引擎 在绝大部分存储系统中,数据都是需要落盘持久化,单机引擎需要解决的是根据系统特点,如何高效得存取硬盘数据。

  1. NameNode

目录树维护

  • fsimage 文件系统目录树
    完整的存放在内存中
    定时存放在硬盘上
    修改是只会修改内存中的目录树

  • EditLog 目录树修改日志
    client更新目录树需要持久化EditLog后才能表示更新成功
    EditLog可存放在本地文件系统,也可存放在专用系统上
    NameNode HA方案一个关键点就是如何实现EditLog共享

image.png image.png

数据放置

  • 数据块信息维护 目录树保存每个文件的块id
    NameNode维护了每个数据块所在节点信息
    NameNode根据DataNode汇报的信息动态维护位置信息
    NameNode不会持久化数据块位置信息

  • 数据防止策略 新数据存放到那些节点
    数据均衡需要怎么合理搬迁数据
    3个副本怎么合理放置

image.png

  1. DataNode
  • 数据块的硬盘存放 文件在NameNode已分割成block
    DataNode以block为单位对数据进行存取

  • 启动扫盘 DataNode需要知道本机存放了那些数据块
    启动时把本机硬盘上的数据块列表加载到内存中

image.png

  1. HDFS写异常处理 Lease Recovery
  • 租约 Client要改修一个文件时,需要通过NameNode上锁,这个锁就是租约(Lease)。

  • 场景 文件写了一半,client自己挂掉了。可能产生问题:副本不一致,Lease无法释放

  • 解决方法 Lease Recovery image.png Pipeline Recovery

  • 情景 文件写入过程中,DataNode侧出现异常挂掉了。

  • 异常出现时机 创建连接时,数据传输时,complete阶段

  • 解决方法 Pipeline Recovery image.png

  1. Client读异常处理
  • 情景 读取文件的过程,DataNode侧出现异常挂掉

  • 解决方法 节点Failover

  • 增强情景 节点半死不过,读取很慢 image.png

  1. 旁路系统
  • Balancer 均衡DataNode的容量(datanode之间)

  • Mover

确保副本放置位置符合策略条件(副本经常分布在不同机架和datanode节点)

  1. 控制面建设
  • 可观测性设施 指标埋点
    数据采集
    访问日志
    数据分析

  • 运维体系建设 运维操作需要平台化
    NameNode操作复杂
    DataNode机器规模庞大
    组件控制面API

HDFS高可用高扩展

元数据高可用

服务高可用的需求

  1. 故障类型 硬件故障
    软件故障
    认为故障

  2. 灾难:数据中心级别不可用 机房断电
    机房空调停机
    机房网络故障、拥塞

故障不可避免,灾难时有发生。如HDFS系统不可用,业务停止的损失极大,所以HDFS系统高可用性至关重要。

  1. 服务可用性指标 MTTR
    MTTF
    MTBF image.png

  2. 全年不可用时间 可用性 99.9%,全年8.76小时不可用
    可用性 99.99%,全年52.6分钟不可用
    可用性 99.999%,全年5.26分钟不可用

image.png 5. 高可用形式 服务高可用:冷备份,热备份
故障恢复:人工切换、自动切换
人工的反应、决策时间更长,高可用需要让系统自动决策。HDFS的设计中,采用了中心化的元数据管理节点NameNode,NameNode容易成为故障中的单点。

HDFS主备同步实现

  1. HDFS NameNode高可用架构
  • 组件介绍 ActiveNameNode:主节点,提供服务,生产日志
    StandbyNamenode:备节点,消费日志
    Zookeeper:为自动选主提高统一协调服务
    BookKeeper:提供日志存储服务
    ZKFC:NameNode探活,触发主备切换
    HA Client:提供自动切换的客户端 edit log:操作日志

  • 高可用话题 节点状态怎么保存
    操作日志如何同步
    如何做到自动切换 image.png

  1. 状态复制 状态机复制是实现容错的常规方法
    组件:状态机以及副本,变更日志,共识协议 image.png

  2. NameNode操作日志

Active生产,Standby(可能有多个)消费-物理日志和逻辑日志
日志系统
高可用
高扩展
高性能
强一致(有序) image.png image.png 4. NameNode快状态维护

  • 回顾 DataNode Heartbeat,DataNode Block Report

  • 区别 Active 即接收,也发起更改; Standby只接收,不发起变更

  • Content Stale 状态 主备切换后,避免DN的不确定状态

HDFS 自动主备切换

  1. 分布式协调组件-Zookeeper 一般用于提供主、协调、元数据存储
    使用它的组件:HDFS、YARN、HBase、Kafka、ClickHouse
    HA 核心机制: Watch

  2. 自动主备切换流程

  • Service侧 ZKFialoverController:作为外部组件,驱动HDFS NameNode的主备切换,具有如下功能:主备切换、轮询探活、脑裂问题、Fence机制等、
  • Client侧 核心机制:StandbyException Client自动处理

image.png

日志系统BookKeeper

  1. BookKeeper架构 BookKeeper存储日志
    低延迟
    持久性
    强一致性
    读写高可用 image.png
  2. Quorum机制

多副本一致性读写
场景:多副本对象存储,用版本号表示数据新旧
规则 1、Qr+Qw>QQ_{r}+Q_{w}>Q 2、Qw>Q/2Q_{w}>Q/2

image.png Sloppy Quorum机制:适用于顺序追加,只写
Write Quorum:写入副本数
Ack Quorum:响应副本数 image.png 3. Ensemble机制 Round-Robin Load Balancer
第一轮:1,2,3
第二轮:2,3,4
第一轮:3,4,1
第一轮:4,1,2
优势:数据均衡 image.png

数据存储高可用

  1. 单机存储 RAID Redundant Array of Independent Disks RAID
    特点:廉价、高性能、大容量、高可用 image.png
  2. RAID方案

单机存储数据高可用机制

条带状,冗余,容错校验 image.pngnng'a方案

HDFS数据高可用机制

  1. HDFS多副本 Hadoop多副本放置
    优点
    读写路径简单
    副本修复简单
    高可用 image.png

  2. HDFS Erasure Coding 业界常见Reed Solomon算法 image.png 直接保存EC和Stripe(条带化)后保存的EC
    和多副本比较:读写速度,成本,修复速度,读写路径的实现 image.png

网络架构的高可用

  1. 网络架构 机架(Rack):放服务器的架子。
    TOR(Top of Rack): 机架顶部的交换机。 数据中心(Data Center): 集中部署服务器的场所 image.png
  2. 机架感知 一个TOR故障导致整个机架不可用 VS 降低跨rack流量
    trade-off: 一个本地、一个远端 image.png

元数据高扩展性

元数据扩展性挑战

  1. 扩展性挑战 HDFS NameNode是个集中式服务,部署在单个机器上,内存和磁盘的容量、CPU的计算力都不能无限扩展。
    scale up Vs scale out
    扩容单个服务器的能力
    部署多个服务器来服务
    挑战
    控制空间分裂
    DataNode汇报
    目录树结构本身复杂 image.png
  2. 常见scale out方案 KV模型的系统可以适用partition
    Redis
    Kafka
    MySQL(分库分表)
    三种数据路由方式
    服务端侧
    路由层
    客户端侧 image.png

社区解决方案

  1. BlockPool 解决DN同时服务多组NN的问题
    文件服务分层:Namespace、Block Storage
    用BlockPool来分区DN的服务:数据块存储、心跳和快上报 image.png
  2. viewfs

Federation架构:将多个不同集群组合起来,对外表表现像一个集群一样
viewfs通过在client-side的配置指定不同的目录访问不同的NameNode。
局限性:运维复杂 image.png

字节解决方案-NNProxy

  1. NNproxy NNProxy是ByteDance自研的HDFS代理层,提供路由服务,开源地址:github.com/bytedance/n… NNProxy主要实现了路由管理和RPC转发,以及授权,限流,查询缓存等额外能力。 image.png

数据存储高扩展性

超大集群的长尾问题

  1. 延迟的分布和长尾延迟 延迟的分布
    用百分数来表示访问延迟的统计信息
    例如p95表示1ms,代表95%的请求延迟低于1ms,但是后5%延迟会大于1ms 长尾延迟:尾部(p99/p999/p9999)的延迟,衡量系统最差的请求情况,会显著差于平均值 image.png image.png
  2. 尾部延迟放大 木桶原理
    尾部延迟放大:访问的服务变多,尾部的请求就会越发的慢。
    如何变慢
    如何固定延迟阈值,固定延迟百分位 image.png
  3. 长尾问题表现-慢节点

慢节点:读取速度过慢,导致客户端堵塞。
慢节点的发生难以避免和预测
共享资源,后台维护活动,请求多级排队,功率限制
固定的损耗:机器损耗率
混沌现象
离线任务也会遇到长尾问题
全部任务完成时间取决于最慢的任务什么时候完成
集群规模变大,任务数据量变大(集群扩大10倍,问题扩大N(>10)倍)
只要任何数据块的读取受到长尾影响,整个任务就会因此停滞。

image.png

超大集群可靠性问题

  1. 超大集群的可靠性 条件一:超大集群下,有一部分机器是损坏来不及修理的
    条件二:副本放置策略完全随机
    条件三:DN的容量足够大
    推论:必然有部分数据全部副本在损坏的机器上,发生数据丢失 image.png

  2. CopySet 将DataNode分为若干个Copyset选块在copyset内部选择
    原理:减少副本放置的组合数,从而降低副本丢失的概率 image.png

超大集群的不均匀问题

  1. 超大集群的负载均衡和数据迁移

image.png

  1. 数据写入不均 数据不均匀
    节点容量不均匀
    数据新旧不均匀
    访问类型不均匀
    资源负载不均匀 image.png

  2. DN冷热不均 数据不均匀
    节点容量不均匀
    数据新旧不均匀
    访问类型不均匀
    资源负载不均匀 image.png

  3. 负载均衡和数据迁移的典型场景

image.png

数据迁移工具

  1. 跨NN迁移

DistCopy
基于MapReduce,通过一个个任务,将数据从一个NameNode拷贝到另一个NameNode
需要拷贝数据,流量较大,速度较慢
FastCopy
开源社区的无需拷贝数据的快速元数据迁移方案
前提条件:新旧集群的DN列表吻合
对于元数据,直接复制目录树的结构和块信息
对于数据块,直接要求DataNode从源Blockool hardlink到目标BlookPool,没有数据拷贝
hardlink:直接让两个路径指向同一块数据

  1. Balancer 工具向DataNode发起迁移命令,平衡各个DataNode的容量
    场景:单机房适用,多机房使用,限流措施
    评价标准:稳定性成本,可运维性,执行效率 image.png