跳转至

纠删码 vs 三副本存储策略

作者:JiangChong | 撰写时间:2026年09月

适用场景:HDFS 磁盘空间紧张、想给大文件/冷数据降低存储成本,或正在规划湖仓底座存储方案的团队。读完本文你能判断哪些目录该用三副本、哪些该用纠删码(Erasure Coding,EC),以及如何安全地把存量数据迁移过去。

阅读前回顾(30 秒)

前两篇 HDFS 架构原理 和 HDFS 读写流程与副本放置策略 讲了仓库的基本盘:块(block)是标准集装箱,每箱货存 3 份、放在 2 个机架上(2+1 格局),丢 2 份都不慌。本文讲一个现实问题——仓库租金太贵:

  • 贵在哪:每 1 份数据占 3 份磁盘,10 PB 数据要买 30 PB 磁盘;
  • 怎么省:纠删码(EC)给货物配「数学校验块」——数据切 6 份、再算出 3 份校验,组成 6+3 组合,任意 6 份就能拼回原数据,只用 1.5 倍磁盘,容错不打折;
  • 代价:读取和故障重建要多花 CPU 与网络——所以它只适合大文件、冷数据。

读完本文,你会掌握:哪些数据该上 EC、迁移怎么操作、坑在哪里。

关联文章

理解全文脉络

本文先讲三副本「为什么贵」(第 1 节),再讲纠删码如何用更少的空间达到几乎同等的容错(第 2 节),随后用一张表把两者的取舍摊开(第 3 节),并单独解释 EC 为什么不适合小文件(第 4 节)。想直接动手的读者,可从第 5 节的 hdfs ec 命令与迁移注意事项读起;湖仓场景见第 6 节;第 7 节是一个完整的虚构案例;第 8 节是速查式最佳实践清单;术语看不懂时查文末附录 FAQ。


1 三副本模型:一式三份的合同

HDFS 的默认容错方式是把每个数据块复制三份,官方术语叫 replication,默认副本数 dfs.replication = 3。可以把它想象成签合同要一式三份:原始文件被切成固定大小的数据块(block,默认 128 MB),每一块都在集群中保存 3 份。三副本的本质是用「存储空间」换「容错」和「读性能」:每 1 份数据要花 3 份磁盘,代价是 200% 的额外存储开销。

副本放置遵循机架感知策略:第一份优先放本机(client 本身是 DataNode 时),第二份放另一个机架的节点,第三份放第二个机架内的另一节点——即 02 篇讲的「2 机架 2+1」格局。这样任何一个节点宕机、甚至一个机架整体故障,数据都不会丢——这正是 HDFS 读写流程与副本放置策略 一文详述的机制。

三副本的容错能力是容忍任意 2 个副本同时丢失:3 份中只要还剩 1 份,数据就可读;即使 2 个 DataNode 同时宕机,也能立即用剩下的那份继续服务。这在硬件故障频发的生产环境里是一个非常宽裕的余量。

读路径上三副本还有两个实打实的优势:

优势 说明
读容错 客户端按「最近优先」逐个尝试副本,最近的副本故障会自动切换读下一份,只要 3 份剩 1 份,读就不中断
就近读 客户端总能选「离自己最近」的那份副本(本地盘 > 同机架 > 跨机架),MapReduce 的本地读命中率极高

副本丢失后的重建也极其廉价:从剩余副本直接做一次纯网络拷贝即可,没有任何 CPU 编解码计算,恢复一份数据只传 1 份数据量。

代价同样清晰:1 份逻辑数据 = 3 份物理空间。一个 10 PB 逻辑数据的集群,磁盘要备 30 PB。存储成本随数据量线性膨胀,这是三副本模型唯一的、也是最大的痛点。 而 EC 的卖点一句话就能说清——同样的容错能力,磁盘只要 1.5 倍:

flowchart LR
    A["10 PB 逻辑数据"] --> B["三副本<br/>30 PB 磁盘(3 倍)"]
    A --> C["RS-6-3<br/>15 PB 磁盘(1.5 倍)"]

本节要点:三副本 = 用 200% 的额外空间换「任意丢 2 份不慌」的宽裕容错和就近读性能;痛点只有一个——磁盘成本线性膨胀。记住这个痛点,就能理解 EC 的全部存在价值。


2 纠删码原理:带校验码的拼图

纠删码(Erasure Coding,EC)来自存储行业几十年验证的编码理论,Hadoop 3.0 正式引入(HDFS-7285)。它的思路和副本完全不同:不再整块复制,而是把数据切碎后配上「校验块」,凑齐足够数量的碎片就能拼回原图。

通俗理解:三副本像一式三份合同,纠删码像带校验码的拼图——把一幅画拆成 9 块拼图,其中 6 块是原画碎片、3 块是校验碎片,任取其中 6 块都能拼回整幅画,所以丢 3 块也无所谓。

flowchart LR
    A["原始数据<br/>切成 6 个数据 cell"] --> B["RS 编码<br/>算出 3 个校验 cell"]
    B --> C["9 个 cell 写入<br/>9 个不同 DataNode"]
    C --> D["任意 6 个 cell<br/>即可解码恢复全部"]

具体来说,EC 使用 Reed-Solomon(RS)编码:把数据切成 k 个数据块(官方术语叫 cell),按公式计算出 m 个校验块,构成一个 k+m 的编码组(EC group)。任意取其中 k 个块(不管来自数据块还是校验块),都能通过解方程恢复出全部原始数据——这是 RS 编码作为最大距离可分(MDS)码的数学性质。校验块不是简单复制,而是用伽罗华域(Galois field)上的多项式运算算出来的「数学指纹」,所以它比复制更省空间、容错能力却可设计。

校验块的计算有两种算法:

算法 计算方式 容错能力 适用
Reed-Solomon(RS) 伽罗华域多项式运算 容忍 m 个块丢失(m 个校验块 = m 次容错) 需要强容错的场景
XOR(异或) 纯异或运算,比 RS 快得多 只容忍 1 个块丢失(1 个校验块) 节点少、希望 CPU 开销小的场景

Hadoop 3 内置 5 个 EC 策略,策略名格式为「编码算法-数据块数-校验块数-cell 大小」,例如 RS-6-3-1024k 表示 RS 编码、每组 6 个数据块 + 3 个校验块、cell 大小 1024k(1 MiB):

策略名 组成 存储开销(相对原始数据) 相对三副本节省 容错(可同时丢失) 说明
RS-6-3-1024k 6 数据 + 3 校验 1.5 倍(9/6) 省 50% 空间 3 个 cell 默认启用的唯一策略,最常用
RS-10-4-1024k 10 数据 + 4 校验 1.4 倍(14/10) 省 53% 空间 4 个 cell 开销最低,但需更多节点
RS-3-2-1024k 3 数据 + 2 校验 1.67 倍(5/3) 省 44% 空间 2 个 cell 组更小,适合节点较少的集群
XOR-2-1-1024k 2 数据 + 1 校验 1.5 倍(3/2) 省 50% 空间 1 个 cell 计算最快,容错最弱
RS-LEGACY-6-3-1024k 同 RS-6-3 1.5 倍 省 50% 空间 3 个 cell 纯 Java 实现,仅用于兼容旧 HDFS-RAID 存量数据,不建议新用

以上策略名、参数与开销数值均以 Apache Hadoop 官方文档(HDFSErasureCoding)为准;Hadoop 的实现默认用 Intel ISA-L(Intel 智能存储加速库,用 SIMD 指令加速编解码)原生库加速 RS 编解码计算,缺少该库时回退到纯 Java 实现。

EC 彻底改变了 HDFS 的存储布局,把 block 概念升级为 block group / strip / cell:

  • cell:EC 的最小读写单元,默认 1 MiB(即策略名里的 1024k),读写和编解码都按 cell 粒度进行——不足 1 MiB 的数据也占满整个 cell(末尾条带不足时补零),这正是小文件在 EC 下空间必亏的根源(见第 4 节);
  • strip(条带):编解码的单位,一个条带 = k 个数据 cell + m 个校验 cell(RS-6-3 即 9 个 cell),m 个校验 cell 由同一条带的 k 个数据 cell 算出来,block group 内部就是按条带组织的;
  • block group:EC 文件里的「块」,与三副本的 block 角色对应——逻辑大小默认 128 MB(dfs.block.size),文件按它切分,最后一个 block group 是余数;一个文件由多个 block group 组成,block group 数量 ≈ 文件大小 ÷ 块大小(与三副本模式相同)。一个 128 MB 的 block group 在 RS-6-3-1024k 下约含 22 个条带(128 ÷ 6 向上取整,末尾条带不足时补零),物理落盘约 198 MiB(名义 1.5 倍,因末尾条带取整略高),摊在 9 个节点上;
  • 分布:写文件时 DFSStripedOutputStream 为每个 DataNode 维护一条数据流,一个 block group 的 cell 并行写入多个不同的 DataNode,所以 1 GiB 的文件会被「摊」到很多节点上。

这几个概念的包含关系一张图画清楚:

flowchart TB
    F["文件(300 MB)"]
    F -->|"按 128 MB 切分"| BG1["block group 1(128 MB)"]
    F -->|"按 128 MB 切分"| BG2["block group 2(128 MB)"]
    F -->|"最后一块是余数"| BG3["block group 3(44 MB)"]
    BG1 -->|"128 ÷ 6 向上取整"| ST1["条带 ×22"] --> C1["每条带 9 个 cell<br/>6 数据 + 3 校验(各 1 MiB)"] -->|"并行写入"| DN1["9 个不同 DataNode<br/>每节点 22 个 cell"]
    BG2 -->|"128 ÷ 6 向上取整"| ST2["条带 ×22"] --> C2["每条带 9 个 cell<br/>6 数据 + 3 校验(各 1 MiB)"] -->|"并行写入"| DN2["9 个不同 DataNode<br/>每节点 22 个 cell"]
    BG3 -->|"44 ÷ 6 向上取整"| ST3["条带 ×8"] --> C3["每条带 9 个 cell<br/>6 数据 + 3 校验(各 1 MiB)"] -->|"并行写入"| DN3["9 个不同 DataNode<br/>每节点 8 个 cell"]

一句话记忆:文件按 128 MB 切出 block group,block group 内按条带编解码,一个条带由 9 个 1 MiB cell 组成、并行摊到 9 个节点;三个 block group 各自独立选点,9 个节点的集合可以不同。

容量收益立竿见影:官方文档的例子是 6-block 的文件,三副本占 18 个 block,用 RS-6-3 只占 9 个,空间省一半。代价也不是没有:EC 的容错以 cell 为粒度,一个 DataNode 故障后,NameNode 通过心跳发现丢失的 block group,指派一个 DataNode 上的 ECWorker(DataNode 内置的纠删码重建工作线程)并行读取最少需要的 cell 数量(RS-6-3 需读 6 个 cell),现场做解码再传输到目标节点——重建一份数据要跨网络读 k 个 cell 并消耗 CPU 做编解码,网络放大和计算开销都远大于三副本的「1 份纯拷贝」。官方文档给出的恢复传输权重公式是 max(读流数, 写流数) × 0.5——以 RS-6-3 为例:重建需要 6 个读流、1 个写流,代入得 6 × 0.5 = 3 个传输单元,而副本恢复只占 1 个传输单元,网络开销放大 3 倍。

本节要点:EC 用数学计算换存储空间——同样的容错能力,空间从 3 倍降到 1.4~1.5 倍,代价是读写与重建路径上多出的 CPU 编解码开销。


3 三副本 vs 纠删码:一张表看懂取舍

把两个方案的关键维度并排比较:

维度 三副本 纠删码(以 RS-6-3-1024k 为例)
存储开销 3 倍(多 200%) 1.5 倍(多 50%)
容错能力 容忍 2 份副本丢失 容忍 3 个 cell 丢失(策略 m 值决定)
容错粒度 block(128 MB 级) cell(1 MiB 级)
读容错 最近副本故障自动切换下一份,1 份存活即可读 顺序读并行拉取多个 DataNode 的 cell;单 cell 无冗余,节点故障靠解码还原(组内最多容忍 3 个 cell 丢失)
就近读 总能选最近副本,本地读命中率高 文件分散在多个节点,无「整块就近读」,本地性明显变差
重建成本 1 份纯网络拷贝,无 CPU 计算 需读 k 个 cell + 伽罗华域编解码,CPU 与网络开销均放大
写路径 同一 block 写 3 份到不同节点 cell 并行写多个节点,写时即编码(online EC),无后期转换
小文件适配 好:小文件占 3 个 block 空间,就近读 差:见第 4 节
功能支持 完整(append(追加写)、truncate(截断)、hflush 均支持) 受限:append()(追加写)、truncate()(截断)直接抛异常,hflush/hsync(强制落盘)是空操作
副本数语义 可调(dfs.replication、setrep) EC 文件副本数恒为 1,setrep 无效
适用数据 热数据、小文件、需要随机读/追加写的场景 大文件、冷数据、读多写少的场景

逐条展开要点:容量上 EC 至少省一半空间,这是它存在的全部理由;代价集中在读路径与重建路径——EC 没有「就近副本」可选,读一个小文件也要连多个节点,重建还要烧 CPU。 功能限制同样不能忽视:EC 文件不支持 append 和 truncate,这决定了「边写边追加」的日志类数据绝不能进 EC 目录。

另外注意一个容易踩的坑:EC 的容错是「策略级」的——RS-6-3 容忍 3 个 cell 丢失,但这 3 个 cell 通常分散在不同节点上,所以一个节点宕机只损失该节点上的少数 cell,恰好落在 EC 的容错范围内;三副本则直接把 3 份副本放在 2 个机架上,容错逻辑完全不同。两者都不怕单机故障,但对「同一组内多点故障」的容忍方式不同。

本节要点:选型一句话——热数据、小文件、需要追加写的走三副本;大文件、冷数据、读多写少的走 EC。EC 省空间的代价集中在三处:读路径放大、重建烧 CPU、功能受限。


4 为什么 EC 不适合小文件

官方文档特别提醒:在典型 HDFS 集群里,小文件可能占用总存储的 3/4 以上,而小文件恰恰是 EC 的短板区。原因有三个层面:

第一,cell 粒度导致空间收益消失。EC 按 block group 组织,一个 block group 至少包含一个条带,即 k 个数据 cell + m 个校验 cell(RS-6-3 一条带就是 9 个 1 MiB cell)。一个几 KB 的小文件也要占满一条带的配额——文件远小于一条带时,空间浪费比三副本还严重(EC 至少 9 MiB,三副本只有 3 份几 KB)。三副本下小文件至少还有「3 份冗余、可就近读」的价值,EC 下则两头不占。

第二,读取路径被放大。striping 布局「自然地」把小文件分布到多个 DataNode(这是官方文档的原话)——读一个 1 MiB 的文件,客户端要同时连接多个节点拼出全量数据,每个 cell 只有 1 份、没有就近副本可选,网络往返和连接数都高于三副本。小文件的读取往往是高频操作(元数据扫描、抽样、测试),这种放大很不划算。

第三,功能受限叠加。小文件多的目录常常伴随高频的增删改和追加写,而 EC 文件不支持 append/truncate,把这类目录搬上 EC 等于自断后路。

本节要点:EC 的适用场景是「大文件 + 冷数据」——文件越大,block group 摊薄编码开销的能力越强;访问越冷,读取放大和重建 CPU 的代价越可接受。官方文档给出的准则是:冷数据、大文件用 EC;热数据、小文件、需要追加写的文件保持三副本。


5 应用实践:hdfs ec 命令与目录级策略

EC 的启用粒度是目录:为某个目录设置策略后,该目录下之后新建的文件(含子目录继承)自动按 EC 布局写入;存量文件不受影响,三副本文件也不会被自动转换。官方文档明确说明:-setPolicy 只影响目录下新建的文件,把存量数据迁到 EC 目录需要重新复制。另外注意,除了默认启用的 RS-6-3-1024k,其他内置策略要先 -enablePolicy 才能使用,而三副本(REPLICATION)作为永启方案可以和 EC 在集群内共存。

以下是核心命令(完整参数以 Apache Hadoop 官方文档为准):

# 查看内置策略及启用状态(默认只有 RS-6-3-1024k 是 Enabled)
hdfs ec -listPolicies

# 启用非默认策略,例如 RS-10-4-1024k
hdfs ec -enablePolicy -policy RS-10-4-1024k

# 为目录设置 EC 策略:只影响之后新建的文件
hdfs ec -setPolicy -path /data/cold -policy RS-6-3-1024k

# 查看某个目录当前生效的策略(可能继承自父目录)
hdfs ec -getPolicy -path /data/cold

# 取消目录上的显式策略,恢复继承父目录策略
hdfs ec -unsetPolicy -path /data/cold

# 迁移前检查集群能否支撑要启用的策略(节点数、机架数)
hdfs ec -verifyClusterSetup -policy RS-6-3-1024k

命令背后的逻辑:-setPolicy 的 -policy 参数与 -replicate 参数不能同时使用,-replicate 表示强制该目录新文件使用三副本(用于从 EC 目录切回副本);-unsetPolicy 对「纯继承」的目录是空操作,只有显式设置过策略的目录才需要 unset。一条实用经验:先用 -getPolicy 确认策略真实生效,再开始搬数据,不要凭目录名猜。

集群前置条件同样重要,官方文档给出明确数值:

纠删码要求集群 DataNode 数至少等于编码组宽度(k+m)——RS-6-3 至少 9 个 DataNode,RS-10-4 至少 14 个;机架数最少 (k+m)/m 向上取整(RS-6-3 为 3 个机架),要完整保住机架级容错,RS-6-3 理想情况下需要 9 个以上机架。 节点或机架不足时策略可以启用,但容错能力会打折扣,-verifyClusterSetup 就是干这个检查的。

EC 与副本共存是常态,目录树天然分层:/data/hot 用三副本、/data/cold 用 RS-6-3,子目录可以再覆盖父目录策略。迁移存量数据的标准流程是「复制式迁移」:

# 1) 前置检查:集群节点数、机架数是否满足策略要求
hdfs ec -verifyClusterSetup -policy RS-6-3-1024k

# 2) 建新目录并设置 EC 策略
hdfs dfs -mkdir -p /data/cold-ec
hdfs ec -setPolicy -path /data/cold-ec -policy RS-6-3-1024k

# 3) 用 distcp(Hadoop 自带的分布式复制工具)把存量数据复制进 EC 目录,
#    相当于以 EC 布局重写一遍数据
hdfs distcp -update /data/cold /data/cold-ec

# 4) 验证:目录策略生效 + 文件已按 block group 布局存储
hdfs ec -getPolicy -path /data/cold-ec
hdfs fsck /data/cold-ec -files -blocks

# 5) 核对无误后,再删除旧目录释放空间
hdfs dfs -rm -r /data/cold

迁移有四个必须提前规划的注意事项:

  1. 存量不自动转:-setPolicy 之后旧文件还是三副本,必须靠上面的复制流程重写;复制期间新旧两份同时占用空间,要预留足够磁盘(旧 3 倍 + 新 1.5 倍同时存在)。
  2. 带宽与 CPU 预算:distcp 重写和 ECWorker 后台重建都会占网络与 CPU,官方文档明确说编解码「消耗客户端和 DataNode 的额外 CPU」——迁移窗口避开业务高峰,必要时限速。
  3. 先小范围试点:先迁一个小分区目录验证读性能与容量收益,再铺开到全部冷数据。
  4. 验证闭环:迁移后用 -getPolicy 确认策略、fsck 确认 block group 健康、hdfs dfs -du 对比前后空间占用,三件事缺一不可。

本节要点:EC 的落地方式就是「目录级策略 + 复制式迁移」——策略只作用于新文件,存量数据必须重写;动手前用 -verifyClusterSetup 确认集群规模,动手后逐目录验证。


6 与数据湖场景的结合:湖仓底座上的冷数据

湖仓一体(数据湖与数据仓库融合的架构)架构中,HDFS 几乎就是默认的存储底座:Iceberg 表的数据文件(Parquet/ORC)、历史分区、快照和审计日志全部落在 HDFS 上。这类数据的典型特征是总量大、按时间分区、越老的分区访问频率越低——历史月份的分区可能几个月都不会被查询一次,却占着三副本的 3 倍物理空间。这正是纠删码定义的完美场景:大文件(Parquet/ORC 文件动辄上百 MB 到 GB 级)+ 冷数据(低频读 + 不追加写),EC 的容量收益被充分放大、读取与重建代价被充分摊薄。详见同系列 HDFS 数据湖存储底座(与 Iceberg 的关系),以及 Apache Iceberg 表格式深度解析 中关于数据文件组织方式的背景。

结合前面几节的机制,落地路径非常清晰:按 Iceberg 的分区路径(如 table/dt=2025-01-01/)组织目录,对超过 N 天(如 90 天)的历史分区目录统一 -setPolicy 启用 RS-6-3,新数据照常写入热分区(三副本),冷热分层与目录策略天然一一对应,不需要额外的数据搬迁组件——老分区变冷后,只需在迁移窗口用 distcp 重写一次。

对 Vertica 用户还有一个相关提醒:Vertica Eon 模式的 communal storage 可以构建在 HDFS 上,公共存储里同样躺着大量历史数据,容量规划与备份策略见 Vertica Eon Communal Storage 运维实战 与 使用vbr备份Vertica Eon on HDFS数据库。但要注意:Eon 公共存储的文件由数据库自行管理,HDFS 侧无法辨识冷热——目录结构与文件命名是 Vertica 内部实现,「按未访问天数挑目录再 -setPolicy」的套路在这里行不通,EC 策略变更须先过 Vertica 官方支持矩阵(见 FAQ Q8)。「冷数据 EC 化」只适用于你自管的数据目录;Eon 公共存储的成本治理,走 Vertica 自身的路径。

本节要点:湖仓底座 = 大文件 + 冷热分层,是 EC 在 HDFS 上最典型的应用场景;目录策略与分区路径对齐后,冷数据 EC 化几乎是无痛收益。


7 虚构案例:某数仓集群的冷数据 EC 迁移

📝 虚构案例(数据与数字为演示用途,用于串联前文知识点)

某数仓集群的 HDFS 底座面临磁盘告急:逻辑数据量 2.4 PB,三副本占用 7.2 PB 物理空间(集群总容量 9.6 PB,使用率 75%),扩容采购周期长。统计访问日志后发现,超过 90 天未访问的冷数据约 1.6 PB(占 67%),集中在按天分区的历史表上;热数据 0.8 PB。集群共 12 个 DataNode、4 个机架,满足 RS-6-3 的最小节点数(9)与最小机架数(3)要求——机架级容错按官方公式成立,但未达第 5 节所说「理想情况下 9 个以上机架」,应对多机架同时故障的余量有限,是本案接受的取舍。

决策与实施分四步:

第一步:冷热目录拆分。 先确认历史分区的数据文件以百 MB 级 Parquet/ORC 为主——大文件是 EC 收益的前提(见第 4 节);然后建 /warehouse/cold-ec 目录并启用策略,把历史分区路径规划到该目录下:

hdfs ec -verifyClusterSetup -policy RS-6-3-1024k   # 节点/机架检查通过
hdfs dfs -mkdir -p /warehouse/cold-ec
hdfs ec -setPolicy -path /warehouse/cold-ec -policy RS-6-3-1024k

第二步:分批迁移。 按表、按月份分批执行 distcp 重写,每批 0.4 PB 冷数据,采用「迁一批、验一批、删一批」的流水方式——每批复制完成并验证后立即删除对应旧目录。这样迁移峰值占用 = 热数据 2.4 PB + 尚未删除的旧冷数据 + 当批新增的 EC 副本 ≈ 7.8 PB(81%),不会触顶 9.6 PB 的总容量;若一次性全量重写再统一删除,峰值会达到 9.6 PB,直接撞上容量天花板。

第三步:逐目录验证。 每批迁移后用 -getPolicy 确认策略生效、fsck 确认 block group 健康、du 对比空间占用,再删除旧目录。

第四步:效果核算。 冷数据 1.6 PB 从三副本(占 4.8 PB)变为 RS-6-3(1.6 × 1.5 = 2.4 PB),热数据保持 0.8 × 3 = 2.4 PB,全集群物理占用从 7.2 PB 降到 4.8 PB,使用率从 75% 降到 50%——容量节省 33%(2.4/7.2),相当于同样的磁盘可以多容纳 50% 的逻辑数据(7.2/4.8 = 1.5),磁盘告急解除,扩容采购推迟至少一年。

案例中的两个权衡点值得一提:迁移与后台 ECWorker 重建都消耗 CPU 和网络,安排在业务低峰执行,避免与批处理撞车;冷数据查询延迟略有上升(读取要跨节点拼 cell),但对 >90 天未访问的数据而言无感。这个案例说明:冷数据占比越高、文件越大,EC 迁移的 ROI(投资回报率)越高——节省的正是磁盘扩容的钱。


8 最佳实践清单

  1. 大文件 + 冷数据用 EC,小文件 + 热数据用三副本。 为什么:EC 的容量收益依赖 block group 摊薄开销,读取放大对高频访问不划算;两个维度同时满足才进 EC。
  2. 按目录树做冷热分层,策略与分区路径对齐。 为什么:策略沿目录继承、子目录可覆盖,把「数据变冷」映射成「目录迁移」是最简单的运维模型。
  3. 非默认策略先 -enablePolicy,默认只有 RS-6-3-1024k 是启用的。 为什么:未启用策略不能用于 -setPolicy,报错后容易误判为权限问题。
  4. 迁移前跑 hdfs ec -verifyClusterSetup。 为什么:RS-6-3 至少 9 个 DataNode、3 个机架,RS-10-4 至少 14 个节点——规模不够时容错能力名不副实,不如不迁。
  5. 存量数据不自动转换,必须复制式迁移(distcp)并预留新旧两份磁盘空间。 为什么:-setPolicy 只影响新建文件,不重写就永远迁不完;空间预留不足会导致迁移中途失败。
  6. 小文件目录、需要 append/truncate 的文件,一律不进 EC 目录。 为什么:EC 文件不支持追加与截断,hflush/hsync 是空操作,功能损失无法事后补救。
  7. 迁移与重建避开业务高峰,预留 CPU 和网络预算。 为什么:EC 重建要读 k 个 cell 并做编解码,官方明确其 CPU 消耗高于副本拷贝;重建网络传输权重约为副本的数倍(RS-6-3:6 读流 × 0.5 = 3 个传输单元,副本只需 1 个)。
  8. 每批迁移后三层验证:-getPolicy 看策略、fsck 看 block group 健康、du 看空间收益。 为什么:策略可能被继承关系覆盖、block group 可能在迁移中受损,只有三层都通过才允许删旧数据。
  9. 别对 EC 文件调副本:其副本数恒为 1,setrep 无效。 为什么:排障时给 EC 文件加副本是无效操作,应该调整的是策略或重建机制(ECWorker),方向错了浪费时间。
  10. EC 与副本可以长期共存,REPLICATION 策略永远可用。 为什么:目录级策略让两者各司其职,不必追求「全库 EC」——热数据保留副本的读性能红利,冷数据享受 EC 的容量红利,各取所长。

附录:新手常见疑问(FAQ)

Q1:纠删码和 RAID5/RAID6 是什么关系? 同源思想:RAID 在单机磁盘阵列上做「条带 + 校验」,纠删码是把同一套数学搬到集群节点层面——RS-6-3 的一个编码组(6 数据 + 3 校验)就相当于一个跨 9 个节点的「超级 RAID6」,容错还更强。区别是 HDFS EC 以 cell(1 MiB)为粒度、以目录为启用单位,是分布式文件系统的原生实现。

Q2:为什么默认只启用 RS-6-3-1024k 一个策略? 它是官方权衡后的最稳选择:空间 1.5 倍(省 50%)、容 3 个 cell 丢失、门槛适中(9 节点 3 机架)。更省的 RS-10-4 需要 14 个节点,小集群用不了;XOR 容错只有 1 个 cell,太弱。其余策略要 -enablePolicy 显式开启,本质上是让你「先确认集群规模扛得住再开」。

Q3:多小的文件不适合 EC? 没有官方硬阈值,判断标准是「能否摊薄一个编码组的固定开销」:RS-6-3 一组至少 6 个数据 cell(6 MiB),文件远小于这个量级时空间必亏(第 4 节)。工程经验:百 MB 以上的大文件才进 EC;配合 HDFS 小文件问题与治理 的判定口径(平均文件 < 10MB 就该治理),小文件目录本身就该先合并、再谈存储策略。

Q4:EC 的读性能损失到底有多大? 分场景:顺序读大文件损失很小——客户端并行拉多个 DataNode 的 cell,聚合带宽甚至不输三副本;随机读、小文件读放大明显——每个 cell 只有 1 份、没有就近副本,要连多个节点拼数据。所以 EC 适合「低频访问的冷数据」,热数据别省这个钱。

Q5:节点数不够 k+m 时,能启用 EC 策略吗? 命令能执行,但容错名不副实:节点不足时编码组的 cell 被迫挤在少数节点上,一个节点故障可能同时带走超过 m 个 cell,数据就丢了。hdfs ec -verifyClusterSetup 就是干这个检查的——它报不通过就别迁。

Q6:迁移后怎么确认新旧数据一致? 按第 5 节的「三层验证」执行:-getPolicy 确认策略生效、fsck 确认 block group 健康、du 对比空间收益;更严格可以抽验 checksum(校验和)或抽样读回对比。核心原则只有一条:验证全通过之前,绝不删除旧目录。

Q7:EC 目录还能改回三副本吗? 能,方向可逆:-setPolicy -replicate 强制新文件走三副本(或 -unsetPolicy 恢复继承),存量数据再 distcp 重写一遍即可。成本 = 又一次重写 + 磁盘回涨到 3 倍,所以迁移前想清楚「这份数据是不是长期冷」。

Q8:Vertica Eon 公共存储目录能不能上 EC? 理论上 EC 对上层应用透明(读接口兼容),但 Vertica Eon 的公共存储目录是数据库自己管理的,策略变更必须先过 Vertica 官方支持矩阵,未经验证不要在生产直接改;Eon 公共存储的成本治理思路见 Vertica Eon Communal Storage 运维实战。

扩展阅读