这是我参与「第四届青训营 」笔记创作活动的第9天
1. 元数据高可用
1.1. 高可用的需求
1.1.1. 服务高可用的需求
故障类型
- 硬件故障
- 软件故障
- 人为故障
灾难:数据中心级别不可用
- 机房断电
- 机房空调停机
- 机房间网络故障、拥塞
故障不可避免,灾难时常有发生
而如果HDFS系统不可用
- 无法核算广告账单,直接引发收入损伤
- 无法产生数据报表,数据驱动无从谈起
- 无法进行模型训练,用户体验越来越差
业务停止的损失极大,所以HDFS系统的高可用性就至关重要
1.1.2. 高可用的衡量
1.1.3. 可用性的年化
1.1.4. 高可用的形式
服务高可用:
- 热备份
- 冷备份
故障恢复操作
- 人工切换
- 自动切换
人工的反应、决策时间都更长,高可用需要让系统自动决策
HDFS的设计中,采用了中心化的元数据管理化节点NameNode
NameNode容易成为故障中的单点(single point of failure)
1.2. HDFS主备同步实现
1.2.1. HDFS NameNode高可用架构
组件介绍
- ActiveNameNode:主节点,提供服务,生产日志
- StandbyNameNode:备节点,消费日志
- ZooKeeper:为自动选主提供协调服务
- BookKeeper:提供日志存储服务
- ZFKC:NameNode探活,触发主备切换
- HA Client:提供了自动切换的客户端
- edit log:操作的日志
围绕三个问题来看高可用
- 节点状态如何保存
- 操作日志如何同步
- 如何做到自动切换
1.2.2. 理论基础 - 状态机复制和日志
1.2.3. NameNode 状态持久化
1.2.4. NameNode 操作日志的生产消费
Active 生产,Standby(可能有多个)消费
物理日志与逻辑日志
日志系统
- 高可用
- 高扩展性
- 高性能
- 强一致性(有序)
1.2.5. NameNode 块状态维护
区别
- Active 即接收,也发起变更
- Standby 只接收,不发起变更
Content Stale 状态
- 主备切换后,避免DN的不确定状态
1.3. HDFS自动主备切换
1.3.1. 分布式协调组件 - ZooKeeper
一般用于提供选主,协调,元数据存储
使用它的组件
- HDFS 、 YARN 、 HBase
- Kafka 、 ClickHouse
- 等等
HA 核心机制:Watch
1.3.2. 自动主备切换流程 - Server 侧
ZKFailoverController
作为外部组件,驱动HDFS NameNode的主备切换
轮询探活
脑裂问题
Fence 机制
1.3.3. 自动主备切换流程 - Client 侧
核心机制:StandbyException
Client 自动处理
1.4. 日志系统BookKeeper
1.4.1. BookKeeper架构
BookKeeper存储日志
- 低延时
- 持久性
- 强一致性
- 读写高可用
对比:日志系统和文件系统的复杂度
1.4.2. Quorum 机制
Quorum 机制:多副本一致性读写
场景:
- 多副本对象存储,用版本号标识数据新旧
规则
- Qr + Qw > Q
- Qw > Q / 2
1.4.3. BookKeeper Quorum
Sloppy Quorum机制
日志场景:顺序追加、只写
Write Quorum:写入副本数 Ack Quorum:响应副本数
1.4.4. BookKeeper Ensemble
Ensemble 机制
Round-Robin Load Balancer
- 第一轮:1,2,3
- 第二轮:2,3,4
- 第三轮:3,4,1
- 第四轮:4,1,2
2. 数据存储高可用
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 版本的RAID 1
优点
- 读写路径简单
- 副本修复简单
- 高可用
2.2.2. Erasure Coding 原理
HDFS 版本的RAID 2/3
业界常用Reed Solomon算法
2.2.3. Erasure Coding
HDFS 版本的RAID 2
和多副本比较
- 读写速度快
- 成本
- 修复速度
- 读写路径的实现
2.3. 考虑网络架构的数据高可用
2.3.1. 网络架构
机架(Rack):放服务器的架子
TOR(Top of Rack):机架顶部的交换机
数据中心(Data Center):集中部署服务器的场所
2.3.2. 副本放置策略 - 机架感知
一个TOR故障导致整个机架不可用 vs 降低跨rack流量
trade-off:一个本地、一个远端
2.4. 案例:字节跳动的HDFS多机房容灾方案介绍
2.4.1. 案例:字节跳动的HDFS多机房容灾实践
字节跳动的HDFS 集群,从单机房演进到双机房,再从双机房演进到更多的机房
多机房解决的问题
- 容量问题
- 容灾问题
HDFS 双机房放置的设计
- 写入时,每个数据块在两个机房至少各有一个副本,数据实时写入到两个机房
- 读取时,优先读取本地的副本,避免了大量的跨机房读取
2.4.2. 多机房容灾实践
多机房部署的组件
- Zookeeper
- BookKeeper
- NameNode
- DataNode
容灾期间的策略
- 容灾时期,限制跨机房写入
- 容灾时期,限制跨机房副本复制
3. 元数据高扩展性
3.1. 元数据扩展性挑战
3.1.1. 元数据节点扩展性的挑战
HDFS NameNode是个集中式服务,部署在单个机器上,内存和磁盘的容量、CPU的计算能力都不能无限扩展
scale up vs scale out
- 扩容单个服务器的能力
- 部署多个服务器来服务
挑战
- 名字空间分裂
- DataNode 汇报
- 目录树结构本身复杂
3.1.2. 常见的Scale Out方案
KV 模型的系统可以使用partition
- Redis
- Kafka
- MySQL(分库分表)
三种数据路由方式
- 服务端测
- 路由层
- 客户端侧
3.2. 社区的解决方案
3.2.1. 社区解决方案 - BlockPool
解决DN同时服务器多组NN的问题
文件服务分层
- Namespace
- Block Storage
用blockpool来区分DN的服务
- 数据块存储
- 心跳和块上报
3.2.2. 社区解决方案 - viewfs
Federation架构:将多个不同集群组合起来,对外表现像一个集群一样
viewfs通过在client-side的配置,指定不同的目录访问不同的NameNode
局限性:运维复杂
3.3. 字节跳动的NNProxy 方案
3.3.1. 字节跳动的NNProxy
NNProxy是ByteDance自研的HDFS代理层,提供了路由服务
- 于2016年开源,项目地址
- 开源社区的Router Based Federation在2017年上线
NNProxy主要实现了路由管理和RPC转发
- 以及鉴权、限流、查询缓存等额外能力
3.3.2. NNProxy 路由规则保存
3.3.3. NNProxy路由转发实现
路径最长匹配规则
- /
- /home
- /user/bob
- /user/tiger/warehouse
- /user/tiger/dump
3.4. 案例:小文件问题
小文件问题(LSOF,lots of small files):大小不到一个HDFS Block大小的文件过多
- NameNode瓶颈
- I/O变小,数据访问变慢
- 计算任务启动慢
MapReduce的worker数量过多容易引起小文件问题
解决方案
- 后台任务合并小文件
- Shuffle Service
4. 数据存储高扩展性
4.1. 超大集群的长尾问题
4.1.1. 延迟的分布和长尾延迟
4.1.2. 尾部延迟放大
木桶原理
- 尾部延迟放大
- 访问的服务变多,尾部的请求就会越发的慢