Rustorage

开源 · Rust · S3 兼容

Rustorage

从零实现的 S3 兼容对象存储

纠删码,不是多副本。每份分片自带校验和。崩溃之后,你要么看不到这个对象,要么看到一个完整的它。全部依赖就是几块磁盘,跑起来是一个可执行文件。

64×
范围读少读的字节
0
元数据解析的磁盘调用(缓存命中时)
4+2
六盘 4+2 配置,掉两块盘仍可读写

看设计 看性能数据

它是什么

Rustorage 是一个单节点的 S3 兼容对象存储,用 Rust 从零写成。

纠删码

Reed–Solomon。

单节点多盘

所有盘属于一个 erasure set。

S3 数据面

桶与对象的增删查列。

完整性

每份分片带一个 keyed BLAKE3 校验和。

崩溃一致性

数据先落到 .staging-* 临时名。

运维面

健康检查、就绪探针、Prometheus 指标。

三个设计取舍

这三件事是真正花了心思的地方。

01

纠删码,而不是多副本

同样是 6 块盘。

read_quorum  = N − parity
02

绝不返回坏数据

每份分片带校验和。

换来的是单向的可用性收益。

03

崩溃之后看不到半成品

一次写入分三步。

而且写路径是逐块流式的。

设计图解

四张图,讲清对象放在哪。

bucket → key → 7f3a…c21d → meta.xl part.1 … part.N

对象放在哪

桶就是一个目录。

请求体 → 切块 → Reed–Solomon 编码 → .staging-* 写入 → fsync → rename 提交

一次 PUT 经过什么

请求体被逐块切分。

6 块全在 可读写
掉 2 块 可读写
掉 3 块 503

掉几块盘还能用

4+2 布局下读 quorum 是 4。

旧路径 · GET bytes=0-99 100.7 MB
新路径 · GET bytes=0-99 1.57 MB

取 100 字节要读多少

同一个 64 MiB 对象上的 GET bytes=0-99。

两根横条按真实比例绘制。

性能数据

下面每个数字都来自仓库里的基准。

机制 结果 说明
范围读少读的字节 100 676 742 → 1 573 056 64×
同 key 重复 HEAD 的磁盘调用 12 000 → 0 缓存命中即零磁盘 IO
分页列举的目录遍历 11 430 → 7 230 −37%
单次 PUT 内复用分片缓冲 256 → 16 次显式扩容 16×

也有一个数字是难看的

当一次列举必须扫完整个桶时。

怎么读这些数字

计数是主证据,墙钟是佐证。

刻意不做的事

有边界的 MVP 比没有边界的半成品可信。

  • 不支持 multipart。
  • 单节点。
  • 只监听 127.0.0.1。
  • 没有用户组。
  • 列举走全盘遍历。
  • 控制面板是只读的。

路线图

没有日期。

  1. 多节点与池化
  2. multipart 流式上传
  3. TLS
  4. 自动自愈
  5. 命名空间索引