1. 项目概述:HDFS扩容与缩容不是“加磁盘”或“删节点”那么简单
Hadoop优化里,HDFS扩容和缩容是运维同学最常被叫去“救火”的场景之一——业务部门一句“存储快满了”,DBA立刻开始查DataNode日志;新集群上线前,架构组又反复讨论“要不要预留20%节点冗余”。但真实情况是:HDFS的扩缩容从来不是单纯增减物理节点或挂载新磁盘,而是一场涉及数据均衡、块副本调度、NameNode压力、客户端兼容性、服务可用性边界的系统性工程。我做过7个中大型Hadoop集群的生命周期管理,从50节点到2000+节点规模,踩过所有你能想到的坑:扩容后集群吞吐反降30%,缩容时卡在Decommissioning状态超48小时,甚至出现副本数不足导致MapReduce任务集体失败。这些都不是配置写错的问题,而是对HDFS底层机制理解偏差带来的连锁反应。本文聚焦“hadoop 优化之hdfs扩容和缩容”这个标题,不讲泛泛而谈的命令列表,而是拆解为什么扩容要先调dfs.datanode.max.transfer.threads,为什么缩容必须等UnderReplicatedBlocks归零才安全,为什么balancer跑三天可能白干,以及如何用mover工具替代传统均衡策略。适合正在维护生产集群的运维工程师、准备面试大数据岗位的候选人,以及需要为HDFS资源规划提供技术依据的架构师。如果你只打算复制粘贴几条hdfs dfsadmin命令就去操作,建议先读完第4节“常见问题与排查技巧实录”——那里记录了我亲手复现并定位的12个典型故障现场。
2. HDFS扩缩容的本质:不是节点增减,而是数据拓扑重构
2.1 扩容≠加机器,缩容≠删节点:HDFS的数据视角
很多人把HDFS扩容理解成“往集群里加新DataNode”,缩容理解成“把旧DataNode下线”,这是最危险的认知偏差。HDFS的存储能力不取决于节点数量,而取决于有效数据块(Block)的分布密度与副本冗余度。举个生活化类比:一个图书馆(HDFS集群)的藏书容量,不取决于新增了几间阅览室(DataNode),而取决于新书(数据块)是否被合理分发到各楼层书架(磁盘),且每本书是否按规则备有3份副本(默认replication=3)。如果新添的阅览室空着,或者新书全堆在一层,而二层书架已满,那整个图书馆的实际承载力反而下降——这正是扩容后性能不升反降的根本原因。
从NameNode视角看,每个DataNode注册时上报的是本机所有磁盘的总容量、已用空间、剩余空间、块报告(BlockReport)。NameNode据此构建全局块映射表(BlocksMap)和节点心跳状态。当新增DataNode时,NameNode只是多了一个“可存放块”的候选者;当删除DataNode时,NameNode只是标记该节点“不可再分配新块”。但已有数据块的物理位置不会自动迁移——这就是为什么扩容后数据仍集中在老节点,新节点长期空转;缩容时老节点上的块也不会自动复制到其他节点,除非触发副本修复机制。
因此,真正的扩容操作包含三个不可分割的阶段:
- 接入阶段:新DataNode完成配置、启动、向NameNode注册,进入
In Service状态; - 填充阶段:通过
balancer或mover将现有数据块按策略迁移到新节点,提升其存储利用率; - 均衡阶段:调整块分布,使各节点磁盘使用率标准差≤5%,避免热点节点拖累整体IO。
缩容同理,必须经历:
- 标记阶段:执行
hdfs dfsadmin -refreshNodes,将目标节点加入excludes文件,状态变为Decommission In Progress; - 迁移阶段:NameNode主动将该节点上所有块的副本,重新复制到其他存活节点,确保每个块维持
dfs.replication指定的副本数; - 清理阶段:当该节点上所有块副本均被成功迁移,且
UnderReplicatedBlocks=0、CorruptBlocks=0时,状态变为Decommissioned,方可安全停机。
提示:
Decommission In Progress状态持续时间,直接取决于该节点当前存储的数据量、网络带宽、其他节点剩余空间及dfs.namenode.replication.min参数设置。我曾处理过一个节点存有12TB数据、集群平均带宽仅80MB/s的案例,理论迁移时间=12×1024÷80÷3600≈4.3小时,但实际耗时17小时——因为NameNode同时要处理客户端读写请求,副本复制被动态限速。
2.2 NameNode的“大脑负担”:扩容缩容如何影响元数据服务
NameNode是HDFS的“中央大脑”,它不存数据,只存元数据:文件路径、权限、块ID列表、每个块存于哪些DataNode。一次典型的扩容操作,会触发NameNode三类高开销行为:
- 块报告(BlockReport)激增:每个DataNode每6小时向NameNode发送一次完整块列表。新增N个节点,意味着NameNode每轮需处理N倍的块ID解析与索引更新。若单节点平均存有50万个块,新增10节点即增加500万次块ID校验。
- 心跳处理压力上升:DataNode每3秒发送一次心跳,携带磁盘使用率、存活状态等。扩容后心跳总量线性增长,NameNode的RPC Handler线程池可能成为瓶颈。
- 编辑日志(EditLog)写入加速:每次块迁移、副本创建、节点状态变更都会生成EditLog条目。缩容过程中,单节点迁移10万个块,将产生10万条EditLog,显著加快EditLog滚动频率,增加SecondaryNameNode合并压力。
这就解释了为什么扩容后NameNode GC时间变长、WebUI响应延迟升高——不是CPU不够,而是元数据操作并发量陡增。我们曾在线上集群观察到:当DataNode从120台扩至150台后,NameNode Full GC频率从每天2次升至每小时1次,根本原因是EditLog写入速率从12MB/min飙升至45MB/min,触发JVM频繁回收大对象。
解决方案不是盲目堆内存,而是前置优化NameNode参数:
dfs.namenode.handler.count:默认10,建议按max(20, 2×log₂(集群节点数))设置。150节点集群应设为26;dfs.namenode.avoid.stale.datanode:启用后NameNode会过滤掉心跳超时的节点,减少无效计算,建议设为true;dfs.namenode.replication.interval:块副本检查间隔,默认3秒,高负载集群可调至5秒,降低NameNode计算压力。
注意:修改上述参数必须重启NameNode,且需提前在
hdfs-site.xml中配置dfs.namenode.edits.dir指向高IOPS磁盘(如NVMe SSD),否则EditLog写入将成为新的性能瓶颈。我见过因EditLog目录挂在普通SATA盘上,导致扩容后NameNode持续超时的事故。
2.3 DataNode的“肌肉负荷”:数据迁移对IO与网络的真实冲击
DataNode是HDFS的“四肢”,负责数据读写与块传输。扩容后的balancer、缩容时的副本复制,本质都是DataNode间的P2P数据搬运。这种搬运对资源的消耗远超想象:
- 磁盘IO:每个块迁移需读取源节点磁盘+写入目标节点磁盘。假设块大小128MB,单次迁移产生256MB磁盘IO。1000个块即256GB IO,足以让一块7200转SATA盘持续满载。
- 网络带宽:块数据通过DataNode间TCP连接传输,默认使用
dfs.datanode.address端口(50010)。若集群未启用Rack Awareness,数据可能跨机架传输,消耗核心交换机带宽。 - CPU与内存:块校验(CRC32)、压缩/解压缩(若启用
dfs.client.read.shortcircuit)、TLS加密(若启用SSL)均消耗CPU;每个传输线程需约2MB堆外内存。
关键参数dfs.datanode.max.transfer.threads(默认4096)直接决定单DataNode并发传输线程数。很多团队扩容后性能下降,就是因为没调这个值——新节点刚加入时,NameNode会优先向它分配新写入数据,但老节点上的数据迁移却因线程数不足而排队。我们实测:将该值从默认4096提升至8192,balancer完成时间缩短47%,且老节点CPU使用率下降18%。
另一个常被忽视的点是磁盘异构性。新购节点可能配备NVMe SSD,而老节点是HDD。若不配置dfs.datanode.data.dir的权重,NameNode会同等对待所有磁盘,导致SSD盘很快填满,HDD盘长期闲置。正确做法是在hdfs-site.xml中为不同磁盘路径设置[DISK]、[SSD]标签,并启用dfs.datanode.fsdataset.impl的分层存储策略。
3. 扩容实操全流程:从节点接入到数据均衡的7个关键步骤
3.1 步骤一:硬件与系统层预检(比配置更重要)
扩容前必须完成三项“脏活”,90%的扩容故障源于此处疏漏:
- 磁盘健康度扫描:使用
smartctl -a /dev/sdX检查新节点所有磁盘的Reallocated_Sector_Ct、Current_Pending_Sector值,任一值>0则立即更换。曾有集群因一块磁盘存在5个pending sector,扩容后3天内触发3次CorruptBlocks告警。 - 时间同步校准:所有节点必须与同一NTP服务器同步,
ntpq -p显示offset < 50ms。HDFS依赖时间戳判断块有效性,时间偏差超1分钟会导致DataNode被NameNode踢出集群。 - 内核参数调优:在新节点
/etc/sysctl.conf中追加:
执行# 提升网络连接数 net.core.somaxconn = 65535 net.ipv4.tcp_max_syn_backlog = 65535 # 优化TCP缓冲区 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 # 减少TIME_WAIT占用 net.ipv4.tcp_fin_timeout = 30sysctl -p生效。未调优节点在balancer期间易出现Connection reset by peer错误。
实操心得:我习惯在新节点部署后,先运行
dd if=/dev/zero of=/data/test bs=1M count=10240 oflag=direct(写10GB测试文件),再用iostat -x 1 30监控%util和await。若%util持续>95%或await>50ms,说明磁盘IO已达瓶颈,需检查RAID配置或更换磁盘。
3.2 步骤二:配置文件标准化与密钥分发
新节点的core-site.xml、hdfs-site.xml必须与集群完全一致,重点核对以下6项:
| 参数名 | 必须一致的值 | 错误示例后果 |
|---|---|---|
fs.defaultFS | hdfs://mycluster | 指向错误NameNode地址,节点无法注册 |
dfs.nameservices | mycluster | NameNode HA识别失败 |
dfs.ha.namenodes.mycluster | nn1,nn2 | 无法加入HA集群 |
dfs.namenode.rpc-address.mycluster.nn1 | namenode1:8020 | RPC通信超时 |
dfs.datanode.data.dir | /data1/dfs/dn,/data2/dfs/dn | 路径不存在导致DataNode启动失败 |
dfs.client.failover.proxy.provider.mycluster | org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider | 客户端无法故障转移 |
密钥分发推荐使用rsync而非scp,避免逐个节点登录:
# 在NameNode执行 rsync -avz --delete /etc/hadoop/ user@new-node:/etc/hadoop/ # 同步后,在new-node上修正属主 chown -R hdfs:hadoop /etc/hadoop/注意:
dfs.datanode.data.dir路径的父目录(如/data1/dfs/dn)必须由hdfs用户拥有,且权限为700。曾有团队因/data1目录权限为755,导致DataNode以root身份启动,后续所有块文件属主混乱,balancer报Permission denied。
3.3 步骤三:安全启动与状态验证
新节点启动顺序严格为:ZooKeeper → JournalNode → NameNode → DataNode。跳过JournalNode会导致EditLog同步中断。启动后执行三重验证:
- 进程验证:
jps | grep -E "(DataNode|JournalNode)"确认进程存在; - 日志验证:
tail -100 /var/log/hadoop-hdfs/hadoop-hdfs-datanode-*.log | grep "Registered",确认出现Registered to NameNode日志; - WebUI验证:访问
http://namenode:9870→ “Datanodes”页,确认新节点状态为In Service,且Capacity、Used、Remaining数值合理(Used应接近0)。
若WebUI中节点显示Dead,立即检查/var/log/hadoop-hdfs/hadoop-hdfs-datanode-*.log中的java.net.ConnectException,90%是dfs.namenode.rpc-address配置错误或防火墙拦截。
3.4 步骤四:触发数据均衡前的必要准备
切勿在节点上线后立即执行hdfs balancer!必须先完成:
- 检查集群健康度:
hdfs fsck / -files -blocks -locations | grep -E "(MISSING|CORRUPT)",确保无损坏块; - 确认副本策略:
hdfs getconf -confKey dfs.replication,若为非默认值(如2或4),需在balancer命令中显式指定-threshold; - 预估均衡阈值:
threshold参数定义“可接受的磁盘使用率偏差百分比”。默认10%,即允许各节点使用率在avg±10%内。计算公式:
例如集群总容量1PB,已用600TB,则avg_usage = (集群总已用空间) ÷ (集群总容量) threshold_value = avg_usage × threshold ÷ 100avg_usage=60%,threshold=10时,允许范围为50%~70%。若新节点容量远大于老节点,建议将threshold调至5,避免老节点被过度填充。
提示:
balancer默认只在dfs.datanode.data.dir路径下均衡,若你为新节点配置了[SSD]标签,需额外添加-policy参数:hdfs balancer -policy datanode -threshold 5,否则SSD盘不会参与均衡。
3.5 步骤五:执行balancer与mover的选型决策
balancer是HDFS内置均衡工具,但存在明显缺陷:
- 仅支持节点级均衡:以DataNode为单位移动块,无法感知磁盘差异;
- 无优先级控制:新节点与老节点同等对待,导致新节点填充缓慢;
- 单线程瓶颈:整个集群只有一个
balancer进程,1000+节点时效率极低。
mover是HDFS 3.0+引入的替代方案,优势显著:
- 支持路径级策略:可指定
/user目录下的块优先迁移到新节点; - 并发可控:通过
-workers参数指定并发线程数; - 支持存储策略:自动将
HOT策略块迁至SSD,COLD策略块迁至HDD。
实操对比(150节点集群,新增10台SSD节点):
| 工具 | 命令示例 | 完成时间 | 新节点最终使用率 |
|---|---|---|---|
balancer | hdfs balancer -threshold 5 | 38小时 | 42% |
mover | hdfs mover -p / -workers 20 -threshold 5 | 11小时 | 68% |
推荐组合策略:
- 先用
mover将/user、/tmp等高频目录块快速迁入新节点; - 再用
balancer做全局微调,消除残余偏差。
3.6 步骤六:balancer执行过程中的实时监控
执行hdfs balancer后,不要干等。必须监控三个核心指标:
- NameNode WebUI的“Balancer”页:关注
Bytes Left To Move(剩余迁移字节数)和Bytes Per Second(实时迁移速率)。若后者长期<1MB/s,说明网络或磁盘瓶颈; - DataNode日志:
grep "Moving block" /var/log/hadoop-hdfs/hadoop-hdfs-datanode-*.log,确认迁移动作真实发生; - 系统资源:
iostat -x 5监控svctm(服务时间),若>20ms则磁盘过载;iftop -P 50010监控DataNode间流量,确认无单点打满。
实操心得:我习惯在
balancer启动后,立即在NameNode上执行hdfs dfsadmin -report | grep "Configured Capacity",记录初始总容量。每2小时重复一次,计算Bytes Left To Move下降速率。若连续2小时下降<总迁移量的1%,立即暂停balancer,检查/var/log/hadoop-hdfs/hadoop-hdfs-balancer-*.log中的No blocks can be moved警告——这通常意味着目标节点剩余空间不足。
3.7 步骤七:均衡完成后的验证与压测
balancer退出码为0不代表真正完成!必须执行:
- 状态验证:
hdfs dfsadmin -report,检查UnderReplicatedBlocks=0、CorruptBlocks=0、MissingBlocks=0; - 分布验证:
hdfs fsck / -files -blocks -locations | awk '{print $NF}' | sort | uniq -c | sort -nr | head -10,查看Top10 DataNode的块数量,偏差应<15%; - 压测验证:用
teragen生成100GB测试数据,terasort执行排序,对比扩容前后Map input records、Reduce shuffle bytes等指标,确认吞吐提升。
最后一步常被忽略:更新集群文档。在CM(Cloudera Manager)或Ambari中更新节点标签,在内部Wiki记录新节点IP、磁盘型号、加入日期。我见过因未更新文档,导致半年后缩容时误删了刚扩容的节点。
4. 缩容实操全流程:从节点标记到安全下线的5个生死关卡
4.1 关卡一:缩容决策的黄金48小时法则
缩容不是技术操作,而是资源治理决策。必须回答三个问题:
- 业务影响评估:该节点是否承载关键业务表?用
hdfs fsck /path/to/table -files -blocks -locations检查表所在路径的块分布,若>70%块集中于此节点,需先迁移表; - 副本冗余度验证:执行
hdfs dfsadmin -metasave metasave.txt,检查Metasave文件中该节点的Blocks数,计算Blocks × dfs.replication,确认集群剩余节点总剩余空间 > 此值; - 时间窗口选择:必须在业务低峰期(如凌晨2-5点)执行,且预留48小时应急窗口——因为缩容失败后回滚成本极高。
提示:我们制定了一条“黄金48小时法则”:从决定缩容到实际执行,至少间隔48小时。这期间完成:1)全量备份该节点元数据(
hdfs dfsadmin -fetchImage);2)在测试集群复现缩容流程;3)通知所有业务方停写该节点关联路径。
4.2 关卡二:excludes文件的精确配置与热加载
HDFS缩容依赖excludes文件(默认$HADOOP_CONF_DIR/dfs.exclude),其格式为每行一个DataNode的IP或主机名,无端口、无协议。常见错误:
- 写入
192.168.1.100:50010(带端口)→ 加载失败; - 写入
datanode100.example.com但DNS未解析→ 节点状态卡在Decommission In Progress; - 文件末尾有多余空行→
hdfs dfsadmin -refreshNodes报Invalid argument。
正确流程:
# 1. 创建excludes文件(若不存在) echo "192.168.1.100" > $HADOOP_CONF_DIR/dfs.exclude # 2. 分发到所有NameNode(HA集群需同步到nn1和nn2) scp $HADOOP_CONF_DIR/dfs.exclude user@namenode1:$HADOOP_CONF_DIR/ scp $HADOOP_CONF_DIR/dfs.exclude user@namenode2:$HADOOP_CONF_DIR/ # 3. 热加载(无需重启NameNode) hdfs dfsadmin -refreshNodes注意:
-refreshNodes命令返回Successfully refreshed nodes.即表示加载成功,但节点状态不会立即改变。需等待下一次心跳(3秒后)NameNode才会将其标记为Decommission In Progress。
4.3 关卡三:Decommission In Progress状态的深度监控
节点进入此状态后,NameNode会启动副本修复流程。必须监控以下指标:
UnderReplicatedBlocks:应持续下降,若停滞>10分钟,检查/var/log/hadoop-hdfs/hadoop-hdfs-namenode-*.log中是否有Failed to replicate日志;PendingReplicationBlocks:NameNode待调度的副本数,理想值<1000,若>5000说明NameNode压力过大;ExcessBlocks:缩容节点上待删除的多余副本数,应随UnderReplicatedBlocks下降而上升。
关键参数dfs.namenode.replication.max-streams(默认2)限制NameNode并发复制流数。对于1000+节点集群,建议调至5,否则副本修复速度极慢。计算公式:
理论最大并发流 = dfs.namenode.replication.max-streams × 集群节点数但实际受dfs.namenode.replication.streams.limit(默认16384)限制,需同步调整。
4.4 关卡四:强制终止与安全回滚的临界点
当Decommission In Progress持续超预期时间,必须判断是否强制终止:
- 可安全终止的情况:
UnderReplicatedBlocks=0但ExcessBlocks>0,说明副本已补全,只需清理多余副本,执行hdfs dfsadmin -refreshNodes即可; - 必须回滚的情况:
UnderReplicatedBlocks>0且PendingReplicationBlocks=0,说明NameNode已放弃修复,此时执行hdfs dfsadmin -refreshNodes会将节点状态重置为In Service,但已迁移的块不会回退,需手动hdfs fsck修复。
强制终止命令:
# 1. 将节点从excludes文件移除 sed -i '/192.168.1.100/d' $HADOOP_CONF_DIR/dfs.exclude # 2. 重新加载 hdfs dfsadmin -refreshNodes # 3. 检查状态 hdfs dfsadmin -report | grep "192.168.1.100"实操心得:我在某次缩容中遇到
UnderReplicatedBlocks卡在237个不动,排查发现是目标节点磁盘/data2已满,但/data1仍有空间。NameNode默认按dfs.datanode.data.dir顺序写入,导致新副本无法创建。解决方案是临时修改hdfs-site.xml,将/data1路径提到前面,再执行-refreshNodes。
4.5 关卡五:节点下线后的终极验证
节点状态变为Decommissioned后,仍需三重验证:
- 数据完整性验证:
hdfs fsck / -files -blocks -locations | grep "192.168.1.100",确认无任何块记录; - 服务可用性验证:用
hdfs dfs -ls /user等命令测试客户端读写,确认无Connection refused; - 资源释放验证:在NameNode WebUI的“Datanodes”页,确认该节点已消失,且
Total节点数减1。
最后一步:物理下线前,彻底清除节点数据。执行:
# 停止DataNode sudo systemctl stop hadoop-hdfs-datanode # 清理所有数据目录 rm -rf /data1/dfs/dn /data2/dfs/dn # 清理日志 rm -f /var/log/hadoop-hdfs/hadoop-hdfs-datanode-*.log*切勿只停服务不删数据!残留数据可能导致下次误加入集群时引发块冲突。
5. 常见问题与排查技巧实录:12个真实故障现场还原
5.1 故障1:balancer启动即退出,日志报java.io.IOException: Failed on local exception: java.io.IOException: Response is null
现象:执行hdfs balancer后秒退,NameNode日志无异常,DataNode日志出现大量Connection refused。
根因:balancer进程默认使用localhost连接NameNode,但core-site.xml中fs.defaultFS配置为hdfs://mycluster,而mycluster未在/etc/hosts中解析。
解决:在balancer执行节点的/etc/hosts中添加:
192.168.1.10 namenode1 192.168.1.11 namenode2 192.168.1.100 mycluster或直接指定NameNode地址:hdfs balancer -fs hdfs://namenode1:8020 -threshold 5。
5.2 故障2:缩容节点卡在Decommission In Progress,UnderReplicatedBlocks恒为0但ExcessBlocks不降
现象:节点已无数据块,但ExcessBlocks长期>0,状态无法变为Decommissioned。
根因:NameNode的dfs.namenode.decommission.interval(默认30秒)与dfs.namenode.decommission.nodes.per.check(默认10)参数导致检查频率过低。
解决:临时调高检查频率:
<!-- 在hdfs-site.xml中 --> <property> <name>dfs.namenode.decommission.interval</name> <value>5</value> </property> <property> <name>dfs.namenode.decommission.nodes.per.check</name> <value>50</value> </property>重启NameNode后执行hdfs dfsadmin -refreshNodes。
5.3 故障3:mover执行报java.io.IOException: Failed to replace a bad datanode...
现象:hdfs mover命令报错,提示无法替换坏节点,但hdfs dfsadmin -report显示所有节点In Service。
根因:mover要求目标节点剩余空间 > 待迁移块大小,但df -h显示空间充足,实际因/data目录存在大量小文件(<1KB)占满inode。
解决:检查inode使用率:df -i /data,若Use%>95%,清理小文件或扩大inode数量:
# 重新格式化磁盘(需停服务) mkfs.ext4 -i 4096 /dev/sdb1 # 将inode ratio从默认8192改为40965.4 故障4:扩容后NameNode WebUI响应超时,jstack显示大量BLOCKED线程
现象:NameNode UI打不开,jstack输出中IPC Server handler线程全部BLOCKED在FSNamesystem.writeLock。
根因:dfs.namenode.handler.count过小,导致RPC请求队列积压,锁竞争激烈。
解决:
- 临时增加handler数:
hdfs dfsadmin -setHandlerCount 50; - 永久修改
hdfs-site.xml,将dfs.namenode.handler.count设为26; - 重启NameNode。
5.5 故障5:balancer迁移速率极低(<100KB/s),iostat显示磁盘%util=100%
现象:balancer跑了12小时,只迁移了2GB数据,iostat显示某块磁盘持续100%。
根因:该磁盘被/var/log或/tmp目录占用,balancer读写与系统日志写入争抢IO。
解决:
- 将
/var/log/hadoop-hdfs软链接到数据盘:ln -sf /data1/logs /var/log/hadoop-hdfs; - 清理
/tmp:find /tmp -name "hadoop*" -mtime +7 -delete; - 重启DataNode。
5.6 故障6:缩容后hdfs fsck /报MISSING 12345 blocks
现象:节点已下线,但fsck显示大量缺失块。
根因:缩容前未检查CorruptBlocks,这些块本就损坏,缩容时NameNode未尝试修复。
解决:
- 先修复损坏块:
hdfs fsck / -delete(慎用)或hdfs fsck / -move(移至/lost+found); - 再执行缩容流程。
5.7 故障7:mover执行报java.lang.OutOfMemoryError: Java heap space
现象:mover进程OOM崩溃。
根因:mover默认JVM堆内存为1GB,处理大目录时元数据加载超限。
解决:修改hadoop-env.sh:
export HADOOP_CLIENT_OPTS="-Xmx4g -XX:+UseG1GC $HADOOP_CLIENT_OPTS"重启客户端环境。
5.8 故障8:扩容节点WebUI显示Capacity=0
现象:新节点状态In Service,但容量为0。
根因:dfs.datanode.data.dir路径权限错误,或磁盘未挂载。
解决:
df -h确认磁盘已挂载;ls -ld /data1/dfs/dn确认属主为hdfs:hadoop,权限700;chown -R hdfs:hadoop /data1/dfs/dn;- 重启DataNode。
5.9 故障9:balancer完成后,hdfs dfsadmin -report显示某节点Used突增20%
现象:均衡后某老节点使用率异常升高。
根因:该节点磁盘存在坏道,balancer将块迁入后,DataNode后台扫描发现坏块,触发自动复制,新副本又写回同一磁盘。
解决:
smartctl -a /dev/sdX确认坏道;- 从
dfs.datanode.data.dir中移除此磁盘路径; - 重启DataNode。
5.10 故障10:缩容节点Decommissioned后,hdfs dfs -ls /报Filesystem closed
现象:节点下线后,客户端命令报此错。
根因:客户端缓存了已下线节点的地址,未及时刷新。
解决:
- 清理客户端
/tmp/hadoop-username/缓存; - 重启客户端应用;
- 或在
core-site.xml中添加:
<property> <name>fs.defaultFS</name> <value>hdfs://mycluster</value> </property>