HDFS 高可用和高扩展机制分析 | 青训营笔记

189 阅读12分钟

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

资料来源于[这](【大数据专场 学习资料三】第四届字节跳动青训营 - 掘金 (juejin.cn))

HDFS 高可用和高扩展机制分析

01.元数据高可用

高可用是因为要处理故障

故障类型:

硬件故障 软件故障 人为故障

灾难

机房断电、机房网络故障拥塞、机房空调停机

HDFS高可用性至关重要!

高可用的衡量:MTTR、MTTF、MTBF

可用性的年化:

image.png

高可用的形式:服务高可用:热备份、冷备份。故障恢复操作:人工切换、自动切换

HDFS中,采用了中心化的元数据管理节点,NameNode容易成为故障中的单点

 

状态机复制模型:实现容错服务的一种常规方法,主要通过复制服务器,并协调客户端和这些服务器镜像间的交互来达到目标。这个方法也同时提供了理解和设计复制管理协议的一套基本框架。

状态机:一个状态机从“初始”状态开始,每一个输入都被传入转换函数和输出函数,以生成一个新的状态和输出。在新的输入被接收到前,状态保持不变,而输出同时被传输给恰当的接受者。

状态机复制:确定性的状态机具有「处理确定的输入后,状态唯一确定」的特性。状态机复制利用这个特性实现多个相同的状态机副本的同步更新。

变更日志:触发状态机更新的变更操作,具有全局确定的顺序。

共识协议:确保每个副本都能收到相同的日志的共识协议,常见的有 Paxos、Raft、ZAB。

HDFS高可用架构

image.png

Active NameNode:提供服务的 NameNode 主节点,生产 editlog。

Standby NameNode:不提供服务,起备份作用的 NameNode 备节点,消费 editlog

editlog:用户变更操作的记录,具有全局顺序,是 HDFS 的变更日志。

ZooKeeper:开源的分布式协调组件,主要功能有节点注册、主节点选举、元数据存储。

BookKeeper:开源的日志存储组件,存储 editlog

ZKFC:和 ZK、NN 通信,进行 NN 探活和自动主备切换。

HA Client:处理 StandbyException,在主备节点间挑选到提供服务的主节点。

NameNode 状态持久化

FSImage 文件:较大的状态记录文件,是某一时刻 NN 全部需要持久化的数据的记录。大小一般在 GB 级别。

EditLog 文件:是某段时间发生的变更日志的存储文件。大小一般在 KB~MB 级别。

checkpoint 机制:将旧的 FSImage 和 EditLog 合并生成新的 FSImage 的流程,在完成后旧的数据可以被清理以释放空间。

物理日志: 存储了物理单元(一般是磁盘的 page)变更的日志形式。

逻辑日志:存储了逻辑变更(例如 rename /a to /b)的日志形式。

HDFS 主备切换

DataNode 心跳与块汇报需要同时向 active NN 和 standby NN 上报,让两者可以同时维护块信息。但只有 active NN 会下发 DN 的副本操作命令。

content stale 状态:在发生主备切换后,新 active NN 会标记所有 DN 为 content stale 状态,代表该 DN 上的副本是不确定的,某些操作不能执行。直到一个 DN 完成一次全量块上报,新 active NN 才标记它退出了 content stale 状态。

例子,多余块的删除:NN 发现某个块的副本数过多,会挑选其中一个 DN 来删除数据。在主备切换后,新 active NN 不知道旧 active NN 挑选了哪个副本进行删除,就可能触发多个 DN 的副本删除,极端情况下导致数据丢失。content stale 状态的引入解决了这个问题。

脑裂问题:因为网络隔离、进程夯住(例如 Java GC)等原因,旧的 active NN 没有完成下主,新的 active NN 就已经上主,此时会存在双主。client 的请求发给两者都可能成功,但不能保证一致性(两个 NN 状态不再同步)和持久化(只能保留一个 NN 状态)。

fence 机制:在新 active NN 上主并正式处理请求之前,先要确保旧 active NN 已经退出主节点的状态。一般做法是先用 RPC 状态检测,发现超时或失败则调用系统命令杀死旧 active NN 的进程。

自动主备切换

ZooKeeper 是广泛使用的选主组件,它通过 ZAB 协议保证了多个 ZK Server 的状态一致,提供了自身的强一致和高可用。

ZooKeeper 的访问单位是 znode,并且可以确保 znode 创建的原子性和互斥性(CreateIfNotExist)。client 可以创建临时 znode,临时 znode 在 client 心跳过期后自动被删除。

ZK 提供了 Watch 机制,允许多个 client 一起监听一个 znode 的状态变更,并在状态变化时收到一条消息回调(callback)。

基于临时 znode 和 Watch 机制,多个客户端可以完成自动的主选举。

ZKFailoverController:一般和 NN 部署在一起的进程,负责定时查询 NN 存活和状态、进行 ZK 侧主备选举、执行调用 NN 接口执行集群的主备状态切换、执行 fence 等能力。

Hadoop 将集群主备选举的能力和 NN 的服务放在了不同的进程中,而更先进的系统一般会内置在服务进程中。

高可用日志系统 BookKeeper

高可靠:数据写入多个存储节点,数据写入就不会丢失。

高可用:日志存储本身是高可用的。因为日志流比文件系统本身的结构更为简单,日志系统高可用的实现也更为简单。

强一致:日志系统是追加写入的形式,Client 和日志系统的元数据可以明确目前已经成功的写入日志的序号(entry-id)。

可扩展:整个集群的读写能力可以随着添加存储节点 Bookie 而扩展。

Quorum 协议: 基于鸽巢原理,在多个副本间确保高可用、高性能的多副本变更协议

多副本间一般通过 version-id 来描述状态的新旧。

高可用:多个副本确保了高可用(后文会再次介绍多副本高可用)。

高性能:不用等所有副本写入成功,降低了的长尾延迟(后文会再次介绍长尾延迟)。

参考:Quorum 协议

BookKeeper Quorum 协议: 基于 Quorum 的多数派思想来提供高可用、高性能写入的日志写入

日志写入是追加,不是状态变更,只需要确认目前的 entry-id,相对更简单。

Write Quorum:一次写入需要写入到的存储节点数。

Ack Quorum:一次写入需要收到的响应数,小于 write quorum。

高性能:不用等所有副本写入成功,降低了的长尾延迟(后文会再次介绍长尾延迟)。

Ensemble:通过轮询(Round-Robin)来确认 write quorum 实际对应的存储节点实例,可以比较简单的完成副本放置和扩展。

02.数据存储高可用

RAID: 将多个廉价、不可靠、低性能、容量小的磁盘组装在一起,提供高可靠、高性能、大容量逻辑磁盘服务的一组磁盘列阵方案。

RAID 0 :将数据分块后按条带化的形式分别存储在多个磁盘上,提供大容量、高性能。

RAID 1:将数据副本存储在多个磁盘上,提供高可靠。

RAID 3:在数据分块存储的基础上,将数据的校验码存储在独立的磁盘上,提供高可靠、高性能。

其他可以参考 RAID

多副本方案:将数据块存储在多个 DN 上

Erasure Coding 方案: 将数据分段,通过特殊的编码方式存储额外的校验块,并条带化的组成块,存储在 DN 上。

条带化:原本块对应文件内连续的一大段数据。条带化后,连续的数据按条带(远小于整个块的单位)间隔交错的分布在不同的块中。

Reed Solomon 算法:参考 Reed-solomon codes

成本更低:多副本方案需要冗余存储整个块,EC 方案需要冗余存储的数据一般更少。

数据中心架构

机架/机柜:将几个服务器统一供电、提供对外网络的固定的物理设备。

TOR top of rack:机架顶部(或底部)的交换机,负责机架内服务器和数据中心的其他服务器的网络通信。

机房和数据中心都是指大量服务器集中放置的场所。

机房:强调的基础设施建设,例如物理承重、空调、防水、消防。

数据中心:强调机房的业务属性。

网络拓扑:按数据中心->机架->机器的顺序,描述进程在网络空间中所处的位置。

跨机房专线:由网络服务商提供,连接机房的专用网络。

稳定性和安全性好于公网。

相比于数据中心内网络,吞吐更为有限、延迟更高、成本更高。

故障域

故障域是基础设施中可能发生故障的区域或组件。每一个域都有自己的风险和挑战,由个别几个因素决定整个故障域的服务能力,需要进行架构。

机架感知:以 TOR 为关键点,机架是一个故障域。数据副本全部放置在一个机架中,当相应 TOR 故障时数据就无法访问。

机房感知:以机房的基础设施(空调、电力)和跨机房专线为关键点,它们发生故障时整个机房会发生故障,导致不可用。

多机房容灾:服务和数据需要存放在多个机房,并配合合理的架构。使得发生机房故障时依然可以提供服务。

03.元数据高扩展性

扩展性方案

scale up:通过单机的 CPU、内存、磁盘、网卡能力的提升来提升系统服务能力,受到机器成本和物理定律的限制。

scale out:通过让多台机器组成集群,共同对外提供服务来提升系统服务能力。一般也称为高扩展、水平扩展。

partition 方法

水平分区和垂直分区:水平分区指按 key 来将数据划分到不同的存储上;垂直分区指将一份数据的不同部分拆开存储,用 key 关联起来。partition 一般都水平分区,又称 shard。

常用于 KV 模型,通过 hash 或者分段的手段,将不同类型 key 的访问、存储能力分配到不同的服务器上,实现了 scale out。

重点:不同单元之间不能有关联和依赖,不然访问就难以在一个节点内完成。例如 MySQL 的分库分表方案,难以应对复杂跨库 join。

federation 架构

使得多个集群像一个集群一样提供服务的架构方法,提供了统一的服务视图,提高了服务的扩展性。

文件系统的目录树比 kv 模型更复杂,划分更困难。

邦联架构的难点一般在于跨多个集群的请求,例如 HDFS 的 rename 操作就可能跨多个集群。

blockpool

将文件系统分为文件层和块存储层,对于块存储层,DN 集群对不同的 NN 提供不同的标识符,称为 block pool。

解决了多个 NN 可能生成同一个 block id,DN 无法区分的问题。

viewfs

邦联架构的一种实现,通过客户端配置决定某个路径的访问要发送给哪个 NN 集群。

缺点:客户端配置难以更新、本身配置方式存在设计(例如,只能在同一级目录区分;已经划分的子树不能再划分)。

NNProxy

ByteDance 自研的 HDFS 代理层,于 2016 年开源

主要提供了路由管理、RPC 转发,额外提供了鉴权、限流、查询缓存等能力。

开源社区有类似的方案 Router Based Federation,主要实现了路由管理和转发。

小文件问题

HDFS 设计上是面向大文件的,小于一个 HDFS Block 的文件称为小文件。

元数据问题:多个小文件相对于一个大文件,使用了更多元数据服务的内存空间。

数据访问问题:多个小文件相对于一个大文件,I/O 更加的随机,无法顺序扫描磁盘。

计算任务启动慢:计算任务在启动时,一般会获得所有文件的地址来进行 MapReduce 的任务分配,小文件会使得这一流程变长。

典型的 MR 流程中,中间数据的文件数和数据量与 mapper*reducer 的数量成线性,而为了扩展性,一般 mapper 和 reducer 的数量和数据量成线性。于是,中间数据的文件数和数据量与原始的数据量成平方关系。

小文件合并任务:计算框架的数据访问模式确定,可以直接将小文件合并成大文件而任务读取不受影响。通过后台运行任务来合并小文件,可以有效缓解小文件问题。通过 MapReduce/Spark 框架,可以利用起大量的机器来进行小文件合并任务。

Shuffle service:shuffle 流程的中间文件数是平方级的,shuffle service 将 shuffle 的中间数据存储在独立的服务上,通过聚合后再写成 HDFS 文件,可以有效地缓解中间数据的小文件问题。