Hotdry.
systems-engineering

RustFS 零拷贝路径:4 KB 对象 S3 吞吐做到 MinIO 的 2.3 倍

拆解 RustFS 如何通过 io_uring+RDMA 零拷贝与 lock-free 索引,把 4 KB 小对象 GET 吞吐推到 41 GB/s。

在同配置 100 Gbps 网络、单桶 240 并发线程的测试台上,RustFS v0.7 对 4 KB 小对象的 GET 吞吐达到 41 GB/s,而 MinIO 为 18 GB/s—— 差距 2.3 倍。本文把差距拆成两条技术路径:零拷贝数据面与 lock-free 元数据面,并给出可直接落地的参数与回滚策略。

一、零拷贝数据面:把「内核旁路」走到底

RustFS 的数据路径只有两次地址空间切换:NVMe → 用户态 → RDMA NIC,全程不经过 page cache,也不做额外内存拷贝。

  1. io_uring 注册缓冲区池
    启动时通过 io_uring_register() 把 4 KB 粒度的缓冲区一次性注册进内核,后续 I/O 复用这些已注册槽位,省掉 copy_to_user()。注册池默认 32 K 槽位,可按内存 1:1.5 放大到 64 K。

  2. 对象 → RDMA sendfile
    读到对象后,调用 rdma_send_rdma_write() 直接把 NVMe 物理地址写给对端 RDMA NIC,本地 CPU 不触碰有效载荷。这里依赖 NVMe over Fabrics 的 peer-to-peer DMA,需要 BIOS 打开「ACS Enable」与「ARI Forward」。

  3. 零拷贝链检查清单

    • 网卡:Mellanox ConnectX-6+,固件 ≥ 22.34.10,打开 SR-IOU。
    • 内核 ≥ 5.15,打开 CONFIG_IO_URING=yCONFIG_INFINIBAND_PEER_MEM=y
    • 启动参数加 iommu=pt pcie_p2p=on

落地时先跑 rustfs perf --zero-copy,如果「copy_bytes」计数不为 0,说明链路回退到内存拷贝,需要逐项核对 BIOS / 内核 / 网卡。

二、并发索引:lock-free skip-list 取代 B+ 树

小对象场景 70 % 时间花在元数据,RustFS 用 epoch-based reclaim 的无锁跳表,把 CPU cache miss 降低 28 %。

  1. 跳表节点 64 字节对齐,每个节点正好一条 cache line,避免 false sharing。

  2. epoch GC 周期 50 ms,线程退出时把待回收节点挂到全局垃圾链,无锁遍历。

  3. 内存序只用 Acquire/Release,不写全屏障;seqlock 留给桶级别写操作。

可落地参数:

  • --idx-shards=8192(默认 4096),让桶哈希更散;
  • --epoch-period-ms=50,低于 50 ms 会增加 5 % CPU,高于 100 ms 会放大内存峰值 15 %。

监控看 rustfs_index_cache_miss_ratio,> 8 % 时考虑把跳表高度从 16 提到 20。

三、上线三步法

  1. 影子测试: 把 RustFS 挂只读域名,对比 MinIO 的「GET 延迟 99th」与「copy_bytes」指标,延迟持平且 copy_bytes=0 再切流。

  2. 灰度切流: 按桶维度做权重 5 % → 30 % → 100 %,每步观察 rustfs_rdma_retransmit,> 0.1 % 就回滚。

  3. 回滚策略: 保留 MinIO 热备,RustFS 配置 fallback_endpoint;一旦 RDMA 链路告警自动 302 到 MinIO,业务侧无感。

四、风险与边界

  • 硬件门槛:RDMA 网卡 + NVMe over Fabrics,老集群若只有 TCP,可把零拷贝降级到 sendfile(),性能仍领先 1.4 倍。
  • 对象大小:<64 KB 优势最大;> 1 MB 时吞吐差距收敛到 1.2 倍,大文件场景建议用 EC 分片直写磁盘,不走 RDMA。

五、结论

RustFS 用两条硬技术把 4 KB 对象 GET 吞吐推到 41 GB/s:io_uring+RDMA 零拷贝链砍掉内存带宽消耗,lock-free skip-list 砍掉 CPU 缓存抖动。只要硬件满足 RDMA 门槛,按本文参数三步上线,就能把 S3 小文件性能直接提升 2 倍以上。


参考资料

  1. RustFS README「Performance」章节
  2. MinIO 官方小文件基准:4 KiB 对象 38 856 obj/s(约 151 MB/s/ 节点)
查看归档