这是我参与「第四届青训营 」笔记创作活动的第9天
元数据服务高可用需求
- 故障类型:硬件/软件/人为
- 灾难:数据中心级别不可用,比如机房断电,机房空调停机,机房间网络故障或者拥塞
服务可用性的衡量指标
- MTTR(Mean Time To Repair):平均修复时间,指系统从发生故障到维修结束之间的时间段的平均值。
- MTTF(Mean Time To Failure):平均失效时间,指系统两次故障发生时间之间的时间段的平均值,一般用于不可修复的系统(制造业)。
- MTBF(Mean Time Between Failures):平均无故障时间,两次故障间的间隔,一般用于可修复的系统(软件)
可用性的计算公式: Availability=
备份方式
- 冷备份:备份服务的数据,可以和数据归档相结合。在主服务故障时,利用备份的数据重启。
- 热备份:主服务和备服务同时运行,在主服务故障时,随时可以切换到备服务。
HDFS NameNode的高可用架构
-
组件介绍
- ActiveNameNode:主节点,提供服务,生产日志
- StandbyNameNode:备节点,消费日志
- ZooKeeper:为自动选主提供统一协调服务
- BookKeeper:提供日志存储服务
- ZKFC:NameNode探活、触发主备切换
- HA Client:提供了自动切换的客户端
- EditLog:操作的日志
-
三个问题
- 节点状态如何保存
- 操作日志如何同步
- 如何做到自动切换
理论基础 - 状态机复制和日志
状态机复制是实现容错的常规方法
组件:
- 状态机及其副本
- 变更日志
- 共识协议
分布式协调组件-ZooKeeper
一般用于提供选主、协调、元数据存储
- 使用它的组件
- HDFS、YARN、HBase
- Kafka、ClickHouse
- HA核心机制:watch(可以让客户端监控到ZooKeeper上存储的节点,发生变化的时候ZooKeeper会通知)
自动主备切换流程
- Server侧
- ZKFC(ZooKeeperFailoverController):作为外部组件,驱动HDFS NameNode的主备切换
- 轮训探活:定时向Server发送RPC请求检查状态
- 脑裂问题:多节点认为自己都是active
- Fence机制:阻止多个节点写同样的日志,避免脑裂
- Client侧
- 核心机制:StandbyException:
依次轮询发送,若Client给Standby发请求,Standby会返回StandbyException,Client会自动找其他节点,直至寻找到ActiveNameNode,再把请求发给它
- 核心机制:StandbyException:
高可用日志系统BookKeeper架构
- bookkeeper存储日志
- 低延时
- 持久性
- 强一致性
- 读写高可用
- 日志系统和文件系统复杂度
Bookkeeper Quorum机制
- Quorum机制:多副本一致性读写
- 场景:多副本对象存储,用版本号标识数据新旧
- 规则:
- 日志场景比对象保存更简单,因为只追加而不会对对象进行反复修改
sloppy quorum机制(不那么严格的quorum协议):
可以调整以下参数,想要可用性更好可以把写入副本数调高,想要一致性更好可以把响应副本数调高
- write quorum 写入副本数:不需同时写完ACK
- ack quorum 响应副本数:只需要部分副本响应即可
Bookkeeper Ensemble机制
- Ensemble机制:round-robin load balancer
- 4机器写入3副本:第一轮123,第二轮234,第三次341,第四次412...
- 轮流写入,数据均衡
数据存储高可用
单机存储的数据高可用机制
RAID (Redundant Array of Independent Disks) 将多个廉价、不可靠、低性能、容量小的磁盘组装在一起,提供高可靠、高性能、大容量逻辑磁盘服务的一组磁盘列阵方案,比如:
- RAID 0: 条带化。将数据分块后按条带化的形式分别存储在多个磁盘上,提供大容量、高性能
- RAID 1: 冗余。将数据副本存储在多个磁盘上,提供高可靠
- RAID 3: 容错校验。在数据分块存储的基础上,将数据的校验码存储在独立的磁盘上,提供高可靠、高性能
HDFS 的数据高可用机制
- 多副本:将数据块存储在多个 DN 上
- 优点:读写路径简单,副本修复简单,高可用
- Erasure Coding 方案:将数据分段,通过特殊的编码方式存储额外的校验块,并条带化的组成块,存储在 DN 上。
元数据扩展问题
- HDFS NameNode是集中式服务,部署在单个机器上,内存和磁盘的容量、CPU的计算力都不能无限扩展
- scale up:扩容单个服务器的能力
- scale out:部署多个服务器来服务
常见的scale-out方案:KV模型的系统可用partition方法(redis, Kafka, MySQL分库分表) - 挑战:
- Namespace分裂:目录树分裂成很多小目录数
- DataNode汇报:NameNode如何负责DataNodes
- 目录树结构本身复杂
社区解决方案
- BlockPool:解决DN同时服务多组NN的问题;同一个block id在不同的NN出现
- 文件服务分层:Namespace;Block Storage
- 用blockpool来区分DN的服务:数据块存储;心跳和块上报
- viewfs:将多个不同集群组合起来,对外表现得像一个集群一样;指定不同的目录访问不同的NameNode