这是我参与「第四届青训营 」笔记创作活动的第8天
HDFS总体回顾:
HDFS通过将文件分块来存储大文件,HDFS的组件有NameNode和DataNode,分别负责提供元数据和数据服务。
在读写数据时,HDFS客户端需要先从NameNode上获取数据读取/写入的DataNode地址,然后和DataNode交互来完成数据读/写。
1. 元数据高可用
2. 数据存储高可用
3. 元数据高扩展性
4. 数据存储高扩展性
1. 元数据高可用
1.1.1 高可用的需求
故障类型:硬件、软件、人为。
灾难:数据中心不可用。(机房断电、机房空调停机、机房网络故障、拥塞)
故障不可避,灾难有时发生。
1.1.2 高可用的衡量
MTTR:平均恢复时间(mean time to recovery)
MTTF:平均无故障时间/平均故障前时间(mean time to failures)
MTBF:平均无故障工作时间
可用性的年化
-可用性99.9%,全年8.76小时不可用
-可用性99.99%,全年52.6min不可用
-可用性99.999%,全年5.26min不可用
1.1.3 高可用的形式
服务高可用:热备份、冷备份
故障恢复操作:人工切换、自动切换
人工的反应、决策时间都更长,高可用需要让系统自动决策。
HDFS的设计中,采用了中心化的元数据管理节点NameNode。NameNode容易成为故障中的单点(NameNode挂了就整个服务无法使用)。
1.2 HDFS主备同步实现
1.2.1 HDFS NameNode高可用架构
组件介绍:
-ActiveNamenode:主节点,提供服务,生产日志
-StandbyNamenode:备节点,消费日志
-ZooKeeper:为自动选主提供统一的协调服务
-BookKeeper:提供日志存储服务
-ZKFC:NameNode探活、触发主备切换
-HA Client:提供了自动切换的客户端
-edit log:操作日志
围绕三个问题来看高可用:
-节点状态如何更新
-操作日志如何同步
-如何做到自动切换
1.2.2理论基础-状态机复制和日志
状态机复制是实现容错的常规方法。
组件:
-状态机以及其副本
-变更日志
-共识协议(保证所有状态机收到 一致的日志)
状态机一般是存在盘上的数据库。
1.2.3 NameNode操作日志的生产消费
目录树和文件信息的更新
Active生产,Standby消费
物理日志和逻辑日志
日志系统:
-高可用
-高扩展性
-高性能
-强一致(有序)
FSImage:目录树,各个节点的子节点、父节点有哪些,每个节点中块的id
Edlog:存在分布式的日志系统上
1.2.4 NameNode块状态维护
回顾:
-DataNode Heartbeat,保持与Namenode的通信,说明存活
-DataNode Block Report
区别:
-Active既接收也发起变更
-Standby只接收,不变更
Content Stale状态:主备切换后,避免DN的不确定状态
1.3 HDFS自动主备切换
1.3.1 分布式协调组件-ZooKeeper
一般用于提供选主、协调、元数据存储
使用它的组件:
-HDFS、YARN、HBase
-Kafka、ClickHouse
HA核心机制:Watch
1.3.2 自动主备切换流程-Server侧
轮询探活
脑裂问题
Fence机制
ZKFailoverController:作为外部组件,驱动HDFS NameNode的主备切换
1.3.3 自动主备切换流程-Client侧
核心机制:StandbyException
Client自动处理
1.4 日志系统BookKeeper简介
1.4.1 BookKeeper
BookKeeper存储日志:低延时、持久、强一致、读写高可用
对比:日志系统和文件系统的复杂度
1.4.2 Quorum机制
多副本的一致性读写。
场景:多副本对象存储
日志场景比对象保存更简单
1.4.3 BookKeeper Quorum
Sloppy Quorum机制
日志场景:顺序追加、只写
Write Quorum:写入副本数
Ack Quorum:响应副本数
思考:Client挂掉导致不确认写入了多少数据?如何恢复?
1.4.4 BookKeeper Ensenmble
Ensemble机制
Round-Robin Load Balancer
-第一轮:1,2,3
-第二轮:2,3,4
-第三轮:3,4,5
-第四轮:4,1,2
数据均衡
2. 数据存储高可用
2.1 单机存储的数据高可用
单机存储-RAID
RAID0:条带化
RAID1:冗余
RAID3:容错校验
2.2 HDFS的数据高可用机制
2.2.1多副本放置(HDFS版本的RAID1)
2.2.2 Erasure Coding原理(HDFS版的RAID0/RAID3)
业界常用Reed Solomon算法
下图为直接保存的EC和Stripe(条带化)后保存的EC
和多副本比较:
-读写速度
-成本
-修复速度
-读写路径
2.3 考虑网络架构的数据高可用
2.3.1 副本放置策略-机架(Rack)感知
-一个TOR故障导致整个机架不可用
-尽量减少rack之间的传输
Trade-off:一个本地、一个远端
下图为HDFS的多机架放置
2.4 案例:字节跳动的HDFS多机房容灾方案简介
多机房问题:容量问题、容灾问题
HDFS双机房放置设计:
-写入时,每个数据块在两个机房至少各有一个副本,数据实时写入到两个机房
-读取时,优先读本地的副本,避免了大量的跨机房读取
多机房部署组件
-ZooKeeper
-BookKeeper
-NameNode
-DataNode
容灾期间(一个机房出错)的策略:限制跨机房写入、限制跨机房副本复制。
3. 元数据高扩展性
3.1.1 元数据扩展性挑战
HDFS NameNode是个集中式服务,部署在单个机器上,内存和磁盘的容量、CPU的计算力都不能无线扩展。
Scale up:扩容单个服务器的能力
Scale out:部署多个服务器来服务
挑战:
-名字空间分裂
-DataNode汇报
-目录树结构本身复杂
3.1.2 常见Scale Out方案
KV模型的系统可以使用partition
-Redis
-Kafka
-MySQL(分库分表)
三种路由方式:
-服务端侧
-路由层
-客户端侧
3.2 社区的解决方案
3.2.1 Blockpool
解决DN同时服务多组NN的问题
-同一个block id在不同的NN上出现
文件服务分层:
-Namespace
-Block Storage
用blockpool来区分DN服务
-数据块存储
-心跳和块上报
3.2.2 viewfs
Federation架构:将多个不同集群组合起来,对外表现像一个集群一样。
通过在client-side的配置,制定不同的目录访问不同的NameNode。
3.3 字节跳动的NNProxy方案
NNProxy是ByteDance自研的HDFS代理层,提供了路由服务。
项目地址:github.com/bytedance/nnproxy
路由管理、RPC转发。
3.3.1 NNProxy路由规则保存
3.3.2 路由转发实现
路劲最长匹配骨子额,可以进一步划分目录树。
跨集群rename。
3.4 案例:小文件问题
小文件问题;大小不到一个HDFS Block大小的文件过多:
-NameNode瓶颈
-I/O变成小的随机IO,数据访问变慢
-计算任务启动慢
解决方案:后台任务合并小文件、shuffle service
4.数据存储高扩展性
4.1 超大集群的长尾问题
延迟的分布:
-用百分数来表示访问的延迟的统计特征
-例如p95延迟为1ms,代表95%的请求延迟要地狱1ms,但后5%的请求延迟会大 于1ms。
长尾延迟:尾部(p99/p999/p9999)的延迟,衡量系统最差的请求情况。会显著差于平均值。
延迟长尾:
延迟分布:
尾部延迟放大:访问的服务变多,尾部的请求就会越发的慢。
慢节点:读取速度过慢,导致客户阻塞。
集群扩大10倍,问题会扩大N(N>10)倍
4.2 超大集群的可靠性问题
条件一:超大集群下,一部分机器是来不及修理的
条件二:副本放置策略完全随机
条件三:DN的容量足够大
推论:必然有本分数据的全部副本在损坏的机器上,发生数据丢失。
Copyset方案:将DataNode分为若干Copyset选块在copyset内部选择。
减少了放置副本的组合数,从而降低了副本丢失的概率。
也是有缺陷的,修复变慢,数据丢失的概率降低,但一旦丢失会丢失更多数据。
4.3 超大集群的不均匀问题
负载均衡:避免热点,可靠性,降低成本
节点容量不均、数据新旧不均匀、访问类型不均匀
4.4 数据迁移工具预览
跨NN迁移
Distcopy:
-基于MapReduce,通过一个个任务,将数据从一个NameNode拷贝到另一个 NameNode
-需要拷贝数据,流量大,速度较慢
FastCopy:
-开源社区的无需拷贝数据的快速元数据迁移方案
-前提条件:新旧集群的DN列表吻合
-对于元数据,直接复制目录树的结构和块信息
-对于数据块,直接要求DataNode从源BlockPool hardlink到目标BlookPool, 没有数据拷贝
-hardlink:直接让两个路径指向同一块数据
Balancer:
向DN发起迁移命令,平衡各个DN的容量
场景:单机房、多机房、限流措施
评价标准:稳定性成本、可运维性、执行效率