第 9/20 天
引言:存储池策略——副本与纠删码的抉择
在上一篇中,我们完成了存储池(Pool)的创建与 PG 数量规划,集群已经能够以默认的副本模式对外提供存储服务。然而,在生产环境中,并非所有数据都需要相同级别的冗余策略。副本池(Replicated Pool) 简单可靠但存储开销大,纠删码池(Erasure Coded Pool) 以计算换空间、大幅提升存储效率但牺牲了部分延迟性能。
这一选择直接影响着集群的存储成本、读写性能和容灾能力。一个典型的生产集群往往同时部署两种策略:热数据走副本池以获得最低延迟,温冷数据走纠删码池以最大化存储利用率。本篇将深入剖析两种策略的工作原理、数据流向和设计考量,并在 Ubuntu 24.04 LTS + Ceph Squid v19 环境下完成完整的部署实战。

一、副本池架构与工作原理
1.1 数据分布机制
副本池是 Ceph 最传统、最成熟的存储策略。每个写入的对象会被完整复制到 N 个 OSD 上(默认 3 副本),每个副本位于不同的故障域中。其核心流程如下:
| 阶段 | 操作 | 参与组件 |
|---|---|---|
| 客户端写入 | 计算对象所属 PG 的主 OSD | Client、Monitor(CRUSH Map) |
| 主 OSD 分发 | 将数据转发到其余副本 OSD | Primary OSD → Replica OSDs |
| 副本确认 | 所有副本写入完成后 ack | Replica OSDs → Primary OSD |
| 客户端确认 | 主 OSD 向客户端返回成功 | Primary OSD → Client |
1.2 读写一致性保证
Ceph 采用 Primary-Replica 模型保证强一致性:
- 写入路径:客户端只与 Primary OSD 通信,Primary 负责将数据并行分发到所有 Replica OSD。只有当所有副本都返回 ack 后,Primary 才向客户端确认写入完成。这确保了任何成功写入的数据在所有副本上都有一致拷贝。
- 读取路径:客户端默认从 Primary OSD 读取数据。虽然 Ceph 支持从副本读取(
rbd_balance_snap_reads、osd_read_op_preference),但为保证强一致性,生产环境通常仍从 Primary 读取。
1.3 存储开销分析
3 副本意味着有效存储容量仅为原始容量的 1/3(33.3%)。对于 TB 级别的集群,这是巨大的硬件成本。2 副本可将效率提升至 50%,但容错能力下降为仅能丢失 1 个 OSD。
二、纠删码池架构与工作原理
2.1 纠删编码基本原理
纠删码(Erasure Code, EC)借鉴了 RAID 5/6 的思想,但将其扩展到分布式层面。一个对象被拆分为 k 个数据块(data chunks) 和 m 个编码块(coding chunks),这 k+m 个块分散存储在不同的 OSD 上。
以最常见的 k=4, m=2 配置为例:
- 一个 4MB 的对象被拆分为 4 个 1MB 数据块 + 2 个 1MB 编码块
- 总共占用 6MB 原始空间,有效存储效率为 4/6 ≈ 66.7%
- 可容忍 2 个块丢失(即 2 个 OSD 故障)仍能完整恢复数据
对象 (4MB)
├── data chunk 0 (1MB) → OSD-1
├── data chunk 1 (1MB) → OSD-2
├── data chunk 2 (1MB) → OSD-3
├── data chunk 3 (1MB) → OSD-4
├── coding chunk 0 (1MB) → OSD-5 ← Reed-Solomon 编码
└── coding chunk 1 (1MB) → OSD-6 ← Reed-Solomon 编码
存储效率: 4/(4+2) = 66.7% 容错: 可丢失 2 个块
对比 3 副本: 效率 33.3% 容错: 可丢失 2 个副本
2.2 Reed-Solomon 编码
Ceph 默认使用 Reed-Solomon 纠删算法。其数学基础是伽罗华域 GF(2^n) 上的多项式运算,能够从任意 k 个存活的块中完整恢复原始数据。编码块是数据块的线性组合:
# Reed-Solomon 编码原理示意(伪代码)
# 编码矩阵 C 将 k 个数据块变换为 m 个编码块
coding_chunk[i] = sum(data_chunk[j] * C[i][j] for j in range(k)) mod GF(2^8)
# 解码:当部分块丢失时,从存活的 k 个块重建
# 存活块构成新方程组,求逆矩阵即可恢复原始数据
2.3 数据流向差异
| 维度 | 副本池 | 纠删码池 |
|---|---|---|
| 写入路径 | Primary → 所有 Replica(全量复制) | Primary → 数据/编码块 OSD(分块分发) |
| 读取路径 | Primary 返回完整对象 | Primary 需读取 k 个数据块并重组 |
| 网络开销 | 写 N 份完整数据 | 写 k+m 份分块数据(总量更少) |
| CPU 开销 | 极低(仅复制) | 编码/解码计算开销显著 |
| 故障恢复 | 从任意存活副本完整拷贝 | 从 k 个存活块数学重建 |
2.4 纠删码池的局限性
EC 池虽然存储效率高,但存在重要限制:
- 不支持 omap:EC 池无法存储对象映射(omap)数据,因此不能直接用于 RBD 元数据池、CephFS 元数据池或 RGW index 池
- 写入放大:部分写入(覆盖写)需要读取-修改-写回整个对象,性能极差
- 延迟更高:读取需从多个 OSD 聚合 k 个块,网络往返延迟叠加
- 典型适用场景:对象存储 RGW 的数据池、归档冷数据、备份存储

三、部署实战:副本池创建与验证
3.1 环境准备
确保集群已正常运行,OSD 数量满足故障域要求:
# 检查集群健康状态
ceph -s
# 查看 OSD 数量与分布
ceph osd tree | head -30
# 确认可用磁盘空间
ceph df
# 查看当前存储池列表
ceph osd pool ls detail
3.2 创建生产级副本池
以下命令创建一个用于 RBD 块存储的 3 副本生产池:
# 创建副本池,指定 PG 数量(基于第 8 天的 PG 规划)
# pool名称: rbd-ssd-pool,目标 ~100 个 PG
ceph osd pool create rbd-ssd-pool 128 128 replicated
# 设置副本数为 3(默认值,显式声明)
ceph osd pool set rbd-ssd-pool size 3
# 设置 min_size,低于此值停止写入(生产建议 >= 2)
ceph osd pool set rbd-ssd-pool min_size 2
# 启用 RBD 应用(标记池用途)
ceph osd pool application enable rbd-ssd-pool rbd
# 初始化 RBD 池
rbd pool init rbd-ssd-pool
3.3 关键配置参数详解
# pg_num / pgp_num:PG 数量与放置组数量(应保持一致)
ceph osd pool set rbd-ssd-pool pg_num 128
ceph osd pool set rbd-ssd-pool pgp_num 128
# crush_rule:指定使用的 CRUSH 规则(故障域控制)
# 使用第 7 天定义的 host 级别故障域规则
ceph osd pool set rbd-ssd-pool crush_rule replicated_rule
# noscrub / nodeep-scrub:临时禁用清理(维护期间使用)
# 生产环境不建议长期禁用
ceph osd pool set rbd-ssd-pool noscrub false
ceph osd pool set rbd-ssd-pool nodeep-scrub false
# recovery_priority:恢复优先级(0-63,值越大优先级越高)
ceph osd pool set rbd-ssd-pool recovery_priority 5
# 查看池完整配置
ceph osd pool get rbd-ssd-pool all
3.4 验证副本池状态
# 查看池详细状态
ceph osd pool ls detail | grep rbd-ssd-pool
# 查看池的 PG 分布
ceph pg ls-by-pool rbd-ssd-pool | head -20
# 查看副本完整性统计
ceph osd pool stats rbd-ssd-pool
# 查看实际存储效率(已用/可用)
ceph df | grep -A2 rbd-ssd-pool
四、部署实战:纠删码池创建与验证
4.1 创建纠删码配置文件
EC 池使用独立的 erasure-code-profile 定义编码参数。生产环境通常自定义 profile:
# 查看默认 EC profile
ceph osd erasure-code-profile ls
ceph osd erasure-code-profile get default
# 创建生产级 EC profile:k=4, m=2, host 故障域
# 含义:4 数据块 + 2 编码块,分布在不同 host
ceph osd erasure-code-profile set ec-profile-prod
k=4
m=2
crush-failure-domain=host
crush-device-class=ssd
plugin=jerasure
technique=reed_sol_van
# 验证 profile 内容
ceph osd erasure-code-profile get ec-profile-prod
4.2 创建纠删码存储池
# 创建 EC 池
# 注意:EC 池的 PG 数量计算与副本池不同
# k+m=6 个块需要分布在至少 6 个不同 host 上
ceph osd pool create ec-data-pool 128 128 erasure ec-profile-prod
# 设置 PG autoscaler 为 on(推荐 EC 池使用自动伸缩)
ceph osd pool set ec-data-pool pg_autoscale_mode on
# 启用 RGW 应用(EC 池典型用于对象存储数据池)
ceph osd pool application enable ec-data-pool rgw
4.3 为 EC 池配置元数据池(RGW 场景)
EC 池不支持 omap,RGW 需要一个副本池作为元数据池:
# 创建 RGW 元数据池(副本池)
ceph osd pool create rgw-meta-pool 64 64 replicated
ceph osd pool set rgw-meta-pool size 3
ceph osd pool application enable rgw-meta-pool rgw
# 创建 RGW index 池(副本池,用于 bucket index)
ceph osd pool create rgw-index-pool 64 64 replicated
ceph osd pool set rgw-index-pool size 3
ceph osd pool application enable rgw-index-pool rgw
# 创建 RGW 控制池
ceph osd pool create rgw-control-pool 32 32 replicated
ceph osd pool application enable rgw-control-pool rgw
# 在 zone 配置中将 ec-data-pool 设为数据池
# 后续 RGW 章节会详细展开
4.4 验证纠删码池状态
# 查看 EC 池编码信息
ceph osd pool ls detail | grep ec-data-pool
# 查看 EC profile 生效情况
ceph osd dump | grep ec-data-pool
# 查看块分布(确认 k+m 块在不同 host)
ceph pg ls-by-pool ec-data-pool | head -10
# 验证存储效率
ceph df
# STORED 栏显示原始存储量,USED 栏显示实际占用量
# EC 池 USED/STORED 比值应接近 (k+m)/k = 1.5
五、性能基准测试对比
使用 Ceph 内置基准工具对比两种池的读写性能:
# 副本池写入基准测试(10秒,4MB块大小,16并发)
rados bench -p rbd-ssd-pool 10 write –no-cleanup -b 4194304 -c 16
# 纠删码池写入基准测试(同样参数)
rados bench -p ec-data-pool 10 write –no-cleanup -b 4194304 -c 16
# 顺序读取测试
rados bench -p rbd-ssd-pool 10 seq
rados bench -p ec-data-pool 10 seq
# 清理基准测试数据
rados -p rbd-ssd-pool cleanup
rados -p ec-data-pool cleanup
典型结果对比(12 节点集群,SSD 介质):
{
"replicated_pool_write": {
"bandwidth": "850 MB/s",
"iops": 212,
"latency_avg": "75ms"
},
"erasure_coded_pool_write": {
"bandwidth": "520 MB/s",
"iops": 130,
"latency_avg": "123ms"
},
"storage_efficiency": {
"replicated_3x": "33.3%",
"ec_4_2": "66.7%"
},
"conclusion": "EC 写入带宽约为副本池的 61%,但存储效率提升 100%"
}
六、生产环境注意事项与踩坑提示
6.1 纠删码池踩坑提示
踩坑一:EC 池覆盖写性能灾难
EC 池对覆盖写(overwrite)支持不佳。每次部分写入需要先读取完整对象、解码、修改、重新编码并写回所有 k+m 个块,导致严重的写放大。
# 生产建议:EC 池仅用于 append-only 或一次性写入场景
# RGW 对象存储天然是 append-only 模型,与 EC 池完美匹配
# RBD 块存储默认不支持 EC(除非使用 cache tiering)
踩坑二:EC 池 PG 数量需要更多 OSD
k=4, m=2 的 EC 池需要至少 6 个位于不同故障域的 OSD。如果 host 数量不足 6,CRUSH 将无法放置所有块,PG 会处于 incomplete 状态。
# 检查 host 数量是否满足 EC profile 要求
ceph osd tree | grep host | wc -l
# 至少需要 k+m 个 host(如 k=4,m=2 则至少 6 个 host)
6.2 副本数与 min_size 调优
# 生产环境 min_size 调优建议:
# size=3, min_size=2 → 允许 1 个 OSD 故障时继续写入(推荐)
# size=3, min_size=3 → 严格模式,任何 OSD 故障即停止写入(数据更安全但可用性低)
# size=2, min_size=1 → 高风险,仅用于测试环境
# 查看当前 min_size
ceph osd pool get rbd-ssd-pool min_size
# 紧急降级场景(多 OSD 故障时保可用性)
# 仅在确认数据一致性风险后执行
ceph osd pool set rbd-ssd-pool min_size 1
6.3 存储效率与容错的平衡选择
| 场景 | 推荐策略 | 理由 |
|---|---|---|
| RBD 块存储(虚拟机/容器盘) | 3 副本 | 低延迟、支持覆盖写 |
| RBD 元数据池 | 3 副本 | 需要 omap 支持 |
| RGW 对象数据池 | EC k=4,m=2 | 对象 append-only,存储效率优先 |
| RGW index/control 池 | 3 副本 | 需要 omap 支持 |
| CephFS 数据池 | 3 副本或 EC | 冷数据可用 EC,热数据用副本 |
| CephFS 元数据池 | 3 副本 | 必须,需 omap + 低延迟 |
| 归档备份存储 | EC k=8,m=4 | 极致存储效率(66.7%→更高) |
6.4 安全与容灾考量
- 故障域隔离:EC 池的 m 值决定了可容忍的故障数。如果 m=2 但所有编码块在同一机柜,机柜故障将导致数据丢失。务必在 EC profile 中设置
crush-failure-domain=host或rack - 数据校验:定期执行 deep-scrub 确保块完整性。EC 池的 scrub 会校验所有 k+m 块的数学一致性
- 恢复时间:EC 池 OSD 故障后重建需要从 k 个存活块读取并计算,恢复时间显著长于副本池的完整拷贝

七、常见问题
Q1:纠删码池能否直接用于 RBD 块存储?
EC 池不能直接作为 RBD 的数据池,因为 RBD 需要覆盖写和 omap 支持。生产方案是使用 Cache Tiering:前端放置一个副本池作为缓存层,后端为 EC 池。热数据在副本缓存中低延迟读写,冷数据被 flush 到 EC 池节省空间。但 Cache Tiering 配置复杂、运维成本高,需谨慎评估。在 Ceph Squid v19 中,推荐对块存储场景直接使用副本池,EC 池保留给对象存储。
Q2:如何从副本池迁移数据到纠删码池?
Ceph 不支持在线将现有池从副本模式转换为 EC 模式。迁移方案有两种:(1)创建新的 EC 池,使用 rados cppool 命令批量拷贝对象;(2)在 RGW 层面配置多站点同步,将新数据写入 EC 池。迁移前务必做完整备份,并在低峰期执行,避免影响生产 I/O。
Q3:纠删码的 k 和 m 值如何选择?
k 值决定存储效率,m 值决定容错能力。常见组合:k=4,m=2(效率 66.7%,容 2 故障)适合中等规模;k=8,m=4(效率 66.7%,容 4 故障)适合大规模归档;k=6,m=3(效率 66.7%,容 3 故障)是均衡选择。注意 k+m 必须小于等于集群中故障域(host/rack)的数量。增大 k 值虽可提升效率,但写入延迟随之增加(需等待更多 OSD ack)。
八、总结
本篇深入对比了 Ceph 的两种核心存储池策略。副本池 以全量复制保证最低延迟和最强一致性,适合 RBD 块存储和元数据池;纠删码池 以 Reed-Solomon 编码换取最高存储效率,适合对象存储数据池和归档场景。在 Ceph Squid v19 生产环境中,典型的部署模式是:副本池承载热数据和元数据,EC 池承载温冷数据和对象存储。选择时需要综合考量存储成本、性能需求、故障域规模和运维复杂度,切忌盲目追求存储效率而忽略延迟和覆盖写场景的适用性。
九、下期预告
明天我们将进入 第 10 天:Ceph 块存储 RBD 配置与生产实践。RBD(RADOS Block Device)是 Ceph 最常用的存储接口之一,广泛用于虚拟机磁盘、容器持久卷和数据库存储。我们将深入 RBD 的分层快照、镜像克隆、QoS 限速等高级特性,并完成一个完整的 RBD 生产部署流程。
十、系列目录
- ✅ 第 1 天:Ceph 架构概述与生产环境选型指南
- ✅ 第 2 天:Ubuntu 系统准备:内核调优与磁盘规划
- ✅ 第 3 天:Cephadm 部署工具详解与集群引导初始化
- ✅ 第 4 天:Monitor 节点部署与高可用配置
- ✅ 第 5 天:Manager 节点部署与模块启用
- ✅ 第 6 天:OSD 存储节点部署:BlueStore 配置与磁盘管理
- ✅ 第 7 天:CRUSH Map 架构解析与故障域规划
- ✅ 第 8 天:存储池(Pool)创建与 PG 数量规划
- 📌 第 9 天:副本与纠删码存储池策略对比实战(本文)
- ⏳ 第 10 天:Ceph 块存储 RBD 配置与生产实践
- ⏳ 第 11 天:Ceph 对象存储 RGW 网关部署与 S3 兼容
- ⏳ 第 12 天:CephFS 分布式文件系统部署与挂载
- ⏳ 第 13 天:Ceph 网络架构:集群网络与公共网络分离
- ⏳ 第 14 天:Ceph 认证体系 cephx 与用户权限管理
- ⏳ 第 15 天:Ceph 集群监控:Prometheus + Grafana + 内置仪表盘
- ⏳ 第 16 天:Ceph 性能调优:OSD 参数与缓存分层
- ⏳ 第 17 天:Ceph 集群扩容实战:OSD 动态添加与 CRUSH 重平衡
- ⏳ 第 18 天:Ceph 高可用与容灾设计:多副本、跨机房与异地灾备
- ⏳ 第 19 天:Ceph 故障排查与数据恢复实战
- ⏳ 第 20 天:Ceph 生产环境升级维护与版本迭代策略

















暂无评论内容