10.7 纠删码与副本的取舍
一句话
副本用 “空间换简单”(3 份、读任意一份、修复只拷一份),纠删码用 “计算换空间”(1.4–1.5 份、重建要读 k 块、CPU 参与);选型只看两个数:存储成本与重建代价。
实测:几种方案的空间与重建代价
| 方案 | 空间开销 | 可容错 | 重建 1 块需读 |
|---|---|---|---|
| 3 副本 | 3.00× | 2 块 | 1 份 |
| EC 4+2 | 1.50× | 2 块 | 4 块 |
| EC 6+3 | 1.50× | 3 块 | 6 块 |
| EC 8+3 | 1.38× | 3 块 | 8 块 |
| EC 10+4 | 1.40× | 4 块 | 10 块 |
例:1PB 原始数据 → 3 副本 3PB;EC 8+3 约 1.375PB(省 54%)。
空间开销 = (k + m) / k
重建读放大 ≈ k(修 1 块要读 k 块参与解码)
可容错 = m 块
三者的真实代价对比
| 维度 | 3 副本 | 纠删码 |
|---|---|---|
| 存储成本 | 3× | 1.4–1.5× |
| 读延迟 | 低(任一副本) | 中(正常读也读多块/或从一块读) |
| 重建网络 | 1 份 | k 份 |
| 重建 CPU | 无 | 有(解码) |
| 小对象效率 | 差(3 倍空间) | 更差(分块开销占比高) |
| 适用 | 热数据、低延迟、小对象 | 温/冷数据、大对象、归档 |
代码:算一算 “该用哪个”
def cost(size_pb, k, m, price_per_tb_month=20, rebuild_gbps=1):
overhead = (k + m) / k
stored = size_pb * overhead
monthly = stored * 1024 * price_per_tb_month
rebuild_hours = (size_pb * 1024) / (rebuild_gbps * 3600) * k # 重建读 k 份
return dict(overhead=round(overhead, 2), stored_pb=round(stored, 2),
monthly_usd=round(monthly), rebuild_hours=round(rebuild_hours, 1))
print("3 副本:", cost(1, 1, 2)) # 近似 3x
print("EC 8+3:", cost(1, 8, 3))
判据:热数据用副本(延迟与小对象友好),冷数据用 EC(空间省 50%+);重建带宽与 CPU 要单独评估,否则 “省下的存储费” 会被 “重建时间/业务影响” 吃掉。
反模式
| 反模式 | 后果 |
|---|---|
| 全部数据用 3 副本 | 存储成本 2–3 倍,账单难看 |
| 热数据用 EC | 读放大 + 解码 CPU,延迟上升 |
| 小对象用 EC | 分块与元数据开销占比过高 |
| 只看空间、不看重建 | 集群越大,重建越慢,故障窗口越长 |
| 重建不限速 | 重建流量挤占前台,业务抖动 |
| 不做过 “同时坏 2 块” 的演练 | 真坏 2 块时才发现恢复不了 |
三条铁律
🔑 热数据副本、冷数据 EC;按访问频率分层。
🔑 EC 的重建读放大 ≈ k,要按 RTO 反推 k 与带宽。
🔑 空间省下来的钱,要扣掉重建与 CPU 成本 再比较。
自检
Q1 为什么 EC 8+3 的空间开销是 1.375×,而不是 8/3?
▸ 答案:因为公式是 (k+m)/k:8 个数据块 + 3 个校验块 = 11 块存 8 块的数据,11/8 = 1.375。8/3 是 “每 3 个数据块配 1 个校验块” 的另一种配比(3+1),不是 8+3 的算法。
Q2 EC 的 “重建读放大 ≈ k” 意味着什么?
▸ 答案:意味着修 1 个块要读取 k 个块参与解码:k 越大,重建占用的网络与磁盘带宽越多,重建时间越长。所以 “k 大省空间” 的代价是 “重建更贵、故障窗口更长”。
Q3 为什么热数据不用 EC?
▸ 答案:因为 EC 在正常读时也可能要读多块并解码(取决于实现),带来读放大与 CPU 开销;而热数据对延迟敏感、访问频繁,3 副本 “读任意一份” 更简单更快。EC 的优势(省空间)在热数据上被 “延迟成本” 抵消。
Q4 小对象为什么不适合 EC?
▸ 答案:因为 EC 要把对象切成 k 块并生成 m 个校验块:对象越小,分块与元数据开销占比越高,甚至 “校验块比数据还大”。小对象通常用副本或 “打包成大对象再 EC”。
Q5 重建速度怎么估?
▸ 答案:重建时间 ≈ (数据量 × k) / 可用带宽:例如 1PB、EC 8+3、重建带宽 1Gbps,理论约 1PB×8 / 1Gbps ≈ 8×10^15×8/(1.25×10^8) 秒 量级(约数天)。所以大规模集群必须限速并规划 “故障窗口”。
Q6 3 副本真的能容 2 块故障吗?
▸ 答案:能,但仅在故障域独立时:3 副本分布在 3 个不同机架,坏 2 个机架仍剩 1 份;如果 3 份都在同一机架,坏 1 个机架就全丢(见 10.6 元数据管理与副本放置)。所以 “容错数” 必须和 “故障域” 一起说。
Q7 怎么决定 “哪些数据用 EC”?
▸ 答案:按 “访问频率 × 对象大小 × 延迟要求” 分层:热 + 小 + 低延迟 → 副本;温/冷 + 大 + 可容忍延迟 → EC;归档可以更激进(如 EC 10+4 + 更高压缩)。分层策略要写进生命周期规则,而不是靠人工判断。
关联
- 前置:10.1 块存储 / 文件存储 / 对象存储、10.6 元数据管理与副本放置
- 并列:10.8 对象存储系统设计、10.3 云盘性能模型
- 下游:44.5 存储引擎:读写放大与空间放大、36.3 冷备-温备-热备