news 2026/8/23 14:04:29

fastblock:基于 SPDK 与 Multi-Raft 的全闪存分布式块存储

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
fastblock:基于 SPDK 与 Multi-Raft 的全闪存分布式块存储

fastblock:基于 SPDK 与 Multi-Raft 的全闪存分布式块存储

【免费下载链接】fastblockA distributed block storage system that uses mature Raft protocol and is designed for all-flash scenarios项目地址: https://gitcode.com/openeuler/fastblock

fastblock 是 openEuler 社区开源的分布式块存储系统,使用 SPDK 用户态框架构建,数据复制依赖成熟的 Raft 协议,面向全闪存(NVMe 磁盘 + RDMA 网络)场景设计。本文回答几个实际问题:它的组件如何分工、PG 对应的多 Raft 复制与心跳合并是怎么做的、没有 RDMA 网卡时如何先跑通最小集群,以及不同副本配置下如何解读 IOPS 与延迟指标。

fastblock 要解决什么问题:传统块存储的五个短板

fastblock 的定位来自对 Ceph 等主流分布式块存储在全闪存场景下五类短板的针对性改进(来自项目 README 的归纳):

维度现有体系中的问题
CPU 经济性NVMe SSD 集群中 CPU 成为瓶颈,消耗偏高
可用性主从强同步复制下,集群抖动时 IO 会被挂起
单卷性能对接 QEMU 时进一步下降,需要多个卷才能跑满集群
单卷延迟未能发挥 NVMe 低延迟特性,RBD 块设备常处于毫秒级
并发总量IOPS 与吞吐距硬件可提供的水平差距较大

对应的四条设计选择是:用 SPDK 的用户态 NVMe 驱动与无锁队列缩短 IO 路径;引入 RDMA 网卡做零拷贝、内核旁路、不需要 CPU 干预的网络通信;采用 multi-raft 做数据复制,每个 PG(放置组)对应一个独立 Raft 组;元数据管理保持简单、可靠、可定制。

💡 ## 如何理解 fastblock 的三层分工:从 Compute 到 localstore

整体架构沿用了 Monitor、OSD、PG 这类 Ceph 概念,降低已有背景读者的理解成本。系统分为计算接入、Monitor 集群、存储集群三层,数据与元数据走不同的链路。

Monitor:为什么元数据用 Golang 和 etcd

Monitor 集群维护 OSDMap、PGMap、Pool 与 Image 信息,处理节点加入/删除、卷元数据、创建 pool 以及按拓扑在 OSD 上均匀放置 Raft 组。它不存用户数据、不追求极致性能,所以用 Golang 实现,并用 etcd 做多副本存储。客户端和每个 OSD 启动后都会开启定时器,周期性向 Monitor 拉取 osdmap/pgmap,因此所有节点看到的是同一份集群视图;客户端 IO 只看到 PG 这一层,对特定 PG 的写入不会落到错误的位置。

OSD:数据面与元数据面分离

OSD(Object Storage Daemon)是存储核心,每个 Storage Node 上运行多个 OSD 实例。OSD 内部又分为 RPC 子系统、Raft 子系统、本地存储引擎(localstore)和 kv 子系统。

RPC 子系统按异构网络思路设计,三类消息走两套传输:

RPC 类型路径与用途传输方式
Control RPC客户端/OSD 与 Monitor 之间传 osdmap、pgmap、image 信息TCP socket
Data RPC客户端与 OSD 之间传对象数据与结果protobuf + RDMA
Raft RPCOSD 之间传 Raft 协议消息(内含对象数据)protobuf + RDMA

元数据量小、频率低,socket 足够;对象数据量大、频率高,交给 RDMA 异步语义(RDMA write)承载。

🔁 ## Multi-Raft 的心跳合并:复制多了为什么不卡

每个 PG 对应一个 Raft 组,集群中大量 Raft 组并存。每个组的 leader 都要向 follower 发心跳,组数一多,心跳包就会挤占带宽和 CPU。fastblock 的合并机制是:同一对 leader/follower 之间属于多个 PG 的心跳合并成一个包再发。例如 pg1 和 pg2 都包含 osd1、osd2、osd3 且 osd1 是 leader,未合并时 osd1 要分别向 osd2、osd3 发两次心跳;合并后只需各发一次携带 (pg1, pg2) 的心跳。

Raft 子系统整体还包含:Raft 组的创建/修改/删除、选举与选举超时处理、log 的缓存/落盘/复制到 follower、数据 state machine 落盘、快照管理与 log 恢复、成员变更管理,参考了 willemt 的 C 语言 Raft 实现并扩展出 multi-raft。

本地存储引擎 localstore 基于 SPDK Blobstore,分三个模块:

  • disk_log:存 Raft log,一个 PG(一个 Raft 组)对应一个 SPDK Blob;
  • object_store:存对象数据,一个对象对应一个 Blob;
  • kv_store:每个 CPU 核一个 Blob,存放该核上需要持久化的 kv 数据。

配套的 kv 子系统用于存 Raft 元数据和系统自身数据:数据量不大,内存 hash map 即可容纳全部数据,对外提供 put、remove、get 接口,每 10ms 把变更写盘。

客户端接入方式怎么选:vhost、NBD、CSI

客户端负责创建、修改、删除 image,把用户对 image 的操作转换为对 object(OSD 处理的基本数据单元)的操作,封装成 Data RPC 发给对应 PG 的 leader OSD,再处理返回的响应。接入方式有三种:

  • SPDK vhost:面向虚拟机(QEMU);
  • NBD:面向裸金属服务器;
  • CSI:面向容器环境。

三种模式最终都经由 libfastblock 库完成 image 到 object 的转换并与 OSD 通信。以 vhost 为例,流程是:启动 fastblock-vhost(一个 SPDK 应用,内置定时器周期性向 Monitor 拉取 osdmap/pgmap/image 信息)→ 用 SPDK 的 rpc.py 发送 bdev_fastblock_create 请求创建 image 与 bdev 设备 → 再发 vhost_create_blk_controller 请求,打开设备并注册 vhost 驱动,创建可供 QEMU 连接的 socket → QEMU 通过 vhost-user-blk 设备挂接后,数据请求即由 libfastblock 路由到 leader OSD。

🖥 ## 没有 RDMA 网卡时如何先跑通最小集群

源码可通过git clone https://gitcode.com/openeuler/fastblock获取。编译侧需要安装依赖后分别构建 Monitor 与 OSD(./install-deps.sh./build.sh -t Release -c monitor./build.sh -t Release -c osd),再到 build 目录make install

跑测试环境不强制依赖真实 RDMA 网卡和 NVMe 盘:vstart.sh 的 dev 模式会利用内核模块 rdma_rxe 创建虚拟 RDMA 网卡、用本地文件做 OSD 后端,在单机搭出 3 个 OSD、三副本的集群并自动创建默认 pool。命令只需一行:

./vstart.sh -m dev -c 3 -r 3 -C 2

其中-C指定每个 OSD 占用的核数,建集群时指定后不可再改;运行前需要预留足够的 hugepage。拉起后建议先做状态验证:

fastblock-client -op=status

后续排查 PG 映射、OSD 状态、建池可用-op=getpgmap-op=getosdmap-op=createpool等参数。多机生产部署则切换 pro 模式,分别指定 Monitor IP、RDMA 网卡名与 NVMe 盘,具体参数以 vstart.sh 脚本头部的注释说明为准。

📊 ## 三副本配置下如何看 IOPS 与延迟指标

项目 2024-12 的性能测试报告使用 Kunpeng-920 96 核、100Gb/s 网卡、4K 写、队列深度 32,且所有副本都在同一台测试机上。素材给出的代表数据:

场景工具IOPSp999 延迟
1 个 OSD、单副本block_bench约 35.8 万约 419us
4 个 OSD、单副本block_bench约 81.6 万约 353us
4 个 OSD、三副本(同机)block_bench约 35 万约 446us

同一报告中还有几条对判断路径损耗有用的对比:虚拟机路径(vhost + 虚机内 fio)在单副本下约 32.1 万 IOPS,与 block_bench 差距不大,损耗主要在虚机内部 IO 与 vhost 通信;NVMe-oF 导出在四 OSD 单副本下,RDMA 传输约 78.4 万,与 block_bench 接近,而 TCP 传输损耗明显更大。报告同时提示,三副本全部压在同一台服务器上受本机资源限制,若分布到三台服务器 IOPS 会显著提高——所以读结果时应先看拓扑,再对比数字,报告里也同步记录了网卡与磁盘的利用率截图作为佐证。

🚧 ## 需要留意的边界与演进方向

当前主线是 CMake + SPDK + 用户态客户端;仓库顶层另有一个 kfastblock 内核态块客户端,定位是研发验证版:已具备 attach、元数据拉取、对象级读写和最小块设备 smoke 闭环,但尚不适合生产级稳定性与性能验收,关注内核态接入路径的读者可以留意其 TASKS.md 中的后续计划。

尚未完成或仍在演进的能力(来自项目 README)包括:卷快照与快照组、卷 QoS、OSD 与客户端的多核性能优化、DPU 卸载 vhost、卷加解密与卷共享。已完成的部分则涵盖 CI 接入、Monitor 的 PG 分配插件化、Raft 成员变更与 PG 分配联调、监控数据导出与运行时数据展示等,完整的性能与故障恢复数据可参考 docs/ 目录下的测试报告。

【免费下载链接】fastblockA distributed block storage system that uses mature Raft protocol and is designed for all-flash scenarios项目地址: https://gitcode.com/openeuler/fastblock

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/23 13:57:00

电钻电池上电就停?Arduino电池诊断三步读出BMS真实故障

电钻电池上电就停?Arduino电池诊断三步读出BMS真实故障 【免费下载链接】open-battery-information 项目地址: https://gitcode.com/GitHub_Trending/op/open-battery-information 拧到第三颗螺丝,电钻突然停了。你以为是电池报废,其…

作者头像 李华
网站建设 2026/8/23 13:56:54

BiliTools小白指南:免费把B站视频存到本地的3步教程

BiliTools小白指南:免费把B站视频存到本地的3步教程 【免费下载链接】BiliTools 本项目已停止维护。 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools 想收藏的番剧、教程视频只能在网页上在线看,离线、存档都不方便?…

作者头像 李华