Chiriri's blog Chiriri's blog
首页
  • Java

    • JavaSE
    • JavaEE
    • 设计模式
  • Python

    • Python
    • Python模块
    • 机器学习
  • Golang

    • Golang
    • gRPC
  • 服务器

    • Linux
    • MySQL
    • NoSQL
    • Kubernetes
  • 项目

    • 传智健康
    • 畅购商城
  • Hadoop生态

    • Hadoop
    • Zookeeper
    • Hive
    • Flume
    • Kafka
    • Azkaban
    • Hbase
    • Scala
    • Spark
    • Flink
  • 大数据项目

    • 离线数仓
  • 青训营

    • 第四届青训营
  • HTML

    • HTML
    • JavaScript
  • Vue

    • Vue2
    • TypeScript
    • Vue3
    • Uni-APP
  • 数据结构与算法
  • C语言
  • 考研数据结构
  • 计算机组成原理
  • 计算机操作系统
  • Java基础

    • Java基础
    • Java集合
    • JUC
    • JVM
  • 框架

    • Spring
    • Dubbo
    • Spring Cloud
  • 数据库

    • MySQL
    • Redis
    • Elasticesearch
  • 消息队列

    • RabbitMQ
    • RocketMQ
  • 408

    • 计算机网络
    • 操作系统
    • 算法
  • 分类
  • 标签
  • 归档
  • 导航站
GitHub (opens new window)

Iekr

苦逼后端开发
首页
  • Java

    • JavaSE
    • JavaEE
    • 设计模式
  • Python

    • Python
    • Python模块
    • 机器学习
  • Golang

    • Golang
    • gRPC
  • 服务器

    • Linux
    • MySQL
    • NoSQL
    • Kubernetes
  • 项目

    • 传智健康
    • 畅购商城
  • Hadoop生态

    • Hadoop
    • Zookeeper
    • Hive
    • Flume
    • Kafka
    • Azkaban
    • Hbase
    • Scala
    • Spark
    • Flink
  • 大数据项目

    • 离线数仓
  • 青训营

    • 第四届青训营
  • HTML

    • HTML
    • JavaScript
  • Vue

    • Vue2
    • TypeScript
    • Vue3
    • Uni-APP
  • 数据结构与算法
  • C语言
  • 考研数据结构
  • 计算机组成原理
  • 计算机操作系统
  • Java基础

    • Java基础
    • Java集合
    • JUC
    • JVM
  • 框架

    • Spring
    • Dubbo
    • Spring Cloud
  • 数据库

    • MySQL
    • Redis
    • Elasticesearch
  • 消息队列

    • RabbitMQ
    • RocketMQ
  • 408

    • 计算机网络
    • 操作系统
    • 算法
  • 分类
  • 标签
  • 归档
  • 导航站
GitHub (opens new window)
  • Hadoop

  • Zookeeper

  • Hive

  • Flume

  • Kafka

  • Azkaban

  • Hbase

  • Scala

  • Spark

  • Flink

  • 离线数仓

  • 青训营

    • 第四届青训营

      • SQL Optimizer 解析| 青训营笔记
      • 流/批/OLAP 一体的 Flink 引擎介绍| 青训营笔记
      • Exactly Once 语义在 Flink 中的实现| 青训营笔记
      • 流式计算中的 Window 计算| 青训营笔记
      • Spark 原理与实践| 青训营笔记
      • 大数据 Shuffle 原理与实践| 青训营笔记
      • Presto 架构原理与优化介绍| 青训营笔记
      • HDFS 原理与应用| 青训营笔记
      • HDFS 高可用与高扩展性机制分析| 青训营笔记
        • 元数据服务高可用
          • 高可用的需求
          • 服务高可用的需求
          • 高可用的衡量
          • 可用性的年化
          • 高可用的形式
          • HDFS 主备同步实现
          • HDFS NameNode 高可用架构
          • 状态机复制和日志
          • NameNode 状态持久化
          • NameNode 操作日志的生产消费
          • NameNode 块状态维护
          • HDFS 自动主备切换
          • 分布式协调组件- ZooKeeper
          • 自动主备切换流程- Server 侧
          • 自动主备切换 - Client 侧
          • 高可用日志系统 BookKeeper
          • Quorum 机制
          • BookKeeper Quorum
          • BookKeeper Ensemble
        • 数据存储高可用
          • 单机存储的数据高可用机制
          • HDFS的数据高可用机制
          • HDFS 多副本
          • Erasure Coding(纠错码) 原理
          • HDFS Erasure Coding
          • 考虑网络架构的数据高可用
          • 故障域
          • 副本放置策略 - 机架感知
          • 案例:字节跳动的HDFS多机房容灾方案简介
          • 多机房容灾实践
        • 元数据高扩展性
          • 元数据扩展性挑战
          • 元数据节点扩展性的挑战
          • 常见的 Scale Out 方案
          • 社区的解决方案
          • 社区解决方案 - BlockPool
          • 社区解决方案 - viewfs
          • 字节跳动的 NNProxy 方案
          • NNProxy 路由规则保存
          • NNProxy 路由转发实现
          • 案例:小文件问题
        • 存储数据高扩展性
          • 超大集群的长尾问题
          • 延迟的分布和长尾延迟
          • 尾部延迟放大
          • 长尾问题的表现 - 慢节点
          • 超大集群的可靠性问题
          • Copyset
          • 超大集群的不均匀问题
          • 数据迁移工具速览
          • 数据迁移工具
          • DistCopy 工具
          • FastCopy 工具
          • Balancer 工具
      • 深入浅出 HBase 实战| 青训营笔记
      • 数据湖三剑客:Delta Lake、Hudi 与 Iceberg| 青训营笔记
      • 从 Kafka 到 Pulsar 的数据流演进之路| 青训营笔记
      • Parquet 和 ORC:高性能列式存储| 青训营笔记
      • LSMT 存储引擎浅析| 青训营笔记
      • 浅谈分布式一致性协议| 青训营笔记
      • 走进 YARN 资源管理和调度| 青训营笔记
      • 深入理解 K8S 资源管理和调度| 青训营笔记
      • 实时数据中心建设思路与企业实践| 青训营笔记
      • 用户数据分析理论与最佳实践| 青训营笔记
      • 大数据可视化理论与案例分析| 青训营笔记
  • DolphinScheduler

  • Doris

  • 大数据
  • 青训营
  • 第四届青训营
Iekr
2022-08-07
目录

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

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

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

# 元数据服务高可用

高可用:系统在困境(adversity,比如硬件故障、软件故障、人为错误)中仍可正常工作(正确完成功能,并能达到期望的性能水准)

容灾:在相隔较远的异地,建立两套或多套功能相同的系统,互相之间可以进行健康状态监视和功能切换,当一处系统因意外(如火灾、地震等)停止工作时,整个应用系统可以切换到另一处,使得该系统功能可以继续正常工作。

# 高可用的需求

# 服务高可用的需求

故障类型:

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

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

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

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

而如果 HDFS 系统不可用。

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

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

# 高可用的衡量

0a17df94-3482-400a-8912-26265023fb18

服务可用性指标:

  • MTTR(Mean Time To Repair):平均修复时间,系统能多快恢复。
  • MTTF(Mean Time To Failure):平均失效时间,运行到故障间的时间,一般用于不可修复的系统(制造业)。
  • MTBF(Mean Time Between Failures):平均无故障时间,两次故障间的间隔,一般用于可修复的系统(软件)。

# 可用性的年化

可用性:A=MTBFMTBF+MTTR

全年不可用时间:系统运行一整年的不可用时间的目标。

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

# 高可用的形式

服务高可用:

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

故障恢复操作:

  • 人工切换:在故障发生时,运维人员接收报警后,手动执行服务切主操作。一般较慢,难以满足全年不可用时间的目标。
  • 自动切换:通过探活组件、分布式共识协议等手段,系统能自动发现主服务的故障,并切换到备份不符。

人工的反应、决策时间都更长,高可用需要让系统自动决策。 HDFS 的设计中,采用了中心化的元数据管理节点 NameNode。 NameNode 容易成为故障中的单点(single point of failure) 。

单点故障 SPOF:指系统中一旦失效,就会让整个系统无法运作的组件。

# HDFS 主备同步实现

# HDFS NameNode 高可用架构

image-20220807211230345

  • Active NameNode:提供服务的 NameNode 主节点,生产 editlog。
  • Standby NameNode:不提供服务,起备份作用的 NameNode 备节点,消费 editlog
  • editlog:用户变更操作的记录,具有全局顺序,是 HDFS 的变更日志。
  • ZooKeeper:开源的分布式协调组件,主要功能有节点注册、主节点选举、元数据存储。
  • BookKeeper:开源的日志存储组件,存储 editlog
  • ZKFC:和 ZK、NN 通信,进行 NN 探活和自动主备切换。
  • HA Client:处理 StandbyException,在主备节点间挑选到提供服务的主节点。

围绕三个问题来看高可用:

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

# 状态机复制和日志

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

image-20220807211750250

  • 状态机:一个状态机从 “初始” 状态开始,每一个输入都被传入转换函数和输出函数,以生成一个新的状态和输出。在新的输入被接收到前,状态保持不变,而输出同时被传输给恰当的接受者。
  • 状态机复制:确定性的状态机具有「处理确定的输入后,状态唯一确定」的特性。状态机复制利用这个特性实现多个相同的状态机副本的同步更新。
  • 变更日志:触发状态机更新的变更操作,具有全局确定的顺序。
  • 共识协议:确保每个副本都能收到相同的日志的共识协议,常见的有 Paxos、Raft、ZAB。

# NameNode 状态持久化

image-20220807213654074

  • FSImage 文件:较大的状态记录文件,是某一时刻 NN 全部需要持久化的数据的记录。大小一般在 GB 级别。
  • EditLog 文件:是某段时间发生的变更日志的存储文件。大小一般在 KB~MB 级别。

image-20220807213708067

  • checkpoint 机制:将旧的 FSImage 和 EditLog 合并生成新的 FSImage 的流程,在完成后旧的数据可以被清理以释放空间。

# NameNode 操作日志的生产消费

Active 生产,Standby (可能有多个)消费

物理日志:存储了物理单元(一般是磁盘的 page)变更的日志形式。

逻辑日志:存储了逻辑变更(例如 rename /a to /b)的日志形式。

image-20220807213756081

日志系统

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

# NameNode 块状态维护

区别

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

Content Stale 状态

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

image-20220807214300838

  • 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 状态的引入解决了这个问题。

# HDFS 自动主备切换

# 分布式协调组件 - ZooKeeper

  • ZooKeeper 是广泛使用的选主组件,它通过 ZAB 协议保证了多个 ZK Server 的状态一致,提供了自身的强一致和高可用。
  • ZooKeeper 的访问单位是 znode,并且可以确保 znode 创建的原子性和互斥性(CreateIfNotExist)。client 可以创建临时 znode,临时 znode 在 client 心跳过期后自动被删除。
  • ZK 提供了 Watch 机制,允许多个 client 一起监听一个 znode 的状态变更,并在状态变化时收到一条消息回调(callback)。
  • 基于临时 znode 和 Watch 机制,多个客户端可以完成自动的主选举。
  • Hadoop 将集群主备选举的能力和 NN 的服务放在了不同的进程中,而更先进的系统一般会内置在服务进程中。

image-20220807214658850

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

ZKFailoverController:一般和 NN 部署在一起的进程,负责定时查询 NN 存活和状态、进行 ZK 侧主备选举、执行调用 NN 接口执行集群的主备状态切换、执行 fence 等能力。

image-20220807214811049

  • 脑裂问题:因为网络隔离、进程夯住(例如 Java GC)等原因,旧的 active NN 没有完成下主,新的 active NN 就已经上主,此时会存在双主。client 的请求发给两者都可能成功,但不能保证一致性(两个 NN 状态不再同步)和持久化(只能保留一个 NN 状态)。
  • fence 机制:在新 active NN 上主并正式处理请求之前,先要确保旧 active NN 已经退出主节点的状态。一般做法是先用 RPC 状态检测,发现超时或失败则调用系统命令杀死旧 active NN 的进程。

# 自动主备切换 - Client 侧

核心机制:StandbyException

Client 自动处理:

Client 的通过 RPC 的 Proxy 与 NameNode 交互。在 client 端会有两个代理同时存在,分别代表与 Active 和 Standby 的 NameNode 的连接。由于 Client 端有 Retry 机制,当与 Active NameNode 正常通信的 client proxy 收到 RPC 返回的 StandbyException 时,说明这个 Active NameNode 已经变成了 Standby 模式,所以触发 dfs.client.failover.proxy.provider.[nameservice ID] 这个参数指定的类来做 failover,目前唯一的实现是 ConfiguredFailoverProxyProvider,实现方法就是下次开始把 RPC 发向另外一个 NameNode。此后的 RPC 都是发往另外一个 NameNode,也就是 NameNode 发生了主从切换。

# 高可用日志系统 BookKeeper

image-20220807215646198

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

# Quorum 机制

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

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

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

image-20220807220842217

规则:

  1. Qa+Qw>Q
  2. Qw>Q2

# BookKeeper Quorum

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

  • 日志写入是追加,不是状态变更,只需要确认目前的 entry-id,相对更简单。
  • Write Quorum:一次写入需要写入到的存储节点数。
  • Ack Quorum:一次写入需要收到的响应数,小于 write quorum。
  • 高性能:不用等所有副本写入成功,降低了的长尾延迟(后文会再次介绍长尾延迟)。

image-20220807221426650

# BookKeeper Ensemble

Ensemble:通过轮询(Round-Robin)来确认 write quorum 实际对应的存储节点实例,可以比较简单的完成副本放置和扩展。

Round-Robin Load Balancer

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

image-20220807221928791

优势:数据均衡

# 数据存储高可用

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

RAID 方案

RAID:将多个廉价、不可靠、低性能、容量小的磁盘组装在一起,提供高可靠、高性能、大容量逻辑磁盘服务的一组磁盘列阵方案。

  • RAID 0 :将数据分块后按条带化的形式分别存储在多个磁盘上,提供大容量、高性能。 0e95672b-af6a-4679-8db9-7e83bb6fe33c
  • RAID 1:将数据副本存储在多个磁盘上,提供高可靠。 a3d6dbd6-5f14-41f9-8d21-5daba36efd5f
  • RAID 3:在数据分块存储的基础上,将数据的校验码存储在独立的磁盘上,提供高可靠、高性能。 f8182a97-caa5-4bea-a3c0-0db30e4bff57
  • 其他可以参考 RAID (opens new window)

# HDFS 的数据高可用机制

# HDFS 多副本

多副本方案:将数据块存储在多个 DN 上,HDFS 版本的 RAID 1

image-20220807222714267

优点

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

# Erasure Coding(纠错码) 原理

Erasure Coding 方案:将数据分段,通过特殊的编码方式存储额外的校验块,并条带化的组成块,存储在 DN 上。HDFS 版本的 RAID 2/3

  • Reed Solomon 算法:参考 Reed-solomon codes (opens new window) image-20220807222821749

# HDFS Erasure Coding

HDFS 版本的 RAID 2

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

  • 条带化:原本块对应文件内连续的一大段数据。条带化后,连续的数据按条带(远小于整个块的单位)间隔交错的分布在不同的块中。
  • 成本更低:多副本方案需要冗余存储整个块,EC 方案需要冗余存储的数据一般更少。

image-20220807223838860

和多副本比较

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

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

  • 机架 / 机柜:将几个服务器统一供电、提供对外网络的固定的物理设备。

  • TOR top of rack:机架顶部(或底部)的交换机,负责机架内服务器和数据中心的其他服务器的网络通信。

  • 机房和数据中心都是指大量服务器集中放置的场所。

    • 机房:强调的基础设施建设,例如物理承重、空调、防水、消防。
    • 数据中心:强调机房的业务属性。
  • 网络拓扑:按数据中心 -> 机架 -> 机器的顺序,描述进程在网络空间中所处的位置。 image-20220807224218482

  • 跨机房专线:由网络服务商提供,连接机房的专用网络。

    • 稳定性和安全性好于公网。
    • 相比于数据中心内网络,吞吐更为有限、延迟更高、成本更高。

# 故障域

  • 故障域是基础设施中可能发生故障的区域或组件。每一个域都有自己的风险和挑战,由个别几个因素决定整个故障域的服务能力,需要进行架构。
  • 机架感知:以 TOR 为关键点,机架是一个故障域。数据副本全部放置在一个机架中,当相应 TOR 故障时数据就无法访问。
  • 机房感知:以机房的基础设施(空调、电力)和跨机房专线为关键点,它们发生故障时整个机房会发生故障,导致不可用。

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

一个 TOR 故障导致整个机架不可用 vs 降低跨 rack 流量

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

HDFS 的多机架放置:

image-20220807224515796

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

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

多机房解决的问题

  • 容量问题
  • 容灾问题

HDFS 双机房放置的设计

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

image-20220807224742624

# 多机房容灾实践

多机房容灾:服务和数据需要存放在多个机房,并配合合理的架构。使得发生机房故障时依然可以提供服务。

多机房部署的组件

  • ZooKeeper
  • BookKeeper
  • NameNode
  • DataNode

容灾期间的策略

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

# 元数据高扩展性

# 元数据扩展性挑战

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

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

scale up vs. scale out

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

扩展性方案

  • scale up:通过单机的 CPU、内存、磁盘、网卡能力的提升来提升系统服务能力,受到机器成本和物理定律的限制。
  • scale out:通过让多台机器组成集群,共同对外提供服务来提升系统服务能力。一般也称为高扩展、水平扩展。

image-20220807225153958

挑战

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

# 常见的 Scale Out 方案

KV 模型的系统可以使用 partition

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

partition 方法

  • 水平分区和垂直分区:水平分区指按 key 来将数据划分到不同的存储上;垂直分区指将一份数据的不同部分拆开存储,用 key 关联起来。partition 一般都水平分区,又称 shard。
  • 常用于 KV 模型,通过 hash 或者分段的手段,将不同类型 key 的访问、存储能力分配到不同的服务器上,实现了 scale out。
  • 重点:不同单元之间不能有关联和依赖,不然访问就难以在一个节点内完成。例如 MySQL 的分库分表方案,难以应对复杂跨库 join。

三种数据路由方式

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

image-20220807225338959

# 社区的解决方案

# 社区解决方案 - BlockPool

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

文件服务分层

  • Namespace
  • Block Storage

image-20220807225541822


用 blockpool 来区分 DN 的服务

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

blockpool

  • 将文件系统分为文件层和块存储层,对于块存储层,DN 集群对不同的 NN 提供不同的标识符,称为 block pool。
  • 解决了多个 NN 可能生成同一个 block id,DN 无法区分的问题。

# 社区解决方案 - viewfs

federation 架构

  • 使得多个集群像一个集群一样提供服务的架构方法,提供了统一的服务视图,提高了服务的扩展性。
  • 文件系统的目录树比 kv 模型更复杂,划分更困难。
  • 邦联架构的难点一般在于跨多个集群的请求,例如 HDFS 的 rename 操作就可能跨多个集群。

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

image-20220807230225776

viewfs

  • 邦联架构的一种实现,通过客户端配置决定某个路径的访问要发送给哪个 NN 集群。
  • 缺点:客户端配置难以更新、本身配置方式存在设计(例如,只能在同一级目录区分;已经划分的子树不能再划分)。

# 字节跳动的 NNProxy 方案

NNProxy

  • ByteDance 自研的 HDFS 代理层,于 2016 年开源,项目地址: github.com/bytedance/n… (opens new window)
  • 主要提供了路由管理、RPC 转发,额外提供了鉴权、限流、查询缓存等能力。
  • 开源社区有类似的方案 Router Based Federation,主要实现了路由管理和转发。

NNProxy 所在系统上下游:

image-20220807230319568

# NNProxy 路由规则保存

三种数据路由方式

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

路由规则的保存:

image-20220807230651817

# NNProxy 路由转发实现

路径最长匹配规则

  • /
  • /home
  • /user/bob
  • /user/tiger/warehouse
  • /user/tiger/dump

匹配最长的路径 转发到具体的 namenode 节点上

image-20220807230848324

# 案例:小文件问题

小文件问题(LSOF,lots of small files):

  • HDFS 设计上是面向大文件的,小于一个 HDFS Block 的文件称为小文件。大小不到一个 HDFSBlock 大小的文件过多。
  • 元数据问题:多个小文件相对于一个大文件,使用了更多元数据服务的内存空间。NameNode 瓶颈
  • 数据访问问题:多个小文件相对于一个大文件,I/O 更加的随机,无法顺序扫描磁盘。I/O 变小,数据访问变慢
  • 计算任务启动慢:计算任务在启动时,一般会获得所有文件的地址来进行 MapReduce 的任务分配,小文件会使得这一流程变长。
  • 典型的 MR 流程中,中间数据的文件数和数据量与 mapper*reducer 的数量成线性,而为了扩展性,一般 mapper 和 reducer 的数量和数据量成线性。于是,中间数据的文件数和数据量与原始的数据量成平方关系。

MapReduce 的 worker 数量过多容易引起小文件问题

image-20220807231212068

解决方案:

  • 小文件合并任务:计算框架的数据访问模式确定,可以直接将小文件合并成大文件而任务读取不受影响。通过后台运行任务来合并小文件,可以有效缓解小文件问题。通过 MapReduce/Spark 框架,可以利用起大量的机器来进行小文件合并任务。
  • Shuffle service:shuffle 流程的中间文件数是平方级的,shuffle service 将 shuffle 的中间数据存储在独立的服务上,通过聚合后再写成 HDFS 文件,可以有效地缓解中间数据的小文件问题。

# 存储数据高扩展性

# 超大集群的长尾问题

长尾

  • 二八定律:在任何一组东西中,最重要的只占其中一小部分,约 20%,其余 80% 尽管是多数,却是次要的。
  • 长尾:占绝大多数的,重要性低的东西就被称为长尾。

百分位延迟

  • 将所有请求的响应速度从快到慢排序,取其中某百分位的请求的延迟时间。
  • 例如 pct99 代表排在 99% 的请求的延迟。相对于平均值,能更好的衡量长尾的情况。

# 延迟的分布和长尾延迟

延迟的分布:

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

image-20220807231732587

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

image-20220807231758667

# 尾部延迟放大

  • 木桶原理:并行执行的任务的耗时取决于最慢的一个子任务。
  • 尾部延迟放大:一个请求或任务需要访问多个数据节点,只要其中有一个慢,则整个请求或任务的响应就会变慢。
  • 固定延迟阈值,访问的集群越大, 高于该延迟的请求占比越高。
  • 固定延迟百分位,访问的集群越大,延迟越差。

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

image-20220807232017379

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

长尾问题

  • 尾部延迟放大 + 集群规模变大,使得大集群中,尾部延迟对于整个服务的质量极为重要。
  • 慢节点问题:网络不会直接断联,而是不能在预期的时间内返回。会导致最终请求不符合预期,而多副本机制无法直接应对这种问题。读取速度过慢,导致客户端阻塞。
  • 高负载:单个节点处理的请求超过了其服务能力,会引发请求排队,导致响应速度慢。是常见的一个慢节点原因。

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

  • 共享资源、后台维护活动、请求多级排队、功率限制
  • 固定的损耗:机器损坏率
  • 混沌现象

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

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

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

# 超大集群的可靠性问题

数据可靠性

  • 超大集群下,一定有部分机器是损坏的,来不及修理的。
  • 随机的副本放置策略,所有的放置组合都会出现。而 DN 容量够大,足够
  • 三副本,单个 DN 视角:容量一百万,机器数量一万。那么另外两个副本的排列组合有一亿种,容量比放置方案大约百分之一。
  • 三副本,全局视角:一万台机器,每台一百万副本,损坏 1%(100 台)。根据排列组合原理,大约有 1009998/(1000099999998)(100000010000)=9704 个坏块
  • callback 一下,叠加长尾问题。每个任务都要访问大量的块,只要一个块丢失就整个任务收到影响。导致任务层面的丢块频发,服务质量变差。

# Copyset

copyset

  • 降低副本放置的组合数,降低副本丢失的发生概率。
  • 修复速度:DN 机器故障时,只能从少量的一些其他 DN 上拷贝数据修复副本。

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

image-20220807232849906

# 超大集群的不均匀问题

负载均衡的意义

  • 避免热点

    • 机器热点会叠加长尾问题,少数的不均衡的热点会影响大量的任务。
  • 成本:

    • 数据越均衡,CPU、磁盘、网络的利用率越高,成本更低。
    • 集群需要为数据腾挪预留的空间、带宽更少,降低了成本。
  • 可靠性

    • 全速运行的机器和空置的机器,以及一会全速运行一会空置的机器,可靠性表现都有不同。负载均衡可以降低机器故障的发生。
    • 同一批机器容易一起故障,数据腾挪快,机器下线快,可以提升可靠性。

负载均衡性影响因素:多个复杂因素共同影响负载均衡性

  • 不同节点上的业务量的平衡
  • 数据放置策略
  • 数据搬迁工具的能力
  • 系统环境

集群的不均衡情况

  • 节点容量不均:机器上的数据量不均衡。

    • 原因可能是各种复杂情况导致,归根结底是混沌现象。
  • 数据新旧不均:机器上的数据新旧不均匀。

    • 例如:新上线的机器,不做任何数据均衡的情况下,只会有新写入的数据。而一般新数据更容易被读取,更为「热」。
  • 访问类型不均:机器上的数据访问类型不均。

    • 例如:机器学习训练需要反复读取数据,小 I/O 更多。而大数据场景一般只扫描一次,大 I/O 为主。这两种模式的读写比不同,I/O pattern 不同,就来带访问冷热的不同。
  • 异构机器:有的机器配置高、有的机器配置低,不考虑异构情况的话配置高的机器会闲置,配置低的机器会过热。

  • 资源不均:机器上的访问请求吞吐、IOPS 不均衡,导致最终机器冷热不均、负载不均。一般由于容量不均、新旧不均、模式不均导致

image-20220807233404137

# 数据迁移工具速览

需要数据迁移的典型场景

  • DN 上线:新上线的机器没有任何数据,而且只会有新数据写入。需要迁移其他 DN 的旧数据到新 DN 上,使得负载和数据冷热均衡。
  • DN 下线:需要下线的机器,需要提前将数据迁移走再停止服务,避免数据丢失的风险。
  • 机房间均衡:因为资源供应、新机房上线等外部条件,机房规划、业务分布等内部条件,不同机房的资源量和资源利用率都是不均衡的。需要结合供应和业务,全局性的进行资源均衡。
  • 日常打散:作为日常任务运行,不断地从高负载、高容量的机器上搬迁数据到低负载、低容量的机器上,使得整个集群的负载均衡起来。

# 数据迁移工具

  • 目的:将数据从一部分节点搬迁到另一部分节点。
  • 要求:高吞吐、不能影响前台的服务。

带元数据迁移的迁移工具

  • 痛点:涉及到元数据操作,需要停止用户的写入。
# DistCopy 工具

DistCopy

  • 通过 MapReduce 任务来并行迁移数据,需要拷贝数据和元数据。
  • 网络流量较大,速度较慢。
# FastCopy 工具

FastCopy

  • 前提条件:新集群的 DN 列表吻合

  • 基于 hardlink 和 blockpool 的原理

    • hardlink:直接让两个路径指向同一块数据。
  • 元数据直接在 NN 集群间拷贝,而数据则在 DN 上的不同 blockpool(对应到 NN 集群)进行 hardlink,不用数据复制。

    • 对于元数据,直接复制目录树的结构和块信息。
    • 对于数据块,直接要求 DataNode 从源 BlockPool hardlink 到目标 BlookPool,没有数据拷贝。
  • 迁移速度要大大优于 DistCopy。

# Balancer 工具

Balancer

  • 代替 NN 向 DN 发起副本迁移的命令,批量执行副本迁移。
  • 场景:大规模数据平衡、机器上下线。

image-20220807233820623

编辑 (opens new window)
上次更新: 2023/12/06, 01:31:48
HDFS 原理与应用| 青训营笔记
深入浅出 HBase 实战| 青训营笔记

← HDFS 原理与应用| 青训营笔记 深入浅出 HBase 实战| 青训营笔记→

最近更新
01
k8s
06-06
02
进程与线程
03-04
03
计算机操作系统概述
02-26
更多文章>
Theme by Vdoing | Copyright © 2022-2025 Iekr | Blog
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式