首页
/ MinIO 存储类(Storage Class)实战指南:按对象配置纠删码奇偶盘

MinIO 存储类(Storage Class)实战指南:按对象配置纠删码奇偶盘

2026-09-05 19:49:52作者:平淮齐Percy

本文基于 MinIO 仓库中的存储类快速入门文档 docs/erasure/storage-class/README.md 展开,讲解 MinIO 纠删码(Erasure Coding)模式下两种存储类 STANDARDREDUCED_REDUNDANCY 的配置方式、磁盘空间占用计算方法、奇偶盘(Parity)取值规则,以及服务端如何将 x-amz-storage-class 请求头落实到对象的实际写入路径。读完后,你可以独立完成存储类的环境变量/mc admin config 配置、根据数据盘/奇偶盘组合评估存储开销,并用客户端按对象指定存储类。

MinIO 16 盘分布式纠删码部署架构

一、存储类的核心概念

MinIO 服务器在纠删码模式下支持存储类(Storage Class),其本质是允许按对象粒度配置“数据盘 + 奇偶盘”的数量组合。MinIO 提供两种内置存储类:

  • STANDARD(标准类):奇偶盘较多,冗余度更高;
  • REDUCED_REDUNDANCY(RRS,低冗余类):奇偶盘较少,磁盘空间利用率更高。

两类存储类的盘数在服务器启动前通过环境变量定义(也可通过 mc admin config 更新)。之后,客户端在 PutObject 请求的元数据中携带 x-amz-storage-class 字段即可指定某个对象使用哪种存储类,MinIO 服务端会遵守该声明,把对象写入对应数量数据盘和奇偶盘构成的纠删码块中。

从源码常量可以看到两种存储类的官方取值与对应环境变量(见 storage-class.go):

// Reduced redundancy storage class
RRS = "REDUCED_REDUNDANCY"
// Standard storage class
STANDARD = "STANDARD"
// Reduced redundancy storage class environment variable
RRSEnv = "MINIO_STORAGE_CLASS_RRS"
// Standard storage class environment variable
StandardEnv = "MINIO_STORAGE_CLASS_STANDARD"

二、存储占用:数据盘/奇偶盘组合对磁盘空间的影响

选择不同数量数据盘与奇偶盘会直接影响磁盘空间占用。借助存储类,你可以针对具体对象在“高冗余”与“高空间利用率”之间做权衡。

16 盘 MinIO 部署 中存放一个 100 MiB 文件为例:

  • 8 数据盘 + 8 奇偶盘:占用约为 2 倍,即 100 MiB 文件约需 200 MiB 空间;
  • 10 数据盘 + 6 奇偶盘:同一文件约需 160 MiB;
  • 14 数据盘 + 2 奇偶盘:同一文件约需 114 MiB。

16 盘部署下不同数据/奇偶盘组合的近似存储占用比如下(“存储占用比” = 纠删编码后文件占用的盘空间 / 文件实际大小):

总盘数 (N) 数据盘 (D) 奇偶盘 (P) 存储占用比
16 8 8 2.00
16 9 7 1.79
16 10 6 1.60
16 11 5 1.45
16 12 4 1.34
16 13 3 1.23
16 14 2 1.14

近似存储占用比 = 总盘数 N / 数据盘数 D(本例中数据盘数 D = N − P)。这个公式可以直接用于容量规划:奇偶盘越多,容错越强,但空间开销也越高。

三、两种存储类的合法取值与默认值

STANDARD 存储类

STANDARD 的奇偶盘应多于 REDUCED_REDUNDANCY,具体规则为:

  • REDUCED_REDUNDANCY 奇偶盘未设置,STANDARD 奇偶盘 ≥ 2
  • REDUCED_REDUNDANCY 奇偶盘已设置,STANDARD 奇偶盘必须大于它;
  • 奇偶块不能超过数据块,因此 STANDARD 奇偶盘不能高于 N/2(N 为纠删集中的总盘数)。

STANDARD 的默认奇偶盘数取决于纠删集(erasure set)中的盘数:

纠删集大小 默认奇偶盘
≤ 5 EC:2
6–7 EC:3
≥ 8 EC:4

源码中的 DefaultParityBlocks 函数给出了与上表一致的默认值(并额外覆盖更小规模的部署):

// DefaultParityBlocks returns default parity blocks for 'drive' count
func DefaultParityBlocks(drive int) int {
	switch drive {
	case 1:
		return 0
	case 3, 2:
		return 1
	case 4, 5:
		return 2
	case 6, 7:
		return 3
	default:
		return 4
	}
}

REDUCED_REDUNDANCY 存储类

REDUCED_REDUNDANCY 的奇偶盘应少于 STANDARD

  • STANDARD 奇偶盘未设置,REDUCED_REDUNDANCY 奇偶盘 < N/2
  • STANDARD 奇偶盘已设置,REDUCED_REDUNDANCY 奇偶盘必须小于它。

REDUCED_REDUNDANCY 的默认值为 EC:1,对应源码常量 defaultRRSParity = 1(见 storage-class.go),其默认配置 DefaultKVS 中 RRS 项的默认值即 "EC:1"

以上取值约束由 validateParity 在启动时统一校验,典型错误信息包括:

  • Standard storage class parity %d should be less than or equal to %d(奇偶盘超过 setDriveCount/2);
  • Standard storage class parity drives %d should be greater than or equal to Reduced redundancy storage class parity drives %d(STANDARD 奇偶盘不大于 RRS 奇偶盘)。

注意:校验在两类都解析完成后才执行,因为需要两个值相互参照才能推断出合法的组合(源码注释明确说明了这一点)。

四、配置存储类

方式一:环境变量

环境变量格式如下:

export MINIO_STORAGE_CLASS_STANDARD=EC:<parity>
export MINIO_STORAGE_CLASS_RRS=EC:<parity>

例如,将 RRS 奇偶盘设为 2、STANDARD 奇偶盘设为 3:

export MINIO_STORAGE_CLASS_STANDARD=EC:3
export MINIO_STORAGE_CLASS_RRS=EC:2

服务端的环境变量帮助文本(errors.go)对其语义的描述是:

MINIO_STORAGE_CLASS_STANDARD:设置 Standard 模式下的奇偶盘数。若 Put 请求未指定存储类,对象将以 Standard 模式存储。 MINIO_STORAGE_CLASS_RRS:设置 Reduced Redundancy 模式下的奇偶盘数。若 Put 请求指定 RRS 存储类,对象将以 Reduced Redundancy 模式存储。

变量值必须严格遵循 EC:<整数> 格式。解析逻辑在 parseStorageClass 中,非法取值会直接报错,例如:

  • 段落数不对:Too few/Too many sections in <value>
  • 前缀不是 ECUnsupported scheme <s>. Supported scheme is EC
  • 奇偶盘不是非负整数:Unsupported parity value <v> provided

方式二:mc admin config

除了环境变量,存储类还可以通过 mc admin config 的 get/set 命令更新配置(子配置项为 standardrrsoptimizeinline_block,见 DefaultKVS),相关说明可参考仓库中的 docs/config/README.md

环境变量与配置文件两者并存时,LookupConfig 通过 env.Get(StandardEnv, kvs.Get(ClassStandard)) 的调用方式可以看出:环境变量优先级高于配置文件值

配置生效的两条规则(重要)

  1. 若已定义 STANDARD(无论通过环境变量还是 mc admin config),而请求元数据中没有 x-amz-storage-class,MinIO 会对该对象应用 STANDARD 存储类,即按其配置的数据盘/奇偶盘写入。
  2. 若启动 MinIO 前未定义任何存储类,而 PutObject 请求的 x-amz-storage-class 字段值为 REDUCED_REDUNDANCYSTANDARD,服务端会直接使用默认奇偶盘值(即上文默认值表)写入。

这两条规则在源码中都能找到对应实现:GetParityForSC 对空字符串走 Standard 分支(对应规则 1);当存储类尚未初始化或未配置时返回 -1,由调用方回退到 er.defaultParityCount(对应规则 2)。

五、服务端如何将存储类落实到写入路径

理解配置后,下面看一下一个对象在 MinIO 服务端如何真正按存储类落盘。

1. 请求层提取 x-amz-storage-class 在对象处理逻辑中,服务端会从请求头(或表单)读取该字段并保留进对象元数据,例如 object-handlers.go 中的处理:

// Storage class is special, it can be replaced regardless of the
// metadata directive, if set should be preserved and replaced
// to the destination metadata.
sc := r.Header.Get(xhttp.AmzStorageClass)
if sc == "" {
    sc = r.Form.Get(xhttp.AmzStorageClass)
}

注释特别指出:存储类是“特殊”元数据,不受 x-amz-metadata-directive(COPY/REPLACE)影响,设置后都会被保留并写入目标对象元数据——这保证了对象迁移/复制场景下存储类声明不丢失。

2. 对象层按存储类计算奇偶盘与写仲裁数。 在纠删码对象的写入路径中(erasure-object.go):

storageDisks := er.getDisks()
// Get parity and data drive count based on storage class metadata
parityDrives := globalStorageClass.GetParityForSC(opts.UserDefined[xhttp.AmzStorageClass])
if parityDrives < 0 {
    parityDrives = er.defaultParityCount
}
dataDrives := len(storageDisks) - parityDrives

// we now know the number of blocks this object needs for data and parity.
// writeQuorum is dataBlocks + 1
writeQuorum := dataDrives
if dataDrives == parityDrives {
    writeQuorum++
}

关键点:

  • 奇偶盘数直接取自对象元数据中的 x-amz-storage-class,即每个对象可以有不同的数据盘/奇偶盘组合
  • 数据盘数 = 纠删集总盘数 − 奇偶盘数;
  • 写仲裁数(writeQuorum)为数据盘数,当数据盘数与奇偶盘数相等时为 D+1——这正是纠删码写入所需的最低成功盘数,决定了该对象能容忍多少盘故障。

3. 启动阶段的默认值回退。 在尚无服务端配置时,格式初始化会调用 ecDrivesNoConfig,尝试从环境变量读取,否则回退到默认奇偶盘数,保证磁盘格式化阶段也能得到合法的 EC 布局。

六、客户端示例:用 minio-go 指定 REDUCED_REDUNDANCY

下面示例使用 minio-go 将对象存储类设置为 REDUCED_REDUNDANCY。假设纠删集为 8 盘且按上文方式将 RRS 配置为 EC:2,则该对象会拆分到 6 个数据盘 + 2 个奇偶盘(原文示例即按此场景说明):

s3Client, err := minio.New("localhost:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true)
if err != nil {
	log.Fatalln(err)
}

object, err := os.Open("my-testfile")
if err != nil {
	log.Fatalln(err)
}
defer object.Close()
objectStat, err := object.Stat()
if err != nil {
	log.Fatalln(err)
}

n, err := s3Client.PutObject("my-bucketname", "my-objectname", object, objectStat.Size(), minio.PutObjectOptions{ContentType: "application/octet-stream", StorageClass: "REDUCED_REDUNDANCY"})
if err != nil {
	log.Fatalln(err)
}
log.Println("Uploaded", "my-objectname", " of size: ", n, "Successfully.")

其中 PutObjectOptions.StorageClass 字段最终会作为 x-amz-storage-class 请求头发送,与第五节的服务端处理逻辑一一对应。

七、延伸阅读:存储类子系统的两个高级配置项

storage-class.go 中,除了两个核心环境变量,还存在两个与存储类同属 storage-class 子系统的进阶配置项,理解它们有助于完整把握该子系统的行为边界:

1. MINIO_STORAGE_CLASS_OPTIMIZE

取值 availability(默认)或 capacity

  • availability(默认):有盘离线时会使用更多奇偶盘写入,以维持既定的奇偶盘冗余水平(见 AvailabilityOptimized);
  • capacity:有盘离线时不额外提升奇偶数,优先保证容量利用率(见 CapacityOptimized)。

2. MINIO_STORAGE_CLASS_INLINE_BLOCK

指定可“内联”写入 xl.meta 的纠删分片大小阈值,默认 128 KiB(见 LookupConfig)。启用版本控制(versioned bucket)时,该阈值自动取 1/8(见 ShouldInline)。源码注释明确提醒:该值是按“每个盘的分片大小”计算的,且若配置超过推荐的 128 KiB 上限,PUT 性能可能下降,变更前应自行做基准测试。

八、要点小结

主题 结论 依据
支持范围 仅纠删码(erasure coding)模式;目前支持的编码方案只有 EC docs/erasure/storage-class/README.mdparseStorageClass
配置入口 MINIO_STORAGE_CLASS_STANDARD=EC:<p> / MINIO_STORAGE_CLASS_RRS=EC:<p>,或 mc admin config errors.goLookupConfig
空间占用比 近似 = N/D(总盘数/数据盘数) 原文档 16 盘示例表
默认奇偶盘 STANDARD:集大小 ≤5 为 EC:2、6–7 为 EC:3、≥8 为 EC:4;RRS 默认 EC:1 DefaultParityBlocksdefaultRRSParity = 1
取值约束 奇偶盘 ≤ N/2;STANDARD 奇偶盘 ≥ RRS 奇偶盘;RRS 默认 1 validateParity
按对象生效 请求头/元数据 x-amz-storage-class 决定单对象的 D/P 组合;未指定时按 STANDARD GetParityForSCerasure-object.go

通过以上配置与验证机制,你可以在同一套纠删码集群内,为不同价值/重要程度的数据选择不同冗余度:关键数据走 STANDARD 换取更强容错,冷数据或可再生数据走 REDUCED_REDUNDANCY 换取更高的磁盘空间利用率。

登录后查看全文
热门项目推荐
相关项目推荐