最佳实践 · 大数据运维

待环境验证

Hadoop 小文件治理与数据一致性验收

从文件增长来源、元数据与查询成本选择合并或归档方案,在独立候选目录验证语义、性能和发布回退条件。

Hadoop大数据
阅读导引 · 理解后再操作

这篇知识解决什么问题

本篇从文件增长来源和可测量的元数据、查询成本判断小文件问题,选择源头控制、格式感知重写或归档。治理结果既要减少目标成本,也要保持记录语义、分区契约及可解释的发布与回退路径。

先治理新增来源再处理存量

过细分区、短批次和重复输出会持续制造文件。将文件创建趋势与上游任务关联后再安排历史治理,才能避免合并任务长期追赶相同来源。

合并按记录语义验收

结构化文件重写可能改变压缩和二进制布局,文件摘要不适合直接作为内容相等的唯一标准。应检查记录、重复键、空值与业务汇总,再对比文件分布与查询成本。

进入文章正文
关联架构图解8 个组件 · 点击展开

通过 Hadoop 运维图理解文件数量对 NameNode 与计算读取链路的不同影响。候选重写目录、目录注册与消费方发布没有被图完整展开,需要按实际表格式补充,不能把文件系统更名当作跨系统原子发布。

查看场景架构与实施步骤
参考架构 · 非实时拓扑

HDFS 存储与 YARN 计算的双层架构

把 HDFS 元数据、数据块与 YARN 资源调度分开阅读:客户端直接读写 DataNode,作业由 ApplicationMaster 协调执行;维护需要同时满足数据副本和队列容量条件。

  • 数据 / 请求
  • 控制 / 管理
  • 观测 / 查询

点击组件,在图下方查看职责;连线编号对应流向解读。小屏可横向滚动,或直接展开文字说明。

HDFS 存储与 YARN 计算的双层架构:组件关系图把 HDFS 元数据、数据块与 YARN 资源调度分开阅读:客户端直接读写 DataNode,作业由 ApplicationMaster 协调执行;维护需要同时满足数据副本和队列容量条件。 作业与数据客户端 → NameNode:查询元数据;作业与数据客户端 → DataNode 组:直接读写数据块;NameNode → DataNode 组:块管理指令;作业与数据客户端 → ResourceManager:提交应用;ResourceManager → ApplicationMaster:分配容器资源;ApplicationMaster → NodeManager 组:协调任务执行;Prometheus → NameNode:采集存储状态;Prometheus → ResourceManager:采集队列状态;Grafana → Prometheus:查询趋势。箭头说明见下方流向解读。
逻辑参考图,只展开现有集群的核心职责;主备、JournalNode、机架与副本实例未全部展开,不代表真实部署或维护已验证。

NameNode

控制 / 治理

表示当前有效的 HDFS 元数据入口;实际主备和 JournalNode 健康必须核对。SecondaryNameNode 不能被当作热备。

查看关联工具
全部组件职责 8 个组件
NameNode
表示当前有效的 HDFS 元数据入口;实际主备和 JournalNode 健康必须核对。SecondaryNameNode 不能被当作热备。工具介绍 NameNode
DataNode 组
保存数据块并服务客户端读写,副本和机架放置需按真实拓扑核对;节点退出前评估剩余可用副本。工具介绍 DataNode 组
作业与数据客户端
客户端查询 HDFS 元数据后直接访问 DataNode;YARN 应用提交走独立计算控制路径,不把所有流量都画成经过 NameNode。
ResourceManager
管理计算资源与队列分配;排队还可能受用户配额和请求规格影响,不能仅用总体 CPU 判断。工具介绍 ResourceManager
ApplicationMaster
为本应用申请资源、跟踪任务,并与 NodeManager 协调容器执行;任务管理不由全局调度器单独承担。
Grafana
将主备、容量、块健康和排队原因关联到同一时间范围,给值班人员保留原生命令核对入口。工具介绍 Grafana
Prometheus
通过已验证的指标适配端点采集控制面、存储、计算和关键作业信号;图中仅展示核心入口观测。工具介绍 Prometheus
NodeManager 组
在计算节点管理任务容器及资源状态,维护前应按所选版本流程排空或退出调度,不能只停止进程。工具介绍 NodeManager 组
流向解读 9 条连接
  1. 1

    作业与数据客户端 NameNode

    控制 / 管理 · 查询元数据

    客户端请求文件与块位置元数据,业务数据块本身不流经 NameNode。

  2. 2

    作业与数据客户端 DataNode 组

    数据 / 请求 · 直接读写数据块

    客户端根据元数据访问 DataNode;图中聚合多个数据节点,未展开具体写入复制管线。

  3. 3

    NameNode DataNode 组

    控制 / 管理 · 块管理指令

    NameNode 管理块放置与复制,DataNode 心跳、块报告等返回关系在此简化省略。

  4. 4

    作业与数据客户端 ResourceManager

    控制 / 管理 · 提交应用

    作业提交进入 YARN 控制路径,需核对队列、配额、资源请求和业务窗口。

  5. 5

    ResourceManager ApplicationMaster

    控制 / 管理 · 分配容器资源

    ApplicationMaster 请求资源后由 ResourceManager 返回分配结果,本连线强调调度职责。

  6. 6

    ApplicationMaster NodeManager 组

    控制 / 管理 · 协调任务执行

    ApplicationMaster 与获分配节点的 NodeManager 协调启动及监控任务容器。

  7. 7

    Prometheus NameNode

    观测 / 查询 · 采集存储状态

    通过实际启用的端点或适配器观测角色、容量和块健康,并与原生命令抽样比对。

  8. 8

    Prometheus ResourceManager

    观测 / 查询 · 采集队列状态

    观测队列和应用状态,采集失败与真实资源不足分别呈现。

  9. 9

    Grafana Prometheus

    观测 / 查询 · 查询趋势

    查询存储与计算侧同时间段趋势,为单节点维护提供可复核证据。

故障域与操作边界

一个物理节点可能同时影响两层

DataNode 与 NodeManager 共置时,退出节点会同时减少存储副本与计算容量;不能只看磁盘健康或只看队列资源。

核心角色不明时停止维护

图中未展开的主备、JournalNode 和机架关系仍是前置条件。同故障域不可并行维护,副本或调度不满足时不能强制退出。

副本和快照不是独立备份

数据删除、逻辑损坏与整个故障域受损需要独立恢复路径;全量 fsck、均衡和退役还需另行评估负载。

架构依据与版本核对 2 篇官方资料

图解是本站基于官方资料整理的逻辑参考;实施前仍需核对实际部署版本、组件支持范围与变更审批。

适用范围与问题定义

本文以 Hadoop 3.4.1 的 HDFS 为基础,讨论数仓、日志落地与批处理中的小文件治理;使用 Spark 重写数据时,示例语义限定 Spark 3.5.7。Hive 事务表、Iceberg、Hudi、Delta 等表格式必须使用各自支持的维护机制,不能直接替换底层文件。文中没有执行集群扫描或合并,状态保持 PENDING。

“小”没有适用于所有业务的固定字节线:重点是文件数量、单位扫描数据的打开成本、计算任务开销,以及 NameNode 元数据压力。应同时统计分区增长与查询模式。一个很少被读取的归档目录,与每天被大量查询的热分区,即使文件数相同,也可能需要不同方案。

为什么磁盘有空闲仍会慢

HDFS 在 NameNode 内存中维护文件、目录与块映射;大量小文件增加命名空间对象和元数据操作量。读取一批文件还会产生目录发现、文件打开与计算调度开销。因此,问题不只是“每个小文件浪费完整块大小的磁盘”,也不能以总字节数推算 NameNode 负载。机制背景见 HDFS 架构

治理应分别观测存储层和引擎层。NameNode RPC、堆内存与垃圾回收反映元数据压力,SQL 的文件发现时间、扫描文件数、任务时长分布反映查询成本。若瓶颈是单个热点关联键,文件合并未必能改善,应避免把所有作业慢都归因于小文件。

先确定一个可比较的采样分区

选择一份已经停止写入、归属明确且规模已知的日分区。避免从根目录做递归列表,也不要把 head 接在全量递归输出后就宣称扫描已被限制。以下命令只覆盖经确认的小范围样本:

hdfs dfs -count -q 'hdfs://REPLACE_WITH_NAMESERVICE/REPLACE_WITH_CLOSED_PARTITION'
hdfs dfs -du -s 'hdfs://REPLACE_WITH_NAMESERVICE/REPLACE_WITH_CLOSED_PARTITION'
hdfs dfs -stat '%b %n' 'hdfs://REPLACE_WITH_NAMESERVICE/REPLACE_WITH_ONE_FILE'

count -q 提供配额及目录、文件、内容大小信息;du -s 要区分逻辑大小与含冗余的存储消耗,不能混用。平均文件大小可由逻辑字节数除以文件数估算,但平均值不能替代文件大小分布,混入隐藏标记文件也可能改变解释。对较大分区优先使用已有清单与监控,扫描成本超出预算就停止。命令定义见 文件系统 Shell

从生产链路定位持续增长来源

把文件创建时间与上游批次、分区数、写入并行度和失败重试关联。常见来源包括过细的时间分区、每个业务实体独立建目录、短触发间隔、每个任务都写一个很小结果,以及重试后遗留多个输出批次。先找到“谁持续制造文件”,再安排历史治理,否则合并任务会变成永远追赶的后台负载。

区分正常数据文件、临时输出和废弃分区,并让数据负责人确认它们的语义。临时文件可能仍被运行中的提交协议使用;名称看起来像临时目录不构成删除依据。若同分区还有迟到数据写入,应先设计不可变批次、维护锁或受支持的事务机制,而不是直接冻结未知上游。

在合并、归档和源头控制之间选择

  • 调整写入批次与分区策略:更适合的目标:减少新增小文件;需要先确认的边界:延迟、迟到数据、资源与下游契约。
  • 用格式感知引擎重写:更适合的目标:经常查询的结构化分区;需要先确认的边界:schema、压缩、记录语义与发布原子性。
  • Hadoop Archive:更适合的目标:少变更且仍需按文件路径访问的归档;需要先确认的边界:HAR 访问支持、不可变语义、恢复路径。
  • 生命周期清理:更适合的目标:已超过保留期限的数据;需要先确认的边界:归属、快照、法律与业务保留要求。

HAR 归档本身不会删除原始输入,并且归档不可变;只创建 archive 不会自动释放原始命名空间。是否支持 HAR URI 还取决于读取应用。文件从加密区进入非加密区的归档会改变保护边界,目标位置需要一并核对。依据 Hadoop Archives Guide

用独立候选目录重写有界样本

以下是供受控演练使用的 Spark 3.5.7 片段:输入必须是一份已关闭且 schema 已确认的 Parquet 样本,目标必须是尚不存在的候选目录,不指向生产表路径。

source = "hdfs://REPLACE_WITH_NAMESERVICE/REPLACE_WITH_CLOSED_PARQUET_SAMPLE"
candidate = "hdfs://REPLACE_WITH_NAMESERVICE/REPLACE_WITH_NEW_CANDIDATE_PATH"
df = spark.read.parquet(source)
df.repartition(8).write.mode("errorifexists").parquet(candidate)

8 只是演练中的计划并行度,不是推荐的生产参数,也不保证所有情形下恰好生成八个数据文件。空分区、按列分区和写入配置都会影响输出。repartition 带来数据重分布成本,应该用样本字节量、任务耗时和目标文件分布调整。候选结果验收前保持独立;本示例不执行发布或删除。Parquet 支持与读写行为见 Spark 3.5.7 Parquet 文档

验证语义比文件数下降更重要

比较同一不可变输入窗口下的记录数、主键重复、空值分布、关键金额汇总、最早与最晚业务时间,并按业务精度处理浮点汇总误差。对于允许重复的数据,不能仅以去重后记录数相同判为一致;对于分区目录,还要验证分区列推断与目录注册是否保持一致。

再比较文件数量与分布、相同查询的扫描量、运行时间、Shuffle 和失败率。测试需固定数据、SQL 与资源窗口,冷缓存和热缓存分开记录。压缩与布局变化后逻辑行内容可能相同而文件二进制摘要不同,不能强求输出文件摘要等于输入文件摘要。

常见误区与不适用操作

不要用字节拼接合并 Parquet 或 ORC 等带结构元数据的文件。getmerge 的输出是本地文件,它既不是 HDFS 原地合并,也不会自动维护表格式结构。不要为了追求一个文件普遍使用 coalesce(1),单任务瓶颈和重试成本可能抵消收益。

也不要直接移动或覆盖事务表的文件来绕过引擎维护接口。普通文件系统的路径更名与目录系统、查询缓存、在途读取之间并不是一个跨系统事务,发布需要对应表或平台的受支持流程。若治理同时牵涉 DataNode 容量,可以联合 HDFS 容量与副本健康巡检 判断是否有足够双份数据空间。

验收、发布与回退边界

验收包应包含输入快照或不可变清单、候选目录、写入版本、语义比对、性能对照及目标空间预算。先让少量代表性查询读取候选数据,再按数据平台的发布机制切换入口。若持续写入无法隔离、结果不一致或候选负载影响在线作业,停止扩面并保留原输入。

候选未发布时可以放弃本次候选版本,清理由生命周期流程处理;入口切换后但没有新增写入时,可依据已验证机制返回旧版本。新入口已经接收新数据后,不能简单改回旧目录,否则会遗漏新增记录;应先厘清增量并制定重放方案。原数据删除后,回退依赖快照或备份,恢复计划见 Hadoop 高可用与恢复规划

参考资料

从现象到判断

先收集证据,再缩小范围。以下是判读路径,不代表已经确认根因或获准变更。

  1. 集群磁盘仍有空闲,但目录发现和短任务调度耗时不断上升。

    只读核对
    在已关闭的小范围分区比较文件数、逻辑字节、文件分布与同窗 NameNode 指标。
    如何判读
    平均文件大小与元数据成本有解释价值,但不能由磁盘余量排除小文件压力。
  2. 每日合并成功后文件数量很快回升,同一分区还有迟到批次写入。

    只读核对
    关联上游触发间隔、并行度、目录策略和失败重试,确认分区何时真正关闭。
    如何判读
    持续增长来自写入契约时,单次历史合并无法解决;并发维护还可能遗漏新增文件。
  3. 候选输出文件明显减少,但查询结果记录数或关键金额发生变化。

    只读核对
    对比不可变输入窗口、schema、分区列、重复记录与空值处理,先暂停发布。
    如何判读
    文件数减少不能替代内容正确;只有解释语义差异后才能评价性能收益。
常见误区与判断边界 2 项

用字节拼接处理列式文件

Parquet 等文件带有结构元数据,需要格式感知读取和写入。getmerge 生成本地拼接文件,不能作为 HDFS 原地维护或事务表维护方法。

认为创建 HAR 就释放了源文件

HAR 创建不会自动删除原输入,而且归档不可变。访问支持、目标加密边界、源保留和恢复方式都需要分别验收,不能靠归档任务成功直接清理生产源。

交接时应留下的证据

作为记录提纲使用,不是自动检查结果;未取得的证据应标记缺口,并注明负责人。

  • 记录已关闭的输入分区、负责人、采样预算和基准文件清单,注明迟到写入是否已经排除。
  • 保留新增文件来源、逻辑与物理容量、文件分布及元数据与查询开销证据。
  • 保存独立候选路径、引擎版本、schema 和业务一致性结果,再记录同条件性能对照。
  • 交接入口发布机制、原输入保留窗口、双份空间预算和新写入后的增量回放边界。

记录需包含环境、版本、时间与时区;分享前脱敏,不附访问令牌、密码或完整业务敏感数据。

继续阅读与资料核对

补充相关主题,再结合当前环境的实施记录形成结论。

返回原理导读

DOUYA OPS ECOSYSTEM

贡献你的经验,帮助更多运维人

把故障复盘、标准流程和最佳实践沉淀为可检索、可复用的知识内容。