
简介这份资源是《大数据技术原理与应用》课程实验二的完整实验报告面向正在学习Hadoop与大数据基础的高校学生及自学者帮助解决HDFS Shell命令与Java API操作入门难、实验流程不清晰的问题。资源包内含1个docx文档压缩包约3.4MB以实验报告形式呈现涵盖实验环境说明、Shell命令操作与Java编程实现两大模块。报告详细记录了使用hdfs dfs -put上传文件、-test -e检查文件存在性、-appendToFile追加内容及-copyFromLocal -f覆盖文件等命令并给出基于Configuration、FileSystem、Path等类的Java代码实现包括文件存在性判断与本地文件复制到HDFS的完整逻辑。目前已有10214人学习下载适合作为HDFS基础操作的参考范例帮助读者理解HDFS在Hadoop体系中的存储角色为后续MapReduce编程及HBase等生态组件学习打下基础。1. 为什么“会敲 ls 却不会排障”是 HDFS 学习里最典型的翻车现场很多人第一次接触大数据实验都是从 HDFS 开始的。打开终端hadoop fs -ls /能列出目录-put能传文件-cat能看内容实验报告一交感觉已经“掌握”了。可真到了集群里某个 DataNode 掉线、副本数对不上、上传卡在 99% 不动的时候才发现自己只会背命令根本不知道数据到底走了哪条路。这篇笔记围绕一份“熟悉常用的 HDFS 操作”实验资源展开把 HDFS 读写流程、常用命令、Shell 与 Java API 两条操作路径以及最容易踩的坑一次讲透。适合刚上手 Hadoop 的在校学生、转行做大数据开发的工程师也适合已经会敲命令但想补上排障能力的人。资源本身是一套可复现的实验操作集合重点不在“命令大全”而在让你理解每条命令背后动了哪个组件、改了哪份元数据。2. HDFS 读写流程先搞懂数据怎么走命令才不会白敲2.1 写流程为什么上传大文件会先切块再排队HDFS 写文件不是把整个文件一次性推给某台机器而是先切块再流水线复制。客户端调用create()后NameNode 会在元数据里建一条记录返回一个可写的输出流客户端把数据按块大小默认 128MB切开每写完一个块就向 NameNode 申请一组 DataNode 列表然后以管道方式逐个下发。第一个 DataNode 收到包后转发给第二个第二个再转发给第三个ACK 沿原路返回。这就是为什么上传大文件时你会看到进度条一段一段跳而不是线性增长。理解这条链路排障时就有方向了卡在申请块阶段多半是 NameNode 压力大或权限问题卡在管道传输阶段通常是某个 DataNode 磁盘满或网络抖动。常见做法是先用hdfs dfsadmin -report看各节点剩余空间和存活状态再决定是等还是换节点。2.2 读流程为什么“就近读取”能省一半时间读文件时客户端先问 NameNode 要这个文件所有块的位置信息NameNode 返回按网络拓扑排序的 DataNode 列表距离近的排前面。客户端优先读本地或同机架的副本读失败才切下一个副本。这个机制叫机架感知是 HDFS 高吞吐的关键。很多人实验里读文件很快就以为是自己代码写得好其实是副本刚好在本地。这里有个容易忽略的点NameNode 只负责告诉你去哪读不参与实际数据传输。所以读性能瓶颈几乎永远在 DataNode 磁盘和网络而不是 NameNode。实验里如果读特别慢先查iostat和网卡别急着怀疑元数据服务。2.3 用命令验证读写链路光看原理不够得动手验证。下面这组命令能让你直观看到块分布和副本状态# 查看文件被切成了几个块每个块在哪些 DataNode 上 hdfs fsck /user/test/bigfile.txt -files -blocks -locations # 查看集群整体容量、存活节点数、副本情况 hdfs dfsadmin -report # 查看某个目录下文件的块大小和副本数 hdfs dfs -stat 块大小:%o 副本数:%r 路径:%n /user/test/bigfile.txtfsck输出里的BP-xxx是块池 ID后面跟的DatanodeInfoWithStorage就是副本所在节点。如果某个块只显示一个副本说明复制没完成或节点掉线。-stat里的%o是块大小字节%r是副本因子%n是文件名。这几个参数在写实验报告时比截图更有说服力因为它们直接来自元数据。3. 常用命令实操从 put 到 get每条都对应一个元数据动作3.1 文件上传下载-put、-copyFromLocal 和 -moveFromLocal 的区别这三个命令新手最容易混。-put和-copyFromLocal行为几乎一样都是把本地文件复制到 HDFS本地保留-moveFromLocal则是移动本地文件会被删掉。实验里如果只是演示上传用-put最稳因为不会误删本地数据。# 创建测试目录 hdfs dfs -mkdir -p /user/test/hdfs_lab # 上传本地文件到 HDFS保留本地副本 hdfs dfs -put ./local_data.csv /user/test/hdfs_lab/ # 上传并覆盖已存在文件 hdfs dfs -put -f ./local_data.csv /user/test/hdfs_lab/ # 从 HDFS 下载到本地本地已存在会报错 hdfs dfs -get /user/test/hdfs_lab/local_data.csv ./download/ # 下载并合并成一个大文件针对多个块 hdfs dfs -getmerge /user/test/hdfs_lab/part-* ./merged.txt-f参数是覆盖开关不加的话目标存在会直接失败。-getmerge在做 MapReduce 结果收集时特别常用因为 reduce 输出通常是part-r-00000这种多文件合并后方便本地查看。注意-getmerge只做拼接不排序别指望它帮你整理数据。3.2 目录与权限-ls、-du、-chmod 背后的元数据操作-ls读的是 NameNode 的目录树-du统计的是文件实际占用空间考虑副本-chmod改的是权限位。这三个命令都不碰数据块只动元数据所以执行很快。# 递归查看目录显示权限、副本数、大小 hdfs dfs -ls -R /user/test/hdfs_lab # 查看目录总大小含副本所以可能是实际文件的数倍 hdfs dfs -du -s -h /user/test/hdfs_lab # 修改权限和 Linux 类似 hdfs dfs -chmod -R 755 /user/test/hdfs_lab # 修改副本数只影响之后新写入的块 hdfs dfs -setrep -w 2 /user/test/hdfs_lab/local_data.csv-du的输出单位是字节加-h才变成人类可读。-setrep的-w表示等待复制完成不加的话命令立刻返回但后台还在复制。实验里如果改了副本数马上用fsck查可能看到副本还没达标别慌等几秒再查。3.3 用 Java API 操作 HDFS比 Shell 更接近生产Shell 适合快速验证但生产里更多用 Java API因为能嵌到调度系统里。下面这段代码演示了连接、创建目录、上传、读取四个基本动作import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; public class HdfsLab { public static void main(String[] args) throws Exception { // 加载配置core-site.xml 里指定了 NameNode 地址 Configuration conf new Configuration(); conf.set(fs.defaultFS, hdfs://namenode-host:8020); // 获取文件系统实例 FileSystem fs FileSystem.get(conf); // 创建目录 Path dir new Path(/user/test/api_lab); if (!fs.existsSync(dir)) { fs.mkdirs(dir); } // 上传本地文件 Path local new Path(./local_data.csv); Path remote new Path(/user/test/api_lab/data.csv); fs.copyFromLocalFile(local, remote); // 读取文件内容 FSDataInputStream in fs.open(remote); byte[] buffer new byte[1024]; int len; while ((len in.read(buffer)) ! -1) { System.out.write(buffer, 0, len); } in.close(); fs.close(); } }fs.defaultFS必须和集群实际地址一致端口常见是 8020 或 9000写错会直接连不上。copyFromLocalFile默认覆盖目标如果不想覆盖可以先用exists判断。FSDataInputStream是 HDFS 自己的输入流支持seek适合做随机读。这段代码编译时需要把 Hadoop 的 jar 包加进 classpath常见做法是用 Maven 引入hadoop-client依赖版本和集群保持一致否则容易出现序列化不兼容。4. 避坑与排查实验里最容易翻车的五个点4.1 现象put报错 “Could only be replicated to 0 nodes”原因通常是 DataNode 没启动或者磁盘空间不足导致 NameNode 拒绝分配块。先看jps有没有DataNode进程再看dfsadmin -report里存活节点数是不是 0。如果是磁盘满清理/tmp或调整dfs.datanode.du.reserved保留空间。4.2 现象ls能看到文件cat却报 “BlockMissingException”说明元数据还在但实际数据块丢了。用fsck确认哪些块缺失如果副本数大于 1 且还有其他副本HDFS 会自动恢复如果所有副本都没了只能从本地重新上传。实验里常见于手动删了 DataNode 数据目录。4.3 现象Java API 连接超时Shell 却正常多半是fs.defaultFS配错或者客户端没把 Hadoop 配置目录加进 classpath。Shell 会自动读环境变量Java 代码不会。检查Configuration加载的core-site.xml路径或者直接在代码里conf.set指定地址。4.4 现象-setrep改了副本数fsck显示还是旧值-setrep只对新写入的块生效已有块需要等后台复制或手动触发。加-w等待或者用hdfs dfs -setrep -R递归改整个目录。注意副本数不能超过 DataNode 数量否则永远达不到。4.5 现象上传小文件特别慢HDFS 为大数据块设计每个小文件都会在 NameNode 占一份元数据上传时也要走完整的创建、申请块、管道流程。实验里如果传几百个 KB 级文件慢是正常的。生产里常见做法是先合并再上传或者用 HAR 归档。5. 进阶技巧用 fsck 和 safemode 做一次完整体检实验做完别急着关终端用下面这套组合拳给集群做一次体检能提前发现很多隐患# 进入安全模式禁止写操作只读检查 hdfs dfsadmin -safemode enter # 全盘检查列出所有缺失或副本不足的块 hdfs fsck / -files -blocks -locations # 查看检查结果摘要 hdfs fsck / -summary # 退出安全模式 hdfs dfsadmin -safemode leave安全模式下 NameNode 不接受写请求但读和检查正常适合做一致性排查。fsck的-summary会输出总块数、缺失块数、副本不足块数一眼就能判断集群健康度。如果缺失块不为 0先别退出安全模式用-delete参数清理损坏块再从备份恢复。我自己的习惯是每次实验结束前都跑一遍fsck -summary确认副本数达标再关机。有一次偷懒没查第二天发现某个 DataNode 磁盘写满导致三个块副本不足重新复制花了半小时。从那以后我每次做完 HDFS 操作都强制走一遍fsck加safemode检查再也没出现过数据丢失。希望这套流程能帮到你。本文还有配套的精品资源点击获取