简介:这份资源定位为Hadoop入门级综合项目,适合正在学习分布式存储、大数据课程设计或准备相关实验的开发者。压缩包共142个文件,总大小3.14MB,结构较为完整:内含13个Java源文件、4个JSP动态页面、25个JavaScript脚本、16个CSS样式表以及多张图片图标素材,并附有Eclipse工程配置和说明文档,基本还原了基于HDFS的云存储系统Web端与后端逻辑骨架。学习者可据此对照理解HDFS的块存储与多副本容错机制,查看MapReduce的Map/Reduce阶段如何被组织进系统流程,也能从项目目录中借鉴NameNode、DataNode等角色的职责拆分。资源轻量但信息密度高,已有40人学习,适合结合官方文档边阅读源码边验证概念,可帮助快速建立对分布式云存储系统高可靠、高吞吐、可扩展特性的工程化认知。
1. Hadoop分布式云存储:这份资源能跑通的不只是概念
我拆过不少 Hadoop 课程设计和毕业设计的压缩包,最常见的情况是:源码一大堆,前端截图很精美,但真按 README 去配环境,要么缺依赖要么跑不起来。这份“基于Hadoop的分布式云存储系统.zip”不一样,压缩包里能看到.classpath、org.eclipse.wst.common.component这类 Eclipse Java Web 工程标记文件,还有一套基于 Bootmetro 风格的前端样式。也就是说,它不只是一份原理文档,而是一个能导入 IDE、能部署到 Hadoop 集群上的真实工程。你拿它做课程设计或者毕设,核心不是背 HDFS 概念,而是把它在伪分布式或三节点集群上跑起来,把存储流程和计算流程打通。
2. HDFS块与副本机制:先看懂这套系统的存储骨架
2.1 块与副本:两个决定数据安全的核心参数
HDFS 在设计时就假设底层硬件是廉价的、会坏的,所以它把数据切分成固定大小的块再分散存储。一个 1GB 的文件,默认按 128MB 切块,会被拆成 8 个块,分布在集群的不同 DataNode 上。这就是“分布式”最直接的体现:没有哪台机器单独持有完整文件,但合起来就是一个巨大存储池。
块大小和副本数在hdfs-site.xml里分别对应dfs.blocksize和dfs.replication两个参数。伪分布式单机环境下,副本数必须设为 1,否则数据只能写出副本数为 1 的状态,然后一直告警“副本不足”。生产环境一般配 3,这个数字不是拍脑袋定的,它来自“同一机架坏一台机器 + 交换机故障”的容错模型。你能接受多少容错,就放多少副本,副本数不能超过节点数。
查看当前集群生效的块大小和副本数,直接用命令:
hdfs getconf -confKey dfs.blocksize hdfs getconf -confKey dfs.replication第一个命令返回的是字节数,默认 134217728,也就是 128MB;第二个返回副本数。我每次搭完环境都会先跑这两条命令,确认配置真的生效了,而不是只看 xml 文件里写了什么。配置文件改了不重启集群,或者改了没重新格式化,是新手最容易翻车的地方。
想查看某个文件实际被切成了几块、每块放在哪些节点上,用 fsck 命令:
hdfs fsck /user/data/xxx.tar.gz -files -blocks -locations这个命令会打印出文件的块列表,每块对应哪几个 DataNode 的副本位置。你能直观看到 128MB 的边界是怎么切分的,也能验证副本是不是真的分布在多台机器上。如果输出里出现 “Missing replica” 之类的字段,说明副本失败了,基本可以往磁盘空间、DataNode 存活状态这两个方向排查。
2.2 NameNode与DataNode:一只“管账”和一群“管货”
HDFS 里有两类角色。NameNode 管元数据,它维护整个文件系统的目录树、文件与块的映射关系、块与 DataNode 的对应关系,可以理解为“管账本”的角色。DataNode 真正存储数据块,负责读写操作和定期汇报,是“管货”的角色。
客户端读写文件时,这个分工体现得很干净。客户端先访问 NameNode,问“我要读/user/data/xxx这个文件,它的每个块在哪”,NameNode 返回一份块位置列表;然后客户端直连对应的 DataNode 拉数据。整个过程中,数据不经过 NameNode,否则它就成了瓶颈。这也是 HDFS 能支撑高吞吐的原因之一。
DataNode 和 NameNode 之间靠心跳维持关系。DataNode 默认每 3 秒上报一次心跳,包含存活状态、存储容量、块报告。NameNode 如果超过 5 分钟没收到某个 DataNode 的心跳,就会把它标记为下线,并把该节点上的副本在其他节点上重新补足。这个 5 分钟由dfs.namenode.heartbeat.recheck-interval控制,单位是毫秒,默认 300000。
有一次我在实验环境里把一台 DataNode 直接拔电,等了几分钟去看 NameNode 的日志,里面会一条条列“lost block”和“re-replicating”的操作记录。如果你想观察副本自动补足的过程,用hdfs dfsadmin -report反复刷新,能看到副本数从 2 慢慢变回 3。这个现象比任何截图都能说明 HDFS 的容错设计是真实生效的。
2.3 元数据都在内存里:一个容易忽视的边界
NameNode 把元数据全部加载在内存中,这是它的设计边界,也是后面调优的地基。意味着 NameNode 能管理多少文件,取决于给它的堆内存有多大。一个文件一条 inode 记录,一个块也占一条记录,如果你的系统塞满了小文件,几百个 G 的存储挂在上面,最终先爆掉的很可能是 NameNode 的堆内存,而不是磁盘。
这一条对“云存储”类项目特别重要。很多人用 HDFS 存一大堆几 KB 的日志碎片,最后发现 NameNode 频繁 Full GC,而 DataNode 磁盘还空得很。HDFS 是为大文件设计的,海量小文件场景应该先合并,或者改用适合的对象存储方案。这份资源里的工程,存储侧是标准的 HDFS API 读写,不太涉及小文件优化,但理解这个边界,你在设计测试数据时就不会犯“上传一个 10MB 文件然后开了 100 个”这种常识性错误。
元数据本身通过fsimage(内存快照)和edits log(操作日志)持久化到磁盘,SecondaryNameNode 会定期合并这两份文件,避免 edits 无限变大。这块我不过度展开,你只需要记住:元数据不是不存在磁盘上,但完整参与运算的元数据一定在内存里。所以hdfs namenode -format格式化操作要谨慎,它会重建整个元数据空间,format 之后原集群的数据块和新的元数据对上号,之前的数据全部视为孤儿块。
3. 把工程跑起来:伪分布式环境搭建与项目部署
3.1 环境准备:版本、JDK 和 SSH 免密
搭 Hadoop 环境之前,先确认 JDK 版本。Hadoop 3.x 官方支持 Java 8 和 Java 11,我自己习惯装 OpenJDK 8,兼容性最稳。装完 Java 先验证java -version,能正常输出版本号再往下走。Hadoop 3.x 对 Java 9/10 的兼容性很差,装错版本会报一些奇怪的类加载错误,那种问题排查起来很折腾。
然后是 SSH 免密登录。即使是伪分布式单机,start-dfs.sh也是通过 SSH 连接本机来拉起进程的,如果不配免密,每次执行都要输密码,集群自动化根本玩不转。配置命令:
ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys ssh localhost第一行生成密钥对,-P ''表示不设置口令,否则后续 SSH 时会问你 passphrase,脚本化运行就卡住了。最后一行的ssh localhost是验证,能直接进命令行说明免密生效。另外建议在/etc/hosts里把机器 hostname 配好,比如伪分布式常用localhost,完全分布式会把每台节点的 IP 和名称写进去,否则 Hadoop 进程之间解析不到主机名会报连接超时。
Hadoop 本身下载 tar 包解压即用,不需要编译安装。解压到/opt/hadoop,然后配环境变量:
export HADOOP_HOME=/opt/hadoop export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin这两行建议写进/etc/profile,source 一下让当前会话生效。版本选择上,如果你只是课程设计和学习,选 2.x 还是 3.x 都行;但 3.x 更主流,默认端口也和 2.x 有区别,后面的示例我按 3.x 的习惯写,2.x 用户注意端口差异。
3.2 五份核心配置文件逐一改
Hadoop 的环境变量和配置分布在$HADOOP_HOME/etc/hadoop目录下。伪分布式搭建,核心要改五个文件,每个文件的职责要分清。
第一个是hadoop-env.sh,这个文件负责 JVM 参数和环境变量。重点检查两项:
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 export HADOOP_HEAPSIZE=1024 export HDFS_NAMENODE_USER=root export HDFS_DATANODE_USER=root export YARN_RESOURCEMANAGER_USER=root export YARN_NODEMANAGER_USER=rootJAVA_HOME必须改成自己机器上 JDK 的真实路径,不能用/usr/bin/java这种间接路径,Hadoop 启动脚本认的是JAVA_HOME指向的完整目录。后面四项是 Hadoop 3.x 用 root 用户启动时必须补的,不然start-dfs.sh会拒绝执行,我在实验环境里踩过这个坑。如果不打算用 root 运行,再单独建一个 hadoop 用户,但那样文件权限问题会多出一堆,学习环境我建议直接 root 加上面四项。
第二个是core-site.xml,管全局参数:
<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/opt/hadoop/tmp</value> </property> </configuration>fs.defaultFS是 NameNode 的 RPC 通信地址,客户端就是通过这个地址提交读写请求。hadoop.tmp.dir是元数据目录的基路径,默认指向/tmp/hadoop-${user.name},系统重启 tmp 会被清空,NameNode 格式化状态就莫名其妙丢了。我一般会把这个目录移到 Hadoop 安装目录下,和系统临时目录隔离。
第三个是hdfs-site.xml,管 HDFS 自身参数:
<configuration> <property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:///opt/hadoop/data/namenode</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:///opt/hadoop/data/datanode</value> </property> </configuration>dfs.replication伪分布式必须为 1,这是整个配置文件里最容易错的一项。dfs.namenode.name.dir和dfs.datanode.data.dir分别指定元数据和数据块的落盘目录,显式写出来比用默认值更清晰,排障时直接去这些目录里找current/VERSION文件即可。这两个目录在格式化之前要保证存在,或者让脚本自动创建,权限给对。
第四个是mapred-site.xml:在 Hadoop 2.x 和 3.x 里,MapReduce 框架已经改成跑在 YARN 之上,需要显式声明:
<configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration>如果这一步漏了,MapReduce 作业会尝试用老旧的 standalone 模式运行,本地跑没问题,但没法利用集群资源,作业会非常慢,而且ResourceManager界面里看不到任何作业。
第五个是yarn-site.xml,管计算资源调度:
<configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <property> <name>yarn.nodemanager.resource.memory-mb</name> <value>2048</value> </property> </configuration>aux-services是 NodeManager 启动辅助服务的参数,MapReduce 的 shuffle 阶段依赖它,不配的话作业跑起来 Mapper 能过、Reducer 卡死,错误信息在日志里写得也比较隐蔽,建议提前配好。resource.memory-mb是 NodeManager 能调度的物理内存上限,伪分布式的机器内存不大的话给 2048 是一个比较稳妥的值。
3.3 格式化、启动与工程导入
配置文件改完后,第一步是做 NameNode 格式化,这一步只执行一次,千万别在集群跑着的时候反复 format:
hdfs namenode -format命令执行完看到successfully formatted就说明元数据初始化成功。随之会在/opt/hadoop/data/namenode/current下生成VERSION文件,里面记录了namespaceID和clusterID,后面 DataNode 找的就是这个 ID,两边的 clusterID 不匹配就会导致 DataNode 起不来,这是我在第 5 章要重点讲的坑。
启动集群用两个脚本:
start-dfs.sh start-yarn.sh启动完用jps验证进程,伪分布式应该能看到NameNode、DataNode、SecondaryNameNode、ResourceManager、NodeManager五个进程。缺哪个,去对应的日志目录$HADOOP_HOME/logs找日志文件,一行行看报错。再跑hdfs dfsadmin -report,能看到容量和存活节点信息,数据节点注册成功说明 NameNode 和 DataNode 通信没问题。
Web 界面方面,Hadoop 3.x 的 NameNode 页面是http://localhost:9870,Hadoop 2.x 是http://localhost:50070。如果你访问的是 YARN 的页面,那是http://localhost:8088。这三个端口别搞混,我见过有人盯着 8088 端口说 HDFS 打不开,其实两个根本不是同一个服务。
工程导入方面,如果这份资源是 Eclipse 工程,导入路径是File -> Import -> Existing Projects into Workspace,选择解压后的目录,Eclipse 会通过.classpath和.project文件自动识别依赖。它带着org.eclipse.wst.common.component,说明是 Eclipse WTP 的 Web 工程结构,所以跑之前配置好 Tomcat 运行环境。如果是 Maven 工程,直接mvn clean package打包后再部署。前端用 Bootmetro 那套样式,页面响应式布局,跑起来之后在浏览器里操作文件上传、下载、浏览,对应底层调的就是 HDFS API。
4. 副本因子与块大小调优:可靠性是用参数换来的,不是玄学
4.1 副本因子:不是越大越安全
dfs.replication默认是 3,但伪分布式单机必须改成 1。很多人在单机上跑默认配置,上传文件后看到dfs replication显示 3 低于预期,以为 HDFS 坏了,其实只是节点数不支持 3 份副本。这个参数的本质是“你愿意用多少存储空间换多少容错”,3 副本意味着 1TB 数据实际占用 3TB 物理空间。
在完全分布式下,如果每个节点只有一块数据盘,3 副本的放置策略是第一副本在客户端所在节点,第二副本放在同机架的另一节点,第三副本跨机架。这样设计的目的是:同一机架断电不会丢全部副本,机架间交换机故障也有兜底。我在三节点实验集群里验证过,停掉一台 DataNode 后,hdfs dfsadmin -report里能看到其他两台节点的副本数变为 2,然后后台自动完成一次跨节点复制,最终重新恢复到 3。这个过程全部自动执行,调参时只要保证一个原则:副本数不能大于节点数,否则必然会一直停留在补副本状态。
如果不想全局改,只针对某个目录调整副本数,用setrep:
hdfs dfs -setrep -R 2 /user/data/hot-R表示递归,对目录下所有文件生效。这个命令很实用,比如有些目录是访问频率低的历史数据,你可以把副本数临时降为 2,释放一半容量;等数据要参与重要计算时再调回 3。还有一点要注意:setrep只是修改了文件的副本策略,实际补副本或删副本是异步的,可以立刻用fsck验证变化过程。
4.2 块大小与缓冲区:吞吐量和内存的权衡
块大小默认 128MB,自 Hadoop 2.7 之后基本没有变过。块越大,NameNode 需要维护的元数据条目越少,对大文件场景是好事。但块太大,MapReduce 的并行度也会随之降低,因为一个块只能被一个 Mapper 处理,200 个块就能起 200 个 Mapper,60 个块就只有 60 个 Mapper。我在处理 5GB 左右的数据集时,习惯把块大小配置在 128MB 到 256MB 之间,更小的块对小文件没有实质帮助,反而让 NameNode 的块记录膨胀,内存更吃紧。
缓冲区参数容易被忽略,io.file.buffer.size控制在读写 HDFS 文件时使用多大的字节缓冲区,默认只有 4096 字节。这个值偏小,我在处理大数据读写时习惯调到 64KB 到 128KB,能显著减少系统调用次数。注意它不是越大越好,过大会占用过多 JVM 堆外内存,多线程并发读写时反而拖垮性能。
核心参数参考下表:
| 参数 | 默认值 | 常用调整值 | 说明 |
|---|---|---|---|
dfs.blocksize | 128MB | 128MB / 256MB | 数据块大小,影响元数据数量和 Map 并行度 |
dfs.replication | 3 | 单机 1 / 生产 3 | 副本数,不能超过节点数 |
io.file.buffer.size | 4096 | 65536 | HDFS 读写缓冲区字节数 |
dfs.namenode.handler.count | 10 | 100 | NameNode 并发处理线程数,高并发场景调高 |
dfs.datanode.handler.count | 3 | 20 | DataNode 处理数据请求的线程数 |
dfs.heartbeat.interval | 3 | 3 | 心跳间隔秒数 |
dfs.namenode.heartbeat.recheck-interval | 300000 | 300000 | 判定节点下线的检查间隔毫秒数 |
4.3 服务端参数组合:一份可以直接抄的调优示例
把上面的参数变成一份实际可用的hdfs-site.xml调优版本:
<configuration> <property> <name>dfs.namenode.name.dir</name> <value>file:///opt/hadoop/data/namenode</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:///opt/hadoop/data/datanode</value> </property> <property> <name>dfs.replication</name> <value>3</value> </property> <property> <name>dfs.blocksize</name> <value>134217728</value> </property> <property> <name>dfs.namenode.handler.count</name> <value>100</value> </property> <property> <name>dfs.datanode.handler.count</name> <value>20</value> </property> <property> <name>io.file.buffer.size</name> <value>65536</value> </property> </configuration>这段配置适用于三节点完全分布式小集群。blocksize写成字节单位的 134217728,就是 128MB。handler.count 是并发能力的关键,默认值 10 在三节点集群写满数据时会明显感觉吞吐上不去,调高到 100 之后并发上传的响应快很多。加了这些参数不意味着改动完成了,还要重启集群让配置生效,再用hdfs getconf -confKey dfs.blocksize逐个验证。
除了 HDFS 侧,YARN 侧的mapreduce.map.memory.mb和mapreduce.reduce.memory.mb控制每个 Map/Reduce 任务的容器内存。我一般给到 1024MB,如果机器总内存只有 4GB,YARN 总资源给 2GB,每个任务容器 512MB 比较安全。yarn.scheduler.minimum-allocation-mb也要同步调低,否则任务分配不到容器会一直卡在 PENDING 状态。
这套参数逻辑,对你日后接触其他分布式存储系统同样适用:先确认节点数和副本数的关系,再调并发线程数,最后调缓冲区。按照这个顺序调参,基本不会出现改了参数反而变慢的情况。
5. 高频故障排查:DataNode失联、端口混淆与内存溢出三座大山
5.1 DataNode反复启动失败,日志报clusterID不一致
现象:执行start-dfs.sh之后,jps能看到 NameNode,但 DataNode 进程消失,或者 DataNode 起来了但 NameNode 页面显示它一直处于 Dead 状态。查看日志目录下的hadoop-root-datanode-*.log,里面报Incompatible clusterIDs。
原因:这个错误几乎都是重新执行了hdfs namenode -format造成的。格式化会为 NameNode 生成一个新的clusterID,而旧 DataNode 的VERSION文件里记录的还是第一次格式化时的 clusterID,两个 ID 对不上,DataNode 拒绝注册。伪分布式环境里大家习惯反复格式化,踩这个坑的比例非常高。
解决:把 NameNode 和 DataNode 的数据目录全部清空,然后重新格式化。命令示例:
rm -rf /opt/hadoop/data/namenode /opt/hadoop/data/datanode rm -rf /opt/hadoop/tmp hdfs namenode -format start-dfs.sh注意这是删库级操作,生产环境千万别这么干。学习环境无所谓,但你要清楚:format一次就够了,不要手欠多次格式化。如果只是挨个进程重启,永远不要重新 format。
5.2 浏览器访问NameNode页面被拒
现象:集群启动正常,jps进程齐全,但浏览器输入本地地址打不开页面,显示拒绝连接或超时。
原因:大概率是端口搞混了,或者防火墙没放行。Hadoop 2.x 的 NameNode Web UI 端口是 50070,3.x 改成了 9870;而 8088 是 YARN 的 ResourceManager 页面,不是 HDFS 的页面。很多人用 3.x 去访问 50070,自然打不开。另一方面,很多 Linux 发行版默认开 firewall,9807 端口不在放行列表里。
解决:先用netstat -tlnp | grep java看进程实际监听的端口,确认版本对应的端口号;然后用curl http://localhost:9870测试本机访问是否通。通的话就放行防火墙:
firewall-cmd --zone=public --add-port=9870/tcp --permanent firewall-cmd --reload临时省事也可以用systemctl stop firewalld,但只适合实验环境。如果你是在 Windows 本机访问虚拟机里的 Hadoop,除了防火墙还要确认虚拟机的 NAT 或桥接网络配置,业务端口没映射过去的话域名通、端口未必通。
5.3 伪分布式配置副本数为3,导致副本缺失告警
现象:单机伪分布式,按默认配置启动后上传文件,NameNode 页面一直在报Under replicated blocks,fsck检查结果显示每个块只有 1 个副本,期望是 3。
原因:伪分布式只有一台 DataNode,而dfs.replication默认是 3。HDFS 不会在同一节点上重复存放同一个块的多个副本,所以无论等多久,节点数不够,副本永远到不了 3。这个“玄学”现象的本质是物理条件不满足。
解决:把hdfs-site.xml里的dfs.replication改成 1,重启集群。如果是已上传的文件,用setrep把副本数批量降下来:
hdfs dfs -setrep -R 1 /如果你原本就打算将来扩成多节点集群,也可以保持配置为 3,但副本告警会一直挂在页面上,不影响正常读写,只是视觉效果不好。我更倾向于单机阶段就改成 1,等节点真的加到三台再改回 3,用hdfs fsck重新验证副本补足过程。
5.4 集群启动后频繁OOM或进程被kill
现象:start-dfs.sh执行时提示killed,或者 NameNode 起来后 JVM 直接崩,又或者提交 MapReduce 作业时任务永远是 PENDING。查看hadoop-env.sh日志,能看到java.lang.OutOfMemoryError。
原因:一台 2GB 内存的机器,同时跑 NameNode、DataNode、SecondaryNameNode、ResourceManager、NodeManager 五个 JVM,每个默认堆内存 1GB,加起来远超物理内存,系统 OOM Killer 只能挑进程下手。
解决:在hadoop-env.sh里把堆内存降下来,伪分布式 512MB 完全够用。YARN 的总内存也要同步收紧,yarn.nodemanager.resource.memory-mb设置为 1024 或 2048,yarn.scheduler.maximum-allocation-mb保持不超过这个值。改完重启,用free -h确认内存有富余。
我自己的习惯是分两个阶段避免这个问题:先总览节点数与内存匹配情况,再按“NameNode 512MB + DataNode 256MB + YARN 1GB”的模版去配置。这样做完,一台 4GB 内存的机器跑伪分布式全程都不需要担心 OOM。
5.5 Eclipse直接跑HDFS API报winutils错误
现象:在 Windows 上用 Eclipse 直接运行该工程的 HDFS 读写客户端,报Failed to locate the winutils binary in the hadoop binary path或者Permission denied。
原因:HDFS 客户端在 Windows 上需要一个本地库 winutils.exe 才能模拟权限检查,Windows 原生没有这个文件,Hadoop 的 bin 目录也不会自带。
解决:下载和你 Hadoop 版本对应的 winutils.exe 放入HADOOP_HOME/bin,然后设置HADOOP_HOME系统环境变量。装完之后重启 IDE。如果报错变成权限问题,检查 winutils 的版本和 Hadoop 主版本是否匹配,Hadoop 3.x 的 winutils 和 2.x 不能混用。还有一个更省心的方案:把 HDFS 操作封装成服务端接口,通过 Web 工程代理,客户端只调 HTTP 接口,就完全绕开 winutils 的依赖了。
6. 完整读写验证:让MapReduce任务真正跑一遍分布式存储
环境起来、工程导入、参数调完,这时候还不能算“跑通”。我习惯做一轮完整的读写验证,把存储链路和计算链路都拉通一遍,证明集群里确实有数据流动。
先建目录再上传文件,模拟一份待处理的数据:
hdfs dfs -mkdir -p /user/data hdfs dfs -put /opt/sample.txt /user/data/sample.txt上传成功后用fsck确认块分布:
hdfs fsck /user/data/sample.txt -files -blocks -locations输出里能看到文件被切成几块,每一块落在哪几个节点上。然后跑一个 MapReduce 任务验证计算链路,用 Hadoop 自带的全分布式 WordCount:
hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar \ wordcount /user/data/sample.txt /user/output任务跑完后查看输出结果:
hdfs dfs -cat /user/output/part-r-00000 | head hdfs dfs -ls /user/output到这一步,上传、块切分、分布式计算、结果写回 HDFS 全部打通,这份资源才真正属于你了。如果 WordCount 卡在map 100% reduce 0%,优先查mapred-site.xml的mapreduce.framework.name是否等于yarn,再看yarn-site.xml的资源内存是否够分配容器。这两个配置是我见过报告推算半天最后才被发现是最低级原因的典型案例。
最后一步是检查 NameNode 的 Web 页面:看存活节点数、容量使用率、副本缺失数量是否都为正常值。如果一切正常,说明集群磁盘、网络、参数三方都健康。从 3 副本的归档文件解压出来,到把它跑成一条完整的数据流水线,真正让你记住的不是界面长什么样,而是那几个进程之间的通信逻辑和错误日志指向的真相。希望你在这个工程里,不只是拿到一个 zip 解压后的文件列表,而是能顺着这套验证流程,把 Hadoop 集群的启动、存储、计算三条链路都亲手走通一次。
本文还有配套的精品资源,点击获取