土法炼钢兴趣小组的算法知识备份

【存储工程】云块存储架构

文章导航

分类入口
storage
标签入口
#cloud-block-storage#ebs#essd#distributed-block-storage#iops#throughput#cloud-disk

目录

在上一篇延迟分析中,我们把存储 I/O 路径拆成了七层,逐层度量延迟。但那个模型有一个隐含假设——块设备就在本机。把存储搬到云上之后,块设备层下面多了一整套分布式系统:网络传输、多副本复制、远端 SSD 集群、元数据服务。一次 4 KB 随机读在本地 NVMe SSD 上大约 70-120 微秒,但在云盘上通常要 100-200 微秒(EBS gp3)甚至更高。延迟多出来的部分去了哪里?

这个问题不只是”多了网络延迟”这么简单。云块存储是一个完整的分布式存储系统,涉及数据分片、三副本写入、日志结构合并、后台垃圾回收、跨可用区复制等机制,每一层都会引入延迟和抖动。理解这些机制,才能解释为什么云盘的 IOPS 有上限、为什么延迟有基线、为什么突发性能会耗尽、为什么 fio 测出来的数字和官方标称不一致。

本文从分布式块存储的通用架构开始,分析 AWS EBS 和阿里云 ESSD 两个主流实现的公开架构细节,然后拆解云盘性能规格的含义,给出 fio 性能测试的正确方法,最后讨论云盘选型和成本优化策略。

说明: 云厂商的内部架构并不完全公开。本文的架构分析基于 AWS re:Invent 演讲、AWS 官方博客、阿里云存储团队的公开论文和技术博客、以及 USENIX/FAST 等学术会议的相关论文。涉及推测或综合判断的部分会明确标注。


一、分布式块存储通用架构

1.1 为什么不能直接用本地盘

本地盘(Instance Store / 本地 NVMe SSD)的问题很明确:

云块存储的核心目标就是解耦计算和存储:计算节点(EC2 / ECS)通过网络访问远端的存储集群,存储集群负责数据的持久化、冗余和弹性扩容。代价是每次 I/O 都要经过网络,延迟不可避免地增加。

1.2 通用架构三层模型

几乎所有云厂商的块存储系统都遵循类似的三层架构:

graph TB
    subgraph 计算节点
        A[虚拟机 / 容器] --> B[块设备前端<br/>virtio-blk / NVMe-oF]
    end

    subgraph 存储接入层
        B -->|RDMA / TCP| C[BlockClient<br/>路由 + 分片]
    end

    subgraph 存储集群
        C --> D1[存储节点 1<br/>ChunkServer]
        C --> D2[存储节点 2<br/>ChunkServer]
        C --> D3[存储节点 3<br/>ChunkServer]
    end

    subgraph 控制面
        E[元数据服务<br/>Partition Map] -.-> C
        E -.-> D1
        E -.-> D2
        E -.-> D3
    end

这张图展示了分布式块存储的四个核心组件:

块设备前端(Block Frontend)。 运行在计算节点上,负责把虚拟机的块 I/O 请求转换成网络请求。早期实现用 virtio-blk 协议,现在高性能场景普遍用 NVMe over Fabrics(NVMe-oF)或自研协议。前端还负责 I/O 的分片——把一个大 I/O 按分片边界拆成多个小请求,分别发往不同的存储节点。

存储接入层(Block Client / Proxy)。 有些架构把分片逻辑放在独立的代理节点上(如早期的 Ceph RBD 通过 RADOS Gateway),有些直接嵌入计算节点的内核或用户态驱动里。接入层持有分片映射表(Partition Map),知道每个数据分片存在哪几个存储节点上。

存储节点(Chunk Server / Storage Server)。 实际存储数据的节点,每个节点管理多块本地 SSD。存储节点内部通常采用日志结构写入(Log-Structured Write)——所有写入先追加到日志,后台再合并到数据区。这样做的好处是把随机写转为顺序写,充分利用 SSD 的顺序写带宽。

元数据服务(Metadata Service)。 维护卷到分片、分片到存储节点的映射关系,处理卷的创建、删除、快照、扩容等控制面操作。元数据服务本身通常用 Paxos 或 Raft 做高可用。数据面(读写 I/O)不经过元数据服务,只有在分片迁移、故障切换等场景下才需要更新映射。

1.3 三副本写入流程

云块存储的持久性保障通常依赖三副本(3-way Replication)。以一次 4 KB 写入为例:

sequenceDiagram
    participant VM as 虚拟机
    participant FE as 块设备前端
    participant P as 主副本
    participant S1 as 从副本 1
    participant S2 as 从副本 2

    VM->>FE: write(4KB)
    FE->>P: 写请求(分片 ID + 偏移 + 数据)
    P->>P: 写入本地日志
    par 并行复制
        P->>S1: 复制数据
        P->>S2: 复制数据
    end
    S1-->>P: ACK
    S2-->>P: ACK
    P-->>FE: 写入完成
    FE-->>VM: write 返回

关键路径上的延迟组成:

  1. 计算节点到主副本的网络延迟。 在同一可用区(AZ)内,RDMA 网络的单程延迟大约 5-10 微秒,TCP 网络大约 20-50 微秒。
  2. 主副本本地日志写入。 追加写入 NVMe SSD 日志区,延迟大约 10-20 微秒。
  3. 主副本到从副本的网络延迟。 并行复制,取两个从副本中较慢的那个。同 AZ 内 5-50 微秒。
  4. 从副本本地日志写入。 同样追加写入日志。
  5. ACK 返回。 网络传输延迟。

整条链路下来,一次写入的典型延迟在 100-300 微秒,这就解释了为什么云盘的写延迟是本地 NVMe 的 3-10 倍。

1.4 读取路径分析

读取路径比写入路径更复杂,因为数据可能分布在多个位置:

  1. BlockClient 接收读请求。 根据分片映射表,定位到存储该偏移量数据的存储节点。读请求只需要访问一个副本(通常是主副本),不需要多数派读。
  2. 存储节点查找数据。 存储节点内部需要确定数据在本地 SSD 的哪个位置。如果使用日志结构存储引擎,数据可能分布在内存中的 MemTable、磁盘上的多层 SSTable 中,需要逐层查找。
  3. 读取 SSD 数据。 找到数据位置后,从本地 NVMe SSD 读取。如果数据在 SSD 的缓存中(控制器 DRAM 缓存或 Host Memory Buffer),延迟约 10-30 微秒;如果需要读取 NAND 闪存,延迟约 70-120 微秒。
  4. 通过网络返回数据。 数据通过 RDMA 或 TCP 返回给计算节点。

读取的一个关键问题是缓存分层

对于读密集型工作负载(如 OLTP 数据库的点查询),存储节点的缓存命中率直接决定了读延迟。缓存未命中率每上升 1%,平均延迟就可能增加几十微秒。这也解释了为什么云盘在冷启动后(例如刚从快照恢复)的读延迟远高于稳态——缓存还没有被预热。

1.5 日志结构写入与后台合并

存储节点内部通常采用日志结构合并树(LSM-Tree,Log-Structured Merge Tree)或类似的日志结构存储引擎。写入流程:

  1. 前台写入(Foreground Write)。 数据先写入内存中的 MemTable,同时追加到磁盘上的 WAL(Write-Ahead Log,预写日志)。MemTable 满后冻结,变成不可变的 Immutable MemTable。
  2. 后台 Flush。 后台线程把 Immutable MemTable 刷到磁盘,生成 SSTable 文件。
  3. 后台 Compaction。 多个 SSTable 文件积累后,后台线程做合并排序(Compaction),减少文件数量和空间放大。

这个设计对延迟的影响:

为什么选择日志结构而不是原地更新(In-place Update)?原因有三:第一,追加写对 SSD 友好——SSD 的随机写性能远低于顺序写性能,而且随机写加速 SSD 磨损和触发 GC。第二,追加写天然支持快照——保留历史版本只需要不删除旧数据。第三,追加写的并发控制更简单——多个写入之间不需要加锁保护同一个数据块。代价是读放大(Read Amplification)和空间放大(Space Amplification),需要靠 Compaction 来控制。

1.6 数据分片与负载均衡

一个云盘卷的数据并不存在单个存储节点上——它被切分成固定大小的分片(Chunk),典型大小在 64 MB 到 256 MB 之间,分散到多个存储节点上。分片的好处:

但分片也引入了新的问题:

1.7 云盘延迟比本地盘高的完整原因

把上面的分析汇总,云盘相比本地盘多出的延迟包括:

延迟来源 典型增量 说明
虚拟化层(virtio / vhost) 5-20 微秒 虚拟机到宿主机的 I/O 转换
计算节点到存储节点网络 10-100 微秒 取决于 RDMA/TCP、网络拥塞
三副本复制 20-100 微秒 并行复制取最慢副本
存储引擎日志写入 10-30 微秒 WAL 追加写
存储引擎读取放大 0-50 微秒 LSM 多层查找
后台任务干扰 0-数毫秒 Compaction、GC、副本修复

总延迟大约是本地 NVMe SSD 的 2-5 倍。使用 RDMA 网络和 NVMe-oF 协议的新一代云盘(如 AWS io2 Block Express、阿里云 ESSD PL3)能把延迟控制在 100-200 微秒,接近但仍高于本地 NVMe 的 70-120 微秒。

1.8 故障处理与数据修复

分布式块存储的一个核心设计目标是容忍硬件故障。故障处理流程直接影响性能:

存储节点故障。 当一个存储节点宕机或其上的 SSD 损坏时,该节点上的分片副本变得不可用。对于三副本系统,剩余两个副本仍然可以正常服务读写。系统在检测到故障后(通常通过心跳超时,几秒到几十秒),开始从存活的副本复制数据到新的存储节点,重建第三个副本。

数据修复期间的性能影响。 副本重建是带宽密集型操作——需要从存活副本读取全部数据并写入新节点。这个过程会消耗存储节点的 SSD 带宽和网络带宽,和前台 I/O 竞争资源。云厂商通常会对修复流量做限速,控制对前台 I/O 的影响,但延迟抖动仍然不可避免。

修复速度与风险窗口。 副本修复完成前,系统处于降级状态(两副本或一副本)。如果在修复完成前又有另一个副本故障,就可能导致数据丢失。修复速度取决于分片大小和可用带宽——一个 64 MB 的分片在 1 Gbps 的修复带宽下需要约 0.5 秒,但一个存储节点上可能有数万个分片,全部修复可能需要几分钟到几小时。

脑裂与一致性。 网络分区可能导致主副本和从副本之间失去联系。系统需要通过 epoch(纪元号)、lease(租约)等机制防止脑裂——确保在任意时刻只有一个主副本接受写入。分区恢复后,需要进行日志回放和数据对账,确保各副本一致。这些机制在正常运行时不影响性能,但在网络抖动或分区边缘场景下可能导致短暂的写入暂停(几百毫秒到几秒)。

这里有一个容易被忽略的问题:云盘的持久性数字(如 99.999%)是年化统计——它不保证任何单次故障中数据不丢失,只保证在一年的时间窗口内丢失数据的概率极低。对于真正不能丢失的数据,仍然需要应用层的跨 AZ 或跨 Region 复制。


二、AWS EBS 架构分析

2.1 EBS 的演进历史

AWS EBS 经历了多次架构重构,每次重构都显著改变了性能特征:

Nitro 架构对 EBS 性能的改善主要体现在两方面:一是把 EBS I/O 从宿主机 CPU 卸载到 Nitro Card 上处理,消除了 hypervisor 的 CPU 开销;二是用 Nitro Card 上的硬件加速器处理 NVMe 协议、加密、校验和,降低了每次 I/O 的固定开销。

2.2 EBS 数据面架构

根据 AWS 在 re:Invent 2021(“Deep dive on Amazon EBS”, STG302)和 2023(“Understanding Amazon EBS architecture”, STG331)中公开的信息,EBS 的数据面架构可以概括为:

计算节点侧: - 每个 EC2 实例通过 Nitro Card 访问 EBS 卷。Nitro Card 对虚拟机暴露 NVMe 设备接口,虚拟机内的操作系统使用标准 NVMe 驱动。 - Nitro Card 负责 NVMe 命令解析、数据加密(AES-256)、请求路由。I/O 请求通过 AWS 自研的网络协议(基于 SRD——Scalable Reliable Datagram)发往存储节点。

存储节点侧: - 每个 EBS 卷的数据被切分成固定大小的分片(Chunk),分散存储在多个存储节点上。 - 每个分片有两个副本(注意:EBS 是两副本,不是三副本),分布在同一可用区的不同故障域中。 - 存储节点使用本地 NVMe SSD 存储数据,内部采用日志结构写入。

写入路径: 写请求到达主副本后,主副本同时写入本地日志并将数据复制到从副本。两个副本都确认写入后,返回完成。这个两副本写入的设计是 EBS 延迟相对较低的原因之一——少一次副本复制意味着少一次网络往返。

读取路径: 读请求只从一个副本读取,不需要多副本一致性协议。读延迟主要取决于网络延迟加上存储节点的 SSD 读取延迟。

2.3 SRD 网络协议

SRD(Scalable Reliable Datagram)是 AWS 自研的网络传输协议,运行在 Nitro Card 的硬件上。与 TCP 的关键区别:

SRD 对 EBS 性能的影响是显著的——通过多路径传输减少了网络延迟的方差,使得 P99 延迟更加稳定。AWS 公布的数据显示,io2 Block Express 的 P99 读延迟可以做到亚毫秒级。

这里有一个工程上的启示:传统的存储网络方案(iSCSI over TCP、FC over Ethernet)都面临 TCP 队头阻塞和单路径传输的问题。SRD 和 RDMA 的普及意味着,分布式存储系统的网络层不再是”把两端连起来就行”,而是和存储引擎一样需要精心设计。

2.4 EBS 限速机制

EBS 对每个卷实施令牌桶(Token Bucket)限速。IOPS 和吞吐分别有独立的令牌桶——IOPS 令牌桶以配置的 IOPS 速率补充令牌,吞吐令牌桶以配置的吞吐速率补充令牌。一次 I/O 需要同时消耗两个桶的令牌。

当令牌耗尽时,EBS 会对 I/O 进行节流(Throttling)——排队等待令牌补充。在 CloudWatch 中,VolumeQueueLength(队列长度)指标上升是节流的直接信号。当 VolumeQueueLength 持续大于 1 时,说明 I/O 请求在排队等待,延迟会随之上升。

一个容易被忽略的细节:EBS 的限速是按卷计算的,但实例级的 EBS 带宽限制是按实例计算的。如果一个实例挂载了多个卷,所有卷共享实例级的 EBS 带宽。三个 gp3 卷各配置 3,000 IOPS(共 9,000 IOPS),但实例的 EBS IOPS 上限只有 6,000——这时会在实例级触发限流,而不是在单个卷上。排查性能问题时,需要同时检查卷级和实例级的限流指标。

2.5 gp3、io2、io2 Block Express 对比

维度 gp3 io2 io2 Block Express
最大 IOPS 16,000 64,000 256,000
最大吞吐 1,000 MB/s 1,000 MB/s 4,000 MB/s
最大容量 16 TiB 16 TiB 64 TiB
基线 IOPS 3,000(免费) 按容量(500 IOPS/GiB) 按容量(500 IOPS/GiB)
延迟(官方标称) 单位数毫秒 单位数毫秒 亚毫秒(sub-millisecond)
持久性 99.8%-99.9% 99.999% 99.999%
多挂载(Multi-Attach) 不支持 支持 支持
Nitro 要求 推荐 推荐 必须(R5b/R6i 等)

几个关键区别需要解释:

gp3 的 IOPS 和吞吐独立配置。 gp3 允许独立设置 IOPS(最高 16,000)和吞吐(最高 1,000 MB/s),互不绑定。基线 3,000 IOPS 和 125 MB/s 吞吐免费包含在存储费用中。这个设计让用户可以按需购买性能,避免为了 IOPS 购买不需要的容量。

io2 Block Express 的架构差异。 io2 Block Express 不是 io2 的简单升级——它使用了完全不同的数据通路。普通 io2 的 I/O 通过 Nitro Card 的 EBS 控制器处理,io2 Block Express 使用 NVMe over Fabrics 协议直接和存储集群通信,跳过了中间的协议转换层。这是它能实现 256,000 IOPS 和亚毫秒延迟的关键原因。

持久性差异。 gp3 的年化持久性为 99.8%-99.9%(AFR 约 0.1%-0.2%),io2 的持久性为 99.999%(AFR 约 0.001%)。io2 通过更多的冗余和更积极的后台数据校验实现更高持久性。

2.6 EBS 突发性能机制

gp3 的 3,000 基线 IOPS 不消耗突发额度——这是 gp3 和 gp2 的关键区别。gp2 使用 I/O 信用(I/O Credits)机制:卷按容量积攒信用(每 GiB 每秒 3 IOPS 的速率),突发时消耗信用,信用耗尽后回落到基线。小容量 gp2 卷(如 100 GiB,基线仅 300 IOPS)在持续负载下很快耗尽信用,性能骤降。

gp3 取消了信用机制,基线 3,000 IOPS 始终可用。如果配置了更高的 IOPS(如 10,000),这个性能也是持续可用的,不依赖信用。这个改变让 gp3 的性能更可预测。


三、阿里云 ESSD 架构分析

3.1 盘古存储系统

阿里云的块存储服务(ESSD)底层基于盘古(Pangu)分布式存储系统。盘古是阿里云的统一存储底座,同时服务块存储、对象存储(OSS)和文件存储(NAS)。盘古的架构在 USENIX ATC 2023 论文 “More Than Capacity: Performance-oriented Evolution of Pangu in Alibaba” 和 FAST 2023 论文 “What’s the Story in EBS Glory: Evolutions and Lessons in Building Cloud Block Store” 中有详细描述。

盘古的核心组件:

3.2 ESSD 的 I/O 路径

根据 FAST 2023 论文,ESSD 的 I/O 路径如下:

  1. 虚拟机发起 I/O。 通过 virtio-blk 或 NVMe 前端设备发送到宿主机。
  2. 神龙 MOC 卡处理。 阿里云的神龙(X-Dragon)架构使用 MOC(Multi-function On-chip)卡——类似 AWS Nitro Card 的硬件卸载卡——处理虚拟化和存储 I/O 转发。MOC 卡负责 NVMe 命令解析和网络传输。
  3. BlockClient 路由。 根据卷的分片映射表,将 I/O 路由到对应的 ChunkServer。
  4. ChunkServer 处理。 ChunkServer 接收写请求后,写入本地 Append-Only 日志(称为 SealedSegment 和 AppendPoint),同时将数据复制到两个从副本(ESSD 也是三副本)。
  5. 三副本确认。 三个副本都写入本地日志后,主副本返回完成。

3.3 盘古 2.0 的性能优化

FAST 2023 论文描述了盘古 2.0 相对于 1.0 的几个关键性能优化:

用户态存储引擎(UESSD,User-space ESSD)。 早期的 ChunkServer 使用内核态文件系统(ext4)管理本地 SSD 上的数据。盘古 2.0 将存储引擎移到用户态,直接通过 SPDK(Storage Performance Development Kit)和用户态 NVMe 驱动访问 SSD,跳过了内核的 VFS、Page Cache 和块设备层。这一个改变就能减少 30-50 微秒的延迟(内核态 I/O 栈的开销)。

RDMA 网络。 PL2 和 PL3 使用 RDMA(Remote Direct Memory Access,远程直接内存访问)替代 TCP 网络。RDMA 绕过内核网络栈,CPU 不参与数据传输,单程网络延迟从 TCP 的 20-50 微秒降到 3-10 微秒。

Append-Only 写入优化。 盘古 2.0 的 ChunkServer 对每个 Chunk 维护一个 AppendPoint(追加点),所有写入都追加到 AppendPoint 后面。读取时,ChunkServer 维护一个索引(BlockMap),记录每个逻辑偏移对应的物理位置。这种设计把随机写变成顺序追加,充分利用 SSD 的顺序写带宽,同时避免了 SSD 内部的 GC 开销——因为数据总是追加的,覆盖写的空间回收由盘古自己的 GC 控制,而不是依赖 SSD 控制器的 GC。

Fusion Engine。 论文提到的 Fusion Engine 是盘古存储引擎的核心组件,负责将多个小写入合并成大的顺序写。例如,多个 4 KB 写入请求可以被合并成一个 64 KB 的顺序追加。这种合并减少了 SSD 的写放大,也提高了 SSD 的有效 IOPS——因为 SSD 的内部写放大(WAF)随着写入块大小的增加而降低。

3.4 ESSD 性能等级

ESSD 按性能等级分为四个规格:

维度 ESSD PL0 ESSD PL1 ESSD PL2 ESSD PL3
单盘最大 IOPS 10,000 50,000 100,000 1,000,000
单盘最大吞吐 180 MB/s 350 MB/s 750 MB/s 4,000 MB/s
单路延迟 0.2-0.5 ms 0.2-0.5 ms 0.1-0.2 ms 0.1 ms
最小容量 40 GiB 20 GiB 461 GiB 1,261 GiB
IOPS 计算公式 min(10000, 1800 + 50 * 容量) min(50000, 1800 + 50 * 容量) min(100000, 1800 + 50 * 容量) min(1000000, 1800 + 50 * 容量)
适用场景 开发测试、小型数据库 中大型数据库、中间件 大型 OLTP、高性能应用 超大规模数据库、极致性能

几个要点:

IOPS 和容量绑定。 不同于 AWS gp3 的 IOPS 独立配置,ESSD 的 IOPS 和容量线性相关——每 GiB 提供 50 IOPS,基线 1,800 IOPS,上限取决于 PL 等级。想要更高 IOPS 必须购买更大容量,即使业务数据量用不了那么大。

PL3 依赖高端实例。 百万级 IOPS 需要实例本身有足够的网络带宽和 CPU 能力。只有 ecs.g7se、ecs.r7se 等增强型实例才能发挥 PL3 的全部性能。

延迟差异来自网络。 PL2/PL3 使用 25GE/100GE RDMA 网络,PL0/PL1 使用普通 TCP 网络。网络传输协议的差异是延迟差异的主要原因。

3.5 ESSD AutoPL

2023 年阿里云推出 ESSD AutoPL,支持按需突发——基线性能由容量决定,突发 IOPS 最高可达 100,000,突发吞吐最高可达 800 MB/s。突发性能按使用量计费。这个模式适合负载波动大但峰值持续时间短的场景(如电商大促、定时批处理),避免为峰值性能常年付费。

3.6 ESSD 与 EBS 的架构差异

维度 AWS EBS 阿里云 ESSD
副本数 2 3
网络传输 SRD(自研) RDMA(PL2/PL3)/ TCP(PL0/PL1)
硬件卸载 Nitro Card 神龙 MOC 卡
IOPS 定价 gp3 独立配置 与容量绑定
最高单盘 IOPS 256,000(io2 BE) 1,000,000(PL3)
最大单盘容量 64 TiB(io2 BE) 64 TiB
持久性(最高) 99.999%(io2) 99.9999999%(9 个 9,官方标称)

两副本和三副本的取舍:AWS 选择两副本,写延迟更低(少一次网络往返和本地写入),但需要更复杂的后台修复机制来保证持久性。阿里云选择三副本,写延迟稍高,但在单节点故障时仍有两个完整副本可用,数据修复的紧迫性更低。两种设计各有道理——AWS 更激进地优化延迟,阿里云更保守地保证可靠性。


四、云盘性能规格解读

4.1 IOPS 的真实含义

IOPS(Input/Output Operations Per Second,每秒输入输出操作数)看起来简单,但隐藏了很多细节:

I/O 大小的影响。 云厂商标称的 IOPS 通常是 4 KB 或 16 KB 块大小下的数字。增大 I/O 大小后,IOPS 通常会下降——因为实际瓶颈从 IOPS 变成了吞吐。一个 16,000 IOPS、1,000 MB/s 吞吐的 gp3 卷,在 4 KB 块大小下可以跑满 16,000 IOPS(总吞吐 62.5 MB/s),但在 256 KB 块大小下只能跑 4,000 IOPS(总吞吐 1,000 MB/s,受吞吐上限限制)。

随机 vs. 顺序。 标称 IOPS 通常是随机 I/O 的数字。顺序 I/O 因为可以被合并,实际的操作次数可能远少于应用发出的 I/O 次数,所以顺序场景下用吞吐而不是 IOPS 来衡量更有意义。

读写比例。 有些云盘规格对读写 IOPS 有不同的上限。例如 AWS io2 Block Express 的读写 IOPS 共享同一个上限,但读延迟和写延迟不同(读通常比写快,因为读只需访问一个副本)。

4.2 吞吐的约束

吞吐(Throughput)是另一个独立的性能维度。IOPS 和吞吐同时受限——取先触达上限的那个。

计算实际可达吞吐的公式:

实际吞吐 = min(最大吞吐, IOPS * I/O 大小)

例如 gp3 默认配置(3,000 IOPS、125 MB/s 吞吐): - 4 KB 块大小:3,000 * 4 KB = 12 MB/s(受 IOPS 限制,远未达到吞吐上限) - 256 KB 块大小:125 MB/s / 256 KB = 500 IOPS(受吞吐限制)

这说明:对于小 I/O 密集型负载(如数据库事务),IOPS 是瓶颈;对于大 I/O 顺序型负载(如日志写入、数据备份),吞吐是瓶颈。

4.3 延迟基线与抖动

云厂商标称的延迟通常是”单位数毫秒”或”亚毫秒”这样的模糊表述。实际延迟取决于多个因素:

空闲延迟(Idle Latency)。 卷没有负载时发送单个 I/O 的延迟,反映了网络传输和存储引擎的固有开销。EBS gp3 的空闲读延迟大约在 0.2-0.5 毫秒,io2 Block Express 大约在 0.1-0.2 毫秒。

负载延迟(Loaded Latency)。 随着并发 I/O 增加,排队延迟上升。当 IOPS 接近上限时,排队延迟可能占总延迟的 50% 以上。

延迟抖动。 云盘延迟不是恒定的,而是有波动。波动来源包括: - 存储节点后台 Compaction 和 GC - 网络拥塞(共享网络带宽的其他租户的干扰) - 副本修复(某个副本故障后的数据重建) - 热点分片(大量 I/O 集中在少数分片上)

P99 延迟通常是 P50 延迟的 3-10 倍。在做容量规划时,应该用 P99 而不是平均延迟来估算。

4.4 实例级限制

云盘的性能还受实例类型的限制。每种实例类型都有自己的 EBS 带宽和 IOPS 上限:

EC2 实例 EBS 性能上限示例(AWS):
┌──────────────────┬────────────┬──────────────┬──────────┐
│ 实例类型         │ EBS 带宽   │ EBS IOPS     │ NVMe 队列│
├──────────────────┼────────────┼──────────────┼──────────┤
│ m6i.large        │ 650 MB/s   │ 3,600        │ 共享     │
│ m6i.xlarge       │ 1,250 MB/s │ 6,000        │ 共享     │
│ m6i.4xlarge      │ 2,500 MB/s │ 15,000       │ 专用     │
│ m6i.16xlarge     │ 5,000 MB/s │ 40,000       │ 专用     │
│ r5b.24xlarge     │ 10,000 MB/s│ 60,000       │ 专用     │
│ r6i.metal        │ 5,000 MB/s │ 40,000       │ 专用     │
└──────────────────┴────────────┴──────────────┴──────────┘
注:以上数据引用自 AWS 官方文档(2024 年),实际可能随实例代次更新。

关键点:即使云盘配置了 16,000 IOPS,如果实例的 EBS IOPS 上限只有 3,600(如 m6i.large),实际只能跑到 3,600。这是新手最常见的困惑之一——买了高性能云盘却跑不出预期性能,原因是实例规格不够。

4.5 I/O 大小与性能的关系

云盘的 IOPS 和吞吐在不同 I/O 大小下的表现差异很大。以一个配置了 16,000 IOPS、1,000 MB/s 吞吐的 gp3 卷为例:

I/O 大小与性能约束关系(gp3: 16K IOPS / 1000 MB/s):
┌──────────┬────────────────┬────────────────┬──────────────┐
│ I/O 大小 │ IOPS 约束吞吐  │ 吞吐约束 IOPS  │ 实际瓶颈     │
├──────────┼────────────────┼────────────────┼──────────────┤
│ 4 KB     │ 62.5 MB/s      │ 256,000        │ IOPS         │
│ 8 KB     │ 125 MB/s       │ 128,000        │ IOPS         │
│ 16 KB    │ 250 MB/s       │ 64,000         │ IOPS         │
│ 64 KB    │ 1,000 MB/s     │ 16,000         │ 两者同时触顶 │
│ 128 KB   │ 2,000 MB/s     │ 8,000          │ 吞吐         │
│ 256 KB   │ 4,000 MB/s     │ 4,000          │ 吞吐         │
│ 1 MB     │ 16,000 MB/s    │ 1,000          │ 吞吐         │
└──────────┴────────────────┴────────────────┴──────────────┘

可以看到,64 KB 是这个配置下的平衡点——IOPS 和吞吐同时达到上限。I/O 大小小于 64 KB 时是 IOPS 受限,大于 64 KB 时是吞吐受限。

这对数据库设计有直接影响。MySQL InnoDB 的页大小默认是 16 KB,PostgreSQL 的页大小默认是 8 KB——这些都在 IOPS 受限区间。如果数据库的瓶颈是随机读写 IOPS,增加云盘的 IOPS 配置比增加吞吐配置更有效。反过来,Kafka 的日志写入使用大块顺序写,通常在吞吐受限区间,应该优先配置更高的吞吐。

4.6 性能监控指标

在实际运行中,需要持续监控以下指标来判断云盘是否成为瓶颈:

AWS CloudWatch 关键指标:

指标名 含义 告警阈值建议
VolumeReadOps / VolumeWriteOps 读写操作次数 接近配置 IOPS 的 80%
VolumeReadBytes / VolumeWriteBytes 读写字节数 接近配置吞吐的 80%
VolumeQueueLength I/O 队列长度 持续大于 1 表示排队
VolumeTotalReadTime / VolumeTotalWriteTime 读写总耗时 用于计算平均延迟
BurstBalance(gp2) 突发余额百分比 低于 20% 预警

平均延迟的计算方式:

平均读延迟 = VolumeTotalReadTime / VolumeReadOps
平均写延迟 = VolumeTotalWriteTime / VolumeWriteOps

注意:CloudWatch 提供的是平均延迟,不提供百分位延迟。要获取 P99 延迟,需要在操作系统内部用 biolatency 或 fio 的延迟直方图来采集。


五、云盘性能测试方法

5.1 为什么直接跑 fio 经常得到错误结果

常见错误:

  1. 没有预热(Pre-conditioning)。 新创建的 EBS 卷或从快照恢复的卷,首次读取每个块时需要从 S3 或快照存储中拉取数据,延迟远高于正常值。必须先对全卷做一次顺序写或读来完成预热。
  2. I/O 深度不够。 云盘的 IOPS 上限需要足够的并发 I/O 才能达到。单线程同步 I/O(iodepth=1)只能在延迟的倒数处运转——如果延迟是 0.2 毫秒,单线程最多 5,000 IOPS。要跑满 16,000 IOPS,至少需要 iodepth=4(16000 * 0.00025 = 4)。
  3. 用了文件系统而不是裸设备。 文件系统引入额外的延迟和 IOPS 开销(元数据操作、日志提交)。性能测试应该直接测裸设备(/dev/nvme1n1),除非目的就是测试文件系统上的性能。
  4. 测试时间太短。 短时间测试可能测到突发性能而不是持续性能。至少跑 5 分钟以上。
  5. 没有等待稳态(Steady State)。 开始测试后前几分钟的性能可能不稳定(缓存效应、存储引擎预热)。应该丢弃前几分钟的数据,只统计稳态数据。

5.2 I/O 深度的计算

队列深度(I/O Depth / Queue Depth)是性能测试中最关键的参数。计算所需队列深度的公式:

所需队列深度 = 目标 IOPS * 平均延迟(秒)

举几个例子:

目标 IOPS 预估延迟 所需队列深度 fio 配置建议
3,000(gp3 基线) 0.3 ms 0.9 ≈ 1 iodepth=1, numjobs=1
16,000(gp3 最大) 0.3 ms 4.8 ≈ 8 iodepth=8, numjobs=1
64,000(io2) 0.2 ms 12.8 ≈ 16 iodepth=16, numjobs=2
256,000(io2 BE) 0.15 ms 38.4 ≈ 64 iodepth=32, numjobs=4

实际测试中通常设置比计算值更高的队列深度(2-4 倍),确保不是队列深度不够导致跑不满。但队列深度也不能过高——过高的队列深度会人为增加排队延迟,使延迟测试结果失真。如果目的是测最低延迟而不是最大 IOPS,应该用 iodepth=1

5.3 fio 测试命令

以下是测试 EBS gp3 卷的 fio 命令示例。假设测试设备为 /dev/nvme1n1(一个挂载到 EC2 实例上的 EBS 卷)。

第一步:预热——对全卷做顺序写

# 预热:顺序写满全卷,确保所有块都已初始化
# 注意:这会覆盖卷上的所有数据
fio --name=precondition \
    --filename=/dev/nvme1n1 \
    --ioengine=libaio \
    --direct=1 \
    --bs=1m \
    --iodepth=64 \
    --rw=write \
    --numjobs=1 \
    --size=100% \
    --group_reporting

第二步:4K 随机读 IOPS 测试

fio --name=randread-iops \
    --filename=/dev/nvme1n1 \
    --ioengine=libaio \
    --direct=1 \
    --bs=4k \
    --iodepth=32 \
    --rw=randread \
    --numjobs=4 \
    --runtime=300 \
    --time_based \
    --group_reporting \
    --lat_percentiles=1 \
    --percentile_list=50:90:95:99:99.9:99.99

第三步:4K 随机写 IOPS 测试

fio --name=randwrite-iops \
    --filename=/dev/nvme1n1 \
    --ioengine=libaio \
    --direct=1 \
    --bs=4k \
    --iodepth=32 \
    --rw=randwrite \
    --numjobs=4 \
    --runtime=300 \
    --time_based \
    --group_reporting \
    --lat_percentiles=1 \
    --percentile_list=50:90:95:99:99.9:99.99

第四步:顺序读吞吐测试

fio --name=seqread-throughput \
    --filename=/dev/nvme1n1 \
    --ioengine=libaio \
    --direct=1 \
    --bs=256k \
    --iodepth=64 \
    --rw=read \
    --numjobs=4 \
    --runtime=300 \
    --time_based \
    --group_reporting

第五步:混合读写测试(70% 读 / 30% 写)

fio --name=mixed-rw \
    --filename=/dev/nvme1n1 \
    --ioengine=libaio \
    --direct=1 \
    --bs=4k \
    --iodepth=32 \
    --rw=randrw \
    --rwmixread=70 \
    --numjobs=4 \
    --runtime=300 \
    --time_based \
    --group_reporting \
    --lat_percentiles=1

5.4 fio 参数说明

参数 含义 为什么这样设
--ioengine=libaio 使用 Linux 原生异步 I/O 直接向内核提交异步请求,绕过 glibc 缓冲
--direct=1 绕过 Page Cache 测试真实的块设备性能,不被缓存干扰
--bs=4k I/O 块大小 4 KB 云厂商标称 IOPS 的基准块大小
--iodepth=32 队列深度 32 维持足够的并发 I/O 来饱和云盘性能
--numjobs=4 4 个并行任务 模拟多线程访问,总并发 = iodepth * numjobs = 128
--runtime=300 运行 300 秒 确保测到稳态性能而非突发
--time_based 固定运行时间 即使文件读完也继续测试
--group_reporting 合并报告 所有 job 的结果合并输出
--lat_percentiles=1 输出延迟百分位 查看 P50/P99/P99.9 延迟

5.5 fio 输出解读

以一个 gp3 卷(配置 3,000 IOPS、125 MB/s)的典型 4K 随机读输出为例(以下为典型输出格式,实际数值取决于具体环境):

randread-iops: (groupid=0, jobs=4): err= 0: pid=12345
  read: IOPS=2998, BW=11.7MiB/s (12.3MB/s)(3517MiB/300001msec)
    slat (usec): min=1, max=85, avg= 3.21, stdev= 1.52
    clat (usec): min=62, max=15234, avg=378.52, stdev=125.67
     lat (usec): min=65, max=15237, avg=381.73, stdev=125.89
    clat percentiles (usec):
     |  1.00th=[  143],  5.00th=[  192], 10.00th=[  225],
     | 20.00th=[  269], 30.00th=[  302], 40.00th=[  334],
     | 50.00th=[  363], 60.00th=[  392], 70.00th=[  424],
     | 80.00th=[  465], 90.00th=[  529], 95.00th=[  594],
     | 99.00th=[  783], 99.50th=[  898], 99.90th=[ 1434],
     | 99.95th=[ 2024], 99.99th=[ 5800]

关键数字解读:

5.6 稳态验证

怎么判断测试是否达到了稳态?用 fio 的 --write_bw_log--write_iops_log 参数输出时间序列数据:

fio --name=steady-state-check \
    --filename=/dev/nvme1n1 \
    --ioengine=libaio \
    --direct=1 \
    --bs=4k \
    --iodepth=32 \
    --rw=randread \
    --numjobs=4 \
    --runtime=600 \
    --time_based \
    --group_reporting \
    --write_iops_log=gp3-iops \
    --write_lat_log=gp3-lat \
    --log_avg_msec=1000

这会生成 gp3-iops_iops.1.loggp3-lat_lat.1.log 文件,每秒一个数据点。用简单的脚本或者 gnuplot 画出时间序列图,观察 IOPS 和延迟是否在前几分钟后趋于平稳。如果 IOPS 持续下降或延迟持续上升,说明测试条件有问题(可能是存储节点在做后台任务,或者触发了性能限流)。


六、云盘选型与成本优化

6.1 选型决策树

云盘选型不应该只看性能参数——成本、持久性、弹性需求都要纳入考量。下面是一个简化的决策流程:

flowchart TD
    A[确定工作负载特征] --> B{需要持久化?}
    B -->|否| C[本地实例存储<br/>Instance Store]
    B -->|是| D{延迟要求?}
    D -->|亚毫秒| E{IOPS 需求?}
    D -->|单位数毫秒可接受| F[gp3 / ESSD PL1]
    E -->|大于 64K| G[io2 Block Express<br/>ESSD PL3]
    E -->|小于 64K| H[io2 / ESSD PL2]
    F --> I{容量需求?}
    I -->|小于 1 TiB| J[gp3 基线 3000 IOPS<br/>性价比最高]
    I -->|大于 1 TiB| K[gp3 按需加 IOPS<br/>或 st1 大容量]
    G --> L[确认实例规格<br/>能支撑目标 IOPS]
    H --> L

6.2 成本对比

以 AWS us-east-1 区域为例,不同 EBS 类型存储 1 TiB 数据、配置 10,000 IOPS 的月度成本估算(截至 2024 年,价格可能变化):

卷类型 存储费用 IOPS 费用 吞吐费用 月度总计(估算)
gp3(1 TiB, 10K IOPS, 250 MB/s) $81.92 $45.50((10000-3000) * $0.0065) $5.00((250-125) * $0.04) 约 $132
io2(1 TiB, 10K IOPS) $125.00 $650.00(10000 * $0.065) 无单独费用 约 $775
io2 Block Express(1 TiB, 10K IOPS) $125.00 $650.00 无单独费用 约 $775
gp2(1 TiB,基线 3000 IOPS) $102.40 无单独配置 无单独配置 约 $102

几个关键发现:

gp3 在大多数场景下性价比最高。 同样 10,000 IOPS,gp3 的成本约为 io2 的 1/6。除非业务对持久性有极高要求(99.999%)或需要 Multi-Attach,否则 gp3 通常是更好的选择。

io2 的 IOPS 单价远高于 gp3。 io2 每 IOPS 每月 $0.065,gp3 每 IOPS 每月 $0.0065(超过基线部分)。io2 的溢价主要买的是更高的持久性(99.999% vs. 99.8%-99.9%)和更低的延迟。

gp2 到 gp3 的迁移几乎总是值得的。 gp3 基线 3,000 IOPS + 125 MB/s 免费包含,而 gp2 需要 600 GiB 以上才能达到 3,000 IOPS 基线(1 GiB = 3 IOPS)。小容量卷从 gp2 迁移到 gp3 可以获得性能提升且成本不变或更低。

6.3 常见的成本浪费

为了 IOPS 购买不需要的容量(ESSD 场景)。 ESSD 的 IOPS 和容量绑定,想要 50,000 IOPS 至少需要 (50000-1800)/50 = 964 GiB 的 PL1 云盘。如果业务数据只有 100 GiB,剩余 864 GiB 是纯粹的成本浪费。这种情况下可以考虑使用 ESSD AutoPL,或者把数据分散到多块小容量 ESSD 上并行访问。

实例规格不匹配。 用 m6i.large(EBS 上限 3,600 IOPS)挂一块配置了 16,000 IOPS 的 gp3——多出来的 12,400 IOPS 完全浪费。先确认实例的 EBS 性能上限,再配置云盘 IOPS。

没有使用 gp3 的独立 IOPS/吞吐配置。 很多用户从 gp2 迁移到 gp3 后,没有额外配置 IOPS 和吞吐,停留在基线 3,000 IOPS / 125 MB/s。如果负载需要更高性能,增加 IOPS 和吞吐的费用远低于升级到 io2。

快照费用忽视。 EBS 快照按增量存储计费($0.05/GiB/月),但长期积累的快照总量可能远超卷本身的大小。定期清理不需要的快照是控制存储成本的基本操作。

6.4 成本优化清单

  1. 审计现有卷的使用率。 用 CloudWatch 的 VolumeReadOpsVolumeWriteOps 指标检查每个卷的实际 IOPS 使用率。如果实际 IOPS 长期低于基线 3,000,说明不需要额外购买 IOPS。
  2. gp2 全面迁移 gp3。 AWS 支持在线变更卷类型(Elastic Volumes),无需停机。迁移后根据实际负载调整 IOPS 和吞吐配置。
  3. 实例和云盘性能对齐。 实例的 EBS 带宽/IOPS 上限应该大于等于所有挂载云盘的性能总和。反过来也成立——不要用过大的实例挂小规格云盘。
  4. 冷数据下沉。 访问频率低的数据(日志归档、历史备份)迁移到 st1(吞吐优化 HDD,$0.045/GiB/月)或 sc1(冷 HDD,$0.015/GiB/月)。
  5. 快照生命周期管理。 使用 AWS Data Lifecycle Manager(DLM)或阿里云快照策略自动管理快照保留周期,避免快照无限增长。
  6. 考虑 ESSD AutoPL 替代固定高规格。 如果负载的峰值持续时间短(每天不超过几小时),按需突发模式的费用可能低于常年购买高 PL 等级。

七、进阶话题

7.1 跨可用区复制与 Multi-Attach

跨可用区复制。 默认情况下,EBS 卷的副本在同一个可用区(AZ)内。如果整个 AZ 故障(虽然罕见但有先例——2012 年 US-East-1 AZ 级故障、2020 年 AP-Northeast-1 事件),卷数据不可访问。跨 AZ 的数据保护需要额外方案:EBS 快照(存储在 S3,跨 AZ 持久化)、应用层复制(如数据库主从)、或 AWS Outposts 的本地存储。

Multi-Attach。 io2 和 io2 Block Express 支持将同一个卷同时挂载到最多 16 个实例上(必须在同一 AZ)。Multi-Attach 不提供文件系统级的协调——需要应用自己实现分布式锁或使用集群文件系统(如 GFS2、OCFS2)。典型场景是共享存储集群(如 Oracle RAC)。

7.2 加密对性能的影响

EBS 默认支持透明加密(AES-256),加密/解密由 Nitro Card 硬件执行,不占用实例 CPU。AWS 官方声明加密对性能的影响”极小”(negligible)。实测中,加密卷和未加密卷的 IOPS 和延迟差异通常在 1-3% 以内——这在实际工作负载中基本不可感知。阿里云的 ESSD 同样支持透明加密,由 MOC 卡硬件处理。

我认为在 2024 年的云环境中,没有理由不开启存储加密。性能影响可以忽略,而加密带来的合规和安全收益是明确的。

7.3 快照与克隆的性能影响

从快照恢复的卷需要预热。 EBS 快照存储在 S3 上。从快照创建的卷,首次访问每个块时需要从 S3 拉取数据——这个延迟可能高达数毫秒到数十毫秒,远高于正常的块设备延迟。AWS 提供 Fast Snapshot Restore(FSR)功能,可以预初始化卷的所有块,消除首次访问的延迟惩罚。FSR 按启用的 AZ 和快照计费($0.75/快照/AZ/小时),成本不低,但对于延迟敏感的生产数据库恢复场景很有价值。

阿里云快照的类似问题。 从快照创建的 ESSD 同样存在首次读取延迟的问题。阿里云的解决方案是”快照极速可用”功能,原理类似——提前将数据从快照存储恢复到块存储集群。

7.4 NVMe over Fabrics 与未来趋势

NVMe over Fabrics(NVMe-oF)是云块存储架构演进的方向。NVMe-oF 把 NVMe 协议从 PCIe 总线扩展到网络——虚拟机内的 NVMe 驱动可以直接和远端存储节点通信,不需要中间的协议转换层(如 virtio-blk 到自研协议再到存储引擎)。

AWS io2 Block Express 已经使用了 NVMe-oF 的思路(虽然底层协议是 SRD 而非标准 NVMe-oF)。阿里云的 ESSD PL3 也在向 NVMe-oF 方向演进。

NVMe-oF 对性能的意义在于减少协议转换层数——每减少一层协议转换,就减少一次数据拷贝和延迟。长期来看,云盘的延迟有望进一步接近本地 NVMe SSD 的水平。但网络传输延迟和多副本复制的开销是物理限制,不可能完全消除。我认为云盘延迟的下限大约在 50-100 微秒——在 RDMA 网络 + 两副本 + 硬件卸载的极致优化下。

7.5 常见性能问题排查

在实际运维中,云盘相关的性能问题排查有一套固定的流程。以下是常见问题和对应的排查方法:

问题一:IOPS 跑不满标称值

排查顺序: 1. 检查实例级 EBS 性能上限(CloudWatch EBSIOBalance% 或实例文档)。 2. 检查 fio 的 iodepth * numjobs 是否足够(参见 5.2 节的计算公式)。 3. 检查是否使用了 --direct=1——不用 direct I/O 时,小 I/O 可能被 Page Cache 合并,实际到达块设备的 IOPS 比预期少。 4. 检查卷是否已预热——未预热的卷首次读取块时会触发后端拉取,IOPS 远低于正常值。

问题二:延迟突然飙高

排查顺序: 1. 检查 VolumeQueueLength——如果队列长度突增,说明触发了限流。 2. 检查是否有突发 I/O(如数据库检查点、日志轮转)导致短时间内 IOPS 超过配置值。 3. 检查实例的网络带宽使用——EBS I/O 和网络流量共享实例的网络带宽(部分实例类型),网络拥塞会影响 EBS 延迟。 4. 检查 dmesg 中是否有 NVMe 超时或重试日志——这可能指示存储后端的临时故障。

问题三:性能周期性波动

可能的原因: 1. 存储后端的 Compaction 或 GC 是周期性任务,会占用 SSD 带宽,导致前台 I/O 延迟周期性上升。 2. 数据库的检查点间隔(如 MySQL 的 innodb_log_file_size 写满后触发检查点)导致 I/O 周期性突增。 3. cron 定时任务(备份、日志压缩)在固定时间点产生突发 I/O。

对于第一种情况,用户端无法直接控制存储后端的行为,但可以通过增大 IOPS 配置预留余量、或使用延迟更低的卷类型(如 io2 Block Express)来缓解。


八、结论与工程建议

8.1 核心结论

  1. 云盘延迟高于本地盘是架构决定的。 网络传输、多副本复制、存储引擎的日志结构写入和后台合并——这些是分布式块存储的固有开销,不是”优化不够”。理解这一点才能正确设定性能预期。

  2. IOPS、吞吐、延迟是三个独立的约束维度。 云盘性能受三者中最先触达上限的那个限制。小 I/O 看 IOPS,大 I/O 看吞吐,延迟敏感型负载看 P99 延迟。选型时三个维度都要评估。

  3. 实例规格是隐藏的性能瓶颈。 云盘性能再高,也不能超过实例的 EBS 带宽和 IOPS 上限。性能调优要先确认瓶颈在实例侧还是云盘侧。

  4. gp3 在绝大多数场景下是性价比最优选择。 除非有明确的亚毫秒延迟要求、99.999% 持久性要求、或超过 16,000 IOPS 的需求,否则从 gp3 开始,按需加量。

  5. 性能测试要用正确的方法。 预热、足够的 I/O 深度、裸设备测试、足够长的运行时间、稳态验证——任何一步缺失都会导致测试结果失真。

8.2 工程建议


参考资料

官方文档与演讲

  1. AWS. “Amazon EBS volume types.” AWS 官方文档,包含 gp3、io2、io2 Block Express 的详细性能规格。
  2. AWS re:Invent 2021, STG302. “Deep dive on Amazon EBS.” EBS 架构和 Nitro 集成的详细讲解。
  3. AWS re:Invent 2023, STG331. “Understanding Amazon EBS architecture.” EBS 数据面架构和 SRD 协议介绍。
  4. 阿里云. “ESSD 云盘.” 阿里云官方文档,包含 ESSD PL0-PL3 性能规格。

论文

  1. Li, Jianguo et al. “What’s the Story in EBS Glory: Evolutions and Lessons in Building Cloud Block Store.” FAST 2023. 阿里云 EBS(ESSD)架构演进的详细论文,包含盘古存储系统的设计和性能分析。
  2. Guo, Hao et al. “More Than Capacity: Performance-oriented Evolution of Pangu in Alibaba.” USENIX ATC 2023. 盘古分布式存储系统面向性能的架构演进。
  3. Arpaci-Dusseau, Remzi H. and Arpaci-Dusseau, Andrea C. “Operating Systems: Three Easy Pieces.” 第 39-42 章,SSD 和闪存存储的基础知识。

工具与测试

  1. fio 项目文档(https://fio.readthedocs.io)——fio 的完整参数说明和使用指南。
  2. AWS. “Benchmark EBS Volumes.” AWS 官方文档中的 EBS 性能测试指南,包含 fio 参数推荐。

上一篇:【存储工程】存储全链路延迟分析

下一篇:【存储工程】云对象存储内部架构

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2025-10-12 · storage

【存储工程】存储基准测试方法论

深入剖析存储基准测试的方法论——fio 参数解析、filebench 工作负载定义、YCSB 数据库基准、测试陷阱规避与性能回归测试集成

2025-08-14 · storage

【存储工程】存储性能建模:IOPS、吞吐与延迟

存储性能不是一个数字,而是 IOPS、吞吐量和延迟在特定工作负载下的函数关系。本文从排队论模型出发,用 fio 实测验证,覆盖从 HDD 到 NVMe SSD 的性能画像,最终落到容量规划和监控体系的工程实践。

2025-08-10 · storage

【存储工程】HDD 机械硬盘:旋转时代的工程遗产

HDD 已经被 SSD 抢去了大部分聚光灯,但全球 90% 以上的数据仍然存储在旋转磁盘上。理解 HDD 的物理结构和性能特征,是理解整个存储栈设计决策的基础——从文件系统的块分配策略到数据库的 WAL 设计,几乎每一个存储优化都能追溯到'旋转延迟'和'寻道时间'这两个物理约束。

2026-04-22 · db / storage

数据库内核实验索引

汇总本站数据库内核与存储引擎实验文章,重点覆盖从零实现 LSM-Tree 及其工程权衡。


By .