高速存储路径总览
# 高速存储路径总览:NVMe、Direct I-O、io_uring、SPDK
存储设备越来越快之后,瓶颈往往不再只是“盘慢”,而是“软件路径太长”。这也是为什么后来的讨论越来越多地转向 NVMe、多队列、Direct I/O、io_uring 和 SPDK。
# 1. 为什么会出现这些技术
在传统路径里,一次 I/O 往往要经过:
- 系统调用切换
- VFS / 文件系统
- Page Cache
- 块层
- 调度器
- 驱动
这条路径很通用,但也很重。
当设备速度越来越高,通用路径里的每一层开销都变得更显眼,于是大家开始想办法:
- 减少内核参与
- 减少拷贝
- 减少上下文切换
- 增强并发队列利用率
# 2. NVMe 带来了什么变化
NVMe 的关键不只是“更快”,而是它天然面向高并发和低延迟:
- 队列更多
- 并行度更高
- 更适合多核 CPU
- 更容易把瓶颈暴露到软件栈
所以 NVMe 时代,性能分析的重点会从“磁盘寻道”更多转向:
- 队列深度
- CPU 开销
- 中断和轮询
- 多队列绑定
- 用户态路径优化
# 3. Direct I-O 在解决什么问题
Direct I/O 的核心思路是:
绕过 Page Cache,尽量让数据更直接地在应用和设备之间流动。
它通常适合:
- 应用自己管理缓存
- 不希望双重缓存
- 大块顺序 I/O
- 需要更明确的 I/O 控制语义
但它不是“天然更快”,因为它也失去了缓存命中和写回合并带来的好处。
所以更准确的说法是:
Direct I/O 不是万能加速,而是把控制权交还给应用。
# 4. io_uring 在解决什么问题
io_uring 更像是在保留内核 I/O 能力的前提下,尽量把提交和完成路径做轻量化。
它的价值主要在于:
- 减少系统调用成本
- 改善异步 I/O 编程模型
- 更适合高并发提交/回收
- 为零拷贝、固定缓冲区等优化提供更好接口
可以把它理解成:
“不一定绕过内核,但尽量把内核 I/O 的路径做得更薄。”
# 5. SPDK 在解决什么问题
SPDK 的思路比 io_uring 更激进:
它把很多 I/O 处理放到用户态,尽量绕过传统内核块层和调度路径,直接驱动 NVMe 等高性能设备。
典型收益:
- 更低延迟
- 更少上下文切换
- 更强的 CPU 亲和和轮询控制
- 更适合极致性能场景
代价也很明确:
- 编程和运维复杂度更高
- 通用性变差
- 需要系统设计者自己承担更多资源管理责任
# 6. 这几种技术不是替代关系,而是路径选择
更适合把它们看成不同层次的选择:
Page Cache:默认通用路径,适合大多数文件 I/ODirect I/O:绕过缓存,但仍走内核设备路径io_uring:优化内核 I/O 提交与完成路径SPDK:更激进的用户态设备访问路径
而 NVMe 是促使这些路径优化越来越重要的硬件背景。
# 7. 怎么建立一个实用判断框架
看一个系统时,可以先问这几个问题:
- 设备快到什么程度了?
- 瓶颈在设备、内核路径还是应用逻辑?
- 应用是否愿意自己管理缓存?
- 更看重通用性,还是极致性能?
- 是想优化接口成本,还是直接重构整条 I/O 路径?
这几个问题能帮助你判断应该继续走内核默认路径,还是转向更“贴设备”的方案。
# 8. 和当前笔记的关系
- 基础缓存层:Page Cache总览
- 语义层补充:fsync、写回与刷盘语义
- 恢复语义补充:文件系统日志与崩溃恢复
- 块层视角:块层与I-O调度总览
- 多队列衔接:blk-mq多队列模型
- DAOS 相关依赖:SPDK Blob
- 总入口:技术专题
# 9. 适合继续拆开的专题
61.NVMe队列模型62.Direct I-O适用场景63.io_uring提交与完成路径64.SPDK轮询模型
关联文章
匹配标签:NVMe, Direct I/O, io_uring, SPDK
- blk-mq多队列模型
Edit (opens new window)
Last Updated: 2026/04/28, 15:19:51