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

104 阅读9分钟

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

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

01. 元数据服务高可用

1.1 高可用的需求

1.1.1 服务高可用的需求

故障类型

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

灾难:数据中心级别不可用

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

故障不可避免,灾难时有发生。

如果HDFS系统不可用。

  • 无法核算广告账单,直接引发收入损失
  • 无法生产数据报表,数据驱动无从谈起
  • 无法进行模型训练,引起用户体验下滑

业务停止的损失极大,所以 HDFS系统的高可用性就至关重要。

1.1.2 高可用的衡量

服务可用指标

  • MTRR
  • MTTF
  • MTBF

1.1.3 可用性的年化

可用性:

全年不可用时间

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

依赖自动化

1.1.4 高可用的形式

服务高可用

  • 热备份
  • 冷备份

故障恢复操作

  • 人工切换
  • 自动切换

人工的反应、决策时间都更长,高可用需要让系统自动决策。 HDFS 的设计中,采用了中心化的元数据管理节点NameNode。

NameNode容易成为故障中的单点( single point of failure ) 。

1.2 HDFS主备同步实现

1.2.1 HDFS NameNode高可用架构

组件介绍

  • ActiveNamenode :主节点,提供服务,生产日志
  • StandbyNamenode:备节点,消费日志
  • ZooKeeper :为自动选主提供统一协调服务
  • BookKeeper :提供日志存储服务
  • ZKFC : NameNode探活、触发主备切换
  • HA Client :提供了自动切换的客户端
  • edit log:操作的日志

围绕三个问题来看高可用

  • 节点状态如何更新
  • 操作日志如何同步
  • 如何做到自动切换

1.2.2 理论基础 状态机复制和日志

状态机复制是实现容错的常规方法

组件:

  • 状态机以及其副本
  • 变更日志
  • 共识协议

1.2.4 NameNode操作日志的生产消费

目录树和文件信息的更新

Active生产,Standby消费

物理日志与逻辑日志

日志系统

  • 高可用
  • 高扩展性
  • 高性能
  • 强一致(有序)

IdLog

1.2.5 NameNode块状态维护

一致性问题

持久化 / 非持久化(块)

回顾:

  • DataNode Heartbeat
  • DataNode Block Report

区别

  • Active即接收,也发起变更
  • Standby只接收,不发起变更

Content Stale状态

  • 主备切换后,避免 DataNode的不确定状态

1.3 HDFS自动主备切换

1.3.1 分布式协调组件 - Zookeeper

HA核心机制:Watch

选举机制

1.3.2 自动主备切换流程 - Server侧

ZKFailoverController作为外部组件,驱动HDFS NameNode的主备切换

  • 轮询探活

  • 脑裂问题:两边都认为自己是Active,导致日志出错(NameNode侧)

    • Hadoop:直接Kill掉,粗暴
  • Fence机制

1.3.3 自动主备切换流程 - Client侧

核心机制:StandbyException

Client自动处理

新Active收到旧Active信息

1.4 日志系统Bookkeeper简介

1.4.1 BookKeeper架构

BookKeeper存储日志

  • 低延时
  • 持久性
  • 强一致性
  • 读写高可用

对比:日志系统和文件系统的复杂度

1.4.2 Quorum机制

Quorum机制:多副本一致性读写

场景:多副本对象存储,用版本号标识数据新旧

规则

  1. Q+ Qw>Q
  2. Qw> Q/2

思考∶日志场景比对象保存更简单

1.4.3 BookKeeper Quorum

Sloppy Quorum机制

日志场景:顺序追加、只写

Write Quorum:写入副本数

Ack Quorum:响应副本数

思考:Client 挂掉导致不确认写入了多少数据,如何恢复?

1.4.4 BookKeeper Ensemble机制

Round-Robin Load Balancer

  • 第一轮:1,2,3
  • 第二轮:2,3,4
  • 第三轮:3,4,1
  • 第四轮︰4,1,2

优势:数据均衡,不用在写日志客户端配置写位置

02. 数据存储高可用

2.1单机存储的数据高可用机制

2.1.1 回到单机存储 - RAID

Redundant Array of Independent Disks

特点

  • 廉价
  • 高性能
  • 大容量
  • 高可用

2.1.2 RAID方案

RAID 0:条带化,把数据分成一个一个条带

RAID 1:冗余

RAID 3:容错校验

2.2 HDFS 的数据高可用机制

2.2.1 HDFS多副本

HDFS版本的RAID1

checksum检查

三副本,存储代价太大

优点

  • 读写路径简单
  • 副本修复简单
  • 高可用

2.2.2 Erasure Coding原理

HDFS版本的RAID 2/3

业界常用Reed Solomon算法 纠错码

四份数据生成六份数据

2.2.3 HDFS Erasure Coding

HDFS版本的RAID 2

和多副本比较

  • 读写速度
  • 成本
  • 修复速度
  • 读写路径的实现

图:直接保存的EC和 Stripe(条带化)后保存的EC

按照条带做EC:做修复时,无需计算整个块

2.3 考虑网络架构的数据高可用

2.3.1 网络架构

Server:一台服务器

机架(Rack):放服务器的架子。

TOR(Top of Rack): 机架顶部的交换机。服务整个Rack

数据中心(Data Center):集中部署服务器的场所

2.3.2 副本放置策略 - 机架感知

一个TOR故障导致整个机架不可用(高可用相当于没有) vs 降低跨rack流量

trade-off:一个本地、一个远端

图: HDFS的多机架放置

2.4案例:字节跳动的HDFS 多机房容灾方案简介

字节跳动的HDFS 集群,从单机房演进到双机房,再从双机房演进到更多的机房。

多机房解决的问题

  • 容量问题
  • 容灾问题(电缆被挖断)

HDFS 双机房放置的设计

  • 写入时,每个数据块在两个机房至少各有一个副本,数据实时写入到两个机房。
  • 读取时,优先读本地的副本,避免了大量的跨机房读取。

多机房容灾实践

多机房部署的组件

  • ZooKeeper(一般部署三机房)
  • BookKeeper
  • NameNode
  • DataNode

容灾期间的策略

  • 容灾期间,限制跨机房写入
  • 容灾期间,限制跨机房副本复制

03. 元数据高扩展性

3.1 元数据扩展性挑战

3.1.1元数据节点扩展性的挑战

HDFS NameNode是个集中式服务,部署在单个机器上,内存和磁盘的容量、CPU的计算力都不能无限扩展。

scale up vs. scale out

  • 扩容单个服务器的能力
  • 部署多个服务器来服务

挑战

  • 名字空间分裂
  • DataNode汇报
  • 目录树结构本身复杂

3.1.2常见的Scale Out方案

KV模型的系统可以使用 partition

  • Redis
  • Kafka
  • MySQL(分库分表)

三种数据路由方式

  • 服务端侧
  • 路由层
  • 客户端侧

目录树:不能按照KV存放

3.2 社区的解决方案

3.2.1社区解决方案-BlockPool,数据存储层扩展

解决DN同时服务多组NN的问题:

同一个block id在不同的NN上出现(互相不知道)

文件服务分层:两部分

  • Namespace:目录树结构,文件块ID
  • Block Storage

用blockpool来区分DN的服务

  • 数据块存储
  • 心跳和块上报

3.2.2社区解决方案 - viewfs,元数据

Federation架构:将多个不同集群组合起来,对外表现像一个集群一样。

viewfs通过在client-side的配置,指定不同的目录访问不同的NameNode。

局限性:运维复杂

3.3 字节跳动的NNProxy方案

3.3.1字节跳动的NNProxy

NNProxy主要实现了路由管理和RPC 转发·以及鉴权、限流、查询缓存等额外能力

NNProxy 所在系统上下游

3.3.2 NNProxy路由规则保存

三种数据路由方式

  • 服务端侧
  • 路由层
  • 客户端侧

考虑点:扩展性、运维性

路由规则的保存

3.3.3 NNProxy路由转发实现

目录树视图

路径最长匹配规则,可以进一步划分目录树

3.4案例:小文件问题

小文件问题(LSOF, lots of small files) :大小不到一个 HDFS Block 大小的文件过多

  • NameNode瓶颈
  • l/O变小,数据访问变慢
  • 计算任务启动慢

MapReduce 的 worker数量过多容易引起小文件问题(笛卡尔积)

解决方案:

  • 后台任务合并小文件
  • Shuffle service(缓存到内存中、聚合)

04. 存储数据高扩展性

4.1超大集群的长尾问题

4.1.1 延迟的分布和长尾延迟

延迟的分布:

  • 用百分数来表示访问的延迟的统计特征
  • 例如p95延迟为1ms,代表95%的请求延迟要低于1ms,但后5%的请求延迟会大于1ms

长尾延迟:尾部(p99/p999/p999)的延迟,衡量系统最差的请求的情况。会显著的要差于平均值

4.1.2 尾部延迟放大

木桶原理(短板)

  • 尾部延迟放大:访问的服务变多,尾部的请求就会越发的慢。

如何变慢

  • 固定延迟阈值
  • 固定延迟百分位

尾部延迟放大,整个服务被Backend 6拖累

4.1.3 长尾问题的表现-慢节点

慢节点:读取速度过慢,导致客户端阻塞。

慢节点的发生难以避免和预测

  • 共享资源、后台维护活动(GC...)、请求多级排队、功率限制(物理,空调坏了)
  • 固定的损耗:机器损坏率
  • 混沌现象

离线任务也会遇到长尾问题

  • 全部任务完成时间取决于最慢的任务什么时候完成。
  • 集群规模变大,任务的数据量变大。
  • 只要任何数据块的读取受到长尾影响,整个任务就会因此停滞。

集群扩大10倍,问题扩大N(>10)倍

慢请求---服务器数量曲线

4.2超大集群的可靠性问题

4.2.1 超大集群下的数据可靠性

  • 条件一:超大集群下,有一部分机器是损坏来不及修理的。
  • 条件二:副本放置策略完全随机。
  • 条件三:DN的容量足够大

推论:必然有部分数据全部副本在损坏的机器上,发生数据丢失。

估算:三副本,10000台机器,每台一百万副本。

  • 有多少种放置的组合数?
  • 损坏100台机器,会有多少副本丢失?

叠加长尾问题,容易导致整个任务无法执行下去。

4.2.2 Copyset

将DataNode分为若干个Copyset选块在copyset内部选择

原理:减少了副本放置的组合数,从而降低副本丢失的概率。