HDFS 高可用与高扩展性机制分析笔记(一)| 青训营笔记

116 阅读8分钟

HDFS 高可用与高扩展性机制分析笔记(一)| 青训营笔记

这是我参与「第四届青训营 -大数据场」笔记创作活动的第13天

一、元数据高可用

1. 高可用的需求

1.1 高可用定义

系统在困境中仍可正常工作。

  • 困境:故障adversity

    • 硬件故障
    • 软件故障
    • 人为错误
  • 灾难:数据中心级别不可用

    • 机房断电
    • 机房空调停机
    • 机房网络故障、阻塞
  • 正常工作:

    • 正确完成功能
    • 能达到期望的性能水准
  • 容灾:

    • 在相隔较远的异地,建立两套或多套功能相同的系统,互相之间可以进行健康状态监视和功能切换,当一处系统因意外(如火灾、地震等)停止工作时,整个应用系统可以切换到另一处,使得该系统功能可以继续正常工作。
1.2 故障度量的指标
  • MTTR(Mean Time To Repair):平均修复时间,系统能多快恢复。
  • MTTF(Mean Time To Failure):平均失效时间,运行到故障间的时间,一般用于不可修复的系统(制造业)。
  • MTBF(Mean Time Between Failures):平均无故障时间,两次故障间的间隔,一般用于可修复的系统(软件)。

image.png

1.3 可用性的年化

image.png

  • 全年不可用时间 (可用性百分比):系统运行一整年的不可用时间的目标。

    • 99.9% 全年8.76小时不可用
    • 99.99% 全年52.6分钟不可用
    • 99.999% 全年5.26分钟不可用
1.4 高可用的形式
  • 服务高可用

    • 热备份:主服务和备服务同时运行,在主服务故障时,随时可以切换到备服务。
    • 冷备份:备份服务的数据,可以和数据归档相结合。在主服务故障时,利用备份的数据重启。
  • 故障恢复操作

    • 人工切换:在故障发生时,运维人员接收报警后,手动执行服务切主操作。一般较慢,难以满足全年不可用时间的目标。
    • 自动切换:通过探活组件、分布式共识协议等手段,系统能自动发现主服务的故障,并切换到备份不符。
  • HDFS设计中采用了中心化的源数据管理节点NameNode,因此容易成为故障中的单点,指系统中一旦失效,就会让整个系统无法运作的组件。

2. HDFS主备同步实现

2.1 HDFS NameNode 高可用架构
2.1.1 组件介绍
  • Active NameNode:提供服务的 NameNode 主节点,生产 editlog。
  • Standby NameNode:不提供服务,起备份作用的 NameNode 备节点,消费 editlog
  • Editlog:用户变更操作的记录,具有全局顺序,是 HDFS 的变更日志。
  • ZooKeeper:开源的分布式协调组件,主要功能有节点注册、主节点选举、元数据存储。
  • BookKeeper:开源的日志存储组件,存储 editlog
  • ZKFC:和 ZK、NN 通信,进行 NN 探活和自动主备切换。
  • HA Client:处理 StandbyException,在主备节点间挑选到提供服务的主节点。
2.1.2 三个问题
  • 节点状态如何更新
  • 操作日志如何同步
  • 如何做到自动切换
2.2 状态机复制模型

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

  • 状态机:一个状态机从“初始”状态开始,每一个输入都被传入转换函数和输出函数,以生成一个新的状态和输出。在新的输入被接收到前,状态保持不变,而输出同时被传输给恰当的接受者。
  • 状态机复制:确定性的状态机具有「处理确定的输入后,状态唯一确定」的特性。状态机复制利用这个特性实现多个相同的状态机副本的同步更新。
  • 变更日志:触发状态机更新的变更操作,具有全局确定的顺序。
  • 共识协议:确保每个副本都能收到相同的日志的共识协议,常见的有 Paxos、Raft、ZAB。
2.3 NameNode 状态持久化
  • FSImage 文件:较大的状态记录文件,是某一时刻 NN 全部需要持久化的数据的记录。大小一般在 GB 级别。
  • EditLog 文件:是某段时间发生的变更日志的存储文件。大小一般在 KB~MB 级别。
  • checkpoint 机制:将旧的 FSImage 和 EditLog 合并生成新的 FSImage 的流程,在完成后旧的数据可以被清理以释放空间。
2.4 NameNode 操作日志的生产消费
  • 目录树和文件信息的更新

  • active生产,standby消费

  • 物理日志和逻辑日志

    • 物理日志:存储了物理单元(一般是磁盘的 page)变更的日志形式。
    • 逻辑日志:存储了逻辑变更(例如 rename /a to /b)的日志形式。
  • 日志系统

    • 高可用
    • 高扩展
    • 高性能
    • 强一致(有序)
2.5 NameNode 块状态维护
  • DataNode Heartbeat:DataNode使用心跳向active和standby节点都报备存活

  • DataNode Block Report:block汇报同时到active和standby

  • 区别

    • active:只接受,也发起变更
    • standby:只接受但不发起变更
  • content stale状态:主备切换后避免dataNode的不确定状态

    • 新上主的node不能直接进行数据操作,需要等上报状态后再进行

3. 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 的进程。

4. 自动主备切换

  • 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 的服务放在了不同的进程中,而更先进的系统一般会内置在服务进程中。

5. 高可用日志系统 BookKeeper

5.1 bookkeeper基础
  • 高可靠:数据写入多个存储节点,数据写入就不会丢失。
  • 高可用:日志存储本身是高可用的。因为日志流比文件系统本身的结构更为简单,日志系统高可用的实现也更为简单。
  • 强一致:日志系统是追加写入的形式,Client 和日志系统的元数据可以明确目前已经成功的写入日志的序号(entry-id)。
  • 可扩展:整个集群的读写能力可以随着添加存储节点 Bookie 而扩展。
5.2 Quorum 协议

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

  • 多副本间一般通过 version-id 来描述状态的新旧。
  • 高可用:多个副本确保了高可用(后文会再次介绍多副本高可用)。
  • 高性能:不用等所有副本写入成功,降低了的长尾延迟(后文会再次介绍长尾延迟)。
  • 参考:Quorum 协议
5.3 BookKeeper Quorum 协议

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

  • 日志写入是追加,不是状态变更,只需要确认目前的 entry-id,相对更简单。
  • Write Quorum:一次写入需要写入到的存储节点数。
  • Ack Quorum:一次写入需要收到的响应数,小于 write quorum。
  • 高性能:不用等所有副本写入成功,降低了的长尾延迟(后文会再次介绍长尾延迟)。
  • Ensemble:通过轮询(Round-Robin)来确认 write quorum 实际对应的存储节点实例,可以比较简单的完成副本放置和扩展。