Hadoop伪分布式数据云盘项目实战:从HDFS存储到MapReduce分析
简介这是一套面向高校计算机相关专业学生的Hadoop大数据开发实战项目资料以数据云盘系统为业务场景适合用作课程设计、期末大作业或毕业设计参考也便于新手通过完整项目理解大数据开发流程。压缩包共126个文件约58.11MB以32个Java源文件为核心配合10个JSP页面、19个JavaScript脚本、11个CSS样式及10个XML配置另有jar依赖、properties配置、字体图标与图片资源构成一套可部署运行的Web应用工程。项目代码注释较为完整功能覆盖数据云盘的核心业务界面美观、操作简单、管理便捷具有较高的实际应用价值。目前已有1153人学习下载说明其参考热度较高。下载后按文档说明简单部署即可运行既能帮助读者快速搭建可演示的系统也便于对照源码梳理模块划分、理解前后端交互与大数据组件集成思路为课程答辩或后续二次开发提供扎实基础。1. 数据云盘项目到底在练什么从 Hadoop 伪分布式到可演示的网盘后端很多人第一次看到「Hadoop 大数据开发项目实战数据云盘项目」这个标题会以为它只是把文件传到 HDFS 上就完事了。真动手做一遍才发现它其实是一条完整的链路用户在前端上传文件后端把文件写进 HDFS元数据落到 MySQL再通过 MapReduce 或 Spark 做文件统计、去重、容量分析最后还要有一套能跑起来的文档说明让答辩老师或者面试官三分钟看懂你做了什么。这个项目适合两类人一类是大数据课程设计、毕业设计需要交出一个完整可演示系统的同学另一类是想从「只会敲 hadoop fs -put」进阶到「能说清 NameNode、DataNode、ResourceManager 怎么协作」的开发者。它不追求高并发生产级但要求你真正理解 HDFS 的读写路径、YARN 的任务调度以及一个云盘类应用的最小闭环。下面我按自己带人做这个项目的顺序把选型、搭建、编码、排错和进阶验证拆开讲。2. 先定架构再动手数据云盘项目的最小可行技术栈2.1 为什么选 Hadoop 伪分布式而不是单机模式单机模式跑 MapReduce 用的是本地文件系统看不到 DataNode 的块副本机制也测不出 YARN 的资源调度。伪分布式虽然只在一台机器上但 NameNode、DataNode、ResourceManager、NodeManager 都是独立进程HDFS 的块大小、副本数、RPC 端口全部按真实集群的方式工作。对于数据云盘项目文件上传后要能通过 Web 界面看到块分布和副本状态伪分布式是成本最低又能体现「大数据」特征的选择。常见做法是开发阶段用伪分布式答辩演示前如果机器够再扩成三节点完全分布式代码基本不用改只改 core-site.xml 里的 fs.defaultFS 指向。2.2 数据云盘的功能模块拆解一个能拿得出手的数据云盘至少包含四个模块。第一是用户模块注册登录、配额管理元数据存 MySQL。第二是文件模块上传、下载、删除、重命名、目录树展示文件实体存 HDFS。第三是分析模块用 MapReduce 统计每个用户的文件总大小、文件类型分布、重复文件检测。第四是回收站删除的文件先移到 HDFS 的 /trash 目录保留七天再物理删除。这四个模块里文件模块和分析模块是 Hadoop 真正发挥作用的地方也是答辩时最容易被追问的点。2.3 环境版本与依赖对照表版本不统一是新手翻车最多的地方。Hadoop 2.x 和 3.x 的端口、配置文件、API 都有差异Java 版本也卡得很死。下面这张表是我在多次搭建后固定下来的组合能避开大部分兼容性问题。组件推荐版本关键说明JDK1.8Hadoop 3.x 对 JDK 11 支持不完整1.8 最稳Hadoop3.2.4伪分布式配置成熟Web UI 端口 9870MySQL5.7 或 8.0存元数据注意时区和驱动包版本Maven3.6管理 Hadoop 客户端依赖Spring Boot2.5.x后端框架和 JDK 1.8 匹配提示不要用最新版 Hadoop 4.x 做课程项目生态工具链还没跟上遇到问题搜到的答案大多是 2.x/3.x 的排查成本极高。2.4 从零开始安装 Hadoop 伪分布式的关键命令安装步骤网上很多我只列容易出错的几个环节。先确认 ssh 免密登录本机已经配好否则 start-dfs.sh 会反复提示输入密码。然后解压、配环境变量、改五个配置文件。核心是 core-site.xml、hdfs-site.xml、mapred-site.xml、yarn-site.xml 和 workers。# 解压并设置环境变量 tar -zxvf hadoop-3.2.4.tar.gz -C /opt/ echo export HADOOP_HOME/opt/hadoop-3.2.4 /etc/profile echo export PATH$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin /etc/profile source /etc/profile # 配置 ssh 免密 ssh-keygen -t rsa -P -f ~/.ssh/id_rsa cat ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys # 格式化 NameNode只执行一次 hdfs namenode -format # 启动 HDFS 和 YARN start-dfs.sh start-yarn.sh # 验证进程 jps逻辑说明hdfs namenode -format会生成 fsimage只在首次搭建时执行重复执行会导致 clusterID 不一致DataNode 起不来。jps应该看到 NameNode、DataNode、SecondaryNameNode、ResourceManager、NodeManager 五个进程。参数说明core-site.xml 里 fs.defaultFS 设为 hdfs://localhost:9000hdfs-site.xml 里 dfs.replication 设为 1因为伪分布式只有一个 DataNode设成 3 会一直报副本不足。2.5 数据云盘后端接入 HDFS 的 Java API 写法Spring Boot 项目里操作 HDFS核心是拿到 FileSystem 对象。不要每次请求都 new 一个 Configuration连接开销很大做成单例 Bean 或者用连接池。下面是一个上传文件的最小示例。// HdfsService.java Component public class HdfsService { private FileSystem fileSystem; PostConstruct public void init() throws IOException { Configuration conf new Configuration(); // 指向伪分布式 NameNode 地址 conf.set(fs.defaultFS, hdfs://localhost:9000); // 避免权限问题本地测试用 System.setProperty(HADOOP_USER_NAME, root); this.fileSystem FileSystem.get(conf); } public void upload(MultipartFile file, String hdfsPath) throws IOException { // 创建目标路径的父目录 Path path new Path(hdfsPath); if (!fileSystem.exists(path.getParent())) { fileSystem.mkdirs(path.getParent()); } // 写入 HDFS try (FSDataOutputStream out fileSystem.create(path); InputStream in file.getInputStream()) { IOUtils.copyBytes(in, out, 4096, false); } } PreDestroy public void close() throws IOException { if (fileSystem ! null) { fileSystem.close(); } } }逻辑说明FileSystem.get(conf)会根据 fs.defaultFS 自动选择 HDFS 实现。fileSystem.create(path)返回 FSDataOutputStream默认覆盖已存在文件如果要追加用 append 方法。IOUtils.copyBytes的第三个参数是缓冲区大小4096 是保守值大文件可以调到 8192 或 16384。参数说明HADOOP_USER_NAME在 Windows 开发环境下必须设否则会报 Permission deniedLinux 下如果当前用户就是 Hadoop 启动用户可以省略。3. 把文件写进 HDFS 之后元数据、分块与 MapReduce 统计的落地细节3.1 HDFS 写文件的真实路径与元数据落库时机很多同学以为文件上传就是调一次 API 就完事实际上 HDFS 的写入分两步客户端先向 NameNode 请求创建文件NameNode 在内存里记录元数据并返回一个 DataNode 列表客户端再把数据切成块逐个写到 DataNode 的管道里。数据云盘项目里MySQL 存的元数据文件名、大小、上传时间、HDFS 路径应该在 HDFS 写入成功之后再落库否则 HDFS 写失败但数据库有记录就会出现「文件列表里有但下载 404」的经典 bug。我一般用先写 HDFS 再写 MySQL 的顺序并在 MySQL 写入失败时补偿删除 HDFS 文件。3.2 用 MapReduce 统计用户文件容量分布分析模块是体现「大数据」的关键。一个简单的 MapReduce 任务是统计每个用户目录下的文件总大小。输入是 HDFS 上 /userdata 下的所有文件输出是用户 ID 和总字节数。下面给出 Mapper 和 Reducer 的核心代码。// SizeMapper.java public class SizeMapper extends MapperLongWritable, Text, Text, LongWritable { Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { // 输入格式每行是 用户ID,文件路径,文件大小 String[] fields value.toString().split(,); if (fields.length 3) { context.write(new Text(fields[0]), new LongWritable(Long.parseLong(fields[2]))); } } } // SizeReducer.java public class SizeReducer extends ReducerText, LongWritable, Text, LongWritable { Override protected void reduce(Text key, IterableLongWritable values, Context context) throws IOException, InterruptedException { long total 0; for (LongWritable val : values) { total val.get(); } context.write(key, new LongWritable(total)); } }逻辑说明Mapper 按逗号切分把用户 ID 作为 key文件大小作为 value 输出。Shuffle 阶段会把同一用户的数据拉到同一个 Reducer。Reducer 累加后输出总大小。参数说明如果输入文件很大可以在 Driver 里设置job.setNumReduceTasks(3)来并行但伪分布式下建议设为 1避免资源竞争。输出路径不能已存在否则 Job 会直接抛 FileAlreadyExistsException。3.3 重复文件检测的 MapReduce 实现思路数据云盘里用户可能上传同一份文件多次检测重复可以按文件内容的 MD5 做 key。Mapper 读文件时计算 MD5输出 MD5, 文件路径。Reducer 里如果 values 数量大于 1就说明有重复。这个任务比容量统计更耗 IO因为要读文件内容而不是元数据。常见做法是先用 MySQL 里存的文件大小做粗筛只对大小相同的文件计算 MD5能减少大量计算。3.4 回收站机制的 HDFS 实现HDFS 本身有 Trash 机制但默认关闭。在 core-site.xml 里设置fs.trash.interval10080单位分钟七天和fs.trash.checkpoint.interval0然后重启 HDFS。之后用hadoop fs -rm删除的文件会移到 /user/root/.Trash 下而不是直接删掉。数据云盘项目里前端点删除时调用的就是带 Trash 的删除 API用户可以在回收站里恢复。注意FileSystem.delete(path, false)是直接删FileSystem.delete(path, true)才是移入回收站这个布尔参数很容易写反。4. 避坑与排查数据云盘项目里最容易翻车的五个地方4.1 DataNode 启动后立刻消失现象jps看到 DataNode 进程一闪而过或者根本没有。原因多次执行hdfs namenode -format导致 NameNode 和 DataNode 的 clusterID 不一致DataNode 拒绝注册。解决删掉所有节点的 data 目录dfs.datanode.data.dir 配置的路径和 NameNode 的 name 目录重新格式化一次然后只启动一次。血泪经验是格式化命令一辈子只跑一次除非你确定要清空集群。4.2 Web UI 打不开 9870 端口现象浏览器访问 http://localhost:9870 超时。原因Hadoop 3.x 的 NameNode Web UI 端口从 50070 改成了 9870很多老教程还在写 50070。另外防火墙可能没放行。解决确认 hdfs-site.xml 里 dfs.namenode.http-address 的值用netstat -tlnp | grep 9870看端口是否监听。如果是云服务器安全组也要放行。4.3 MapReduce 任务卡在 map 0% reduce 0%现象Job 提交后一直不动日志里没有明显报错。原因YARN 的 NodeManager 没启动或者 mapred-site.xml 里 mapreduce.framework.name 没设成 yarn。解决jps确认 NodeManager 在检查 mapred-site.xml 和 yarn-site.xml 的配置是否配对。另一个常见原因是内存不够在 yarn-site.xml 里把 yarn.nodemanager.resource.memory-mb 调小到 1024 试试。4.4 Java API 报 Could not obtain block现象下载文件时抛异常提示某个 block 找不到。原因文件上传后 DataNode 还没完成块复制客户端立刻去读或者 DataNode 挂了导致副本丢失。解决上传后加一个短暂的等待或者用fileSystem.exists()确认文件可见后再返回给前端。如果是副本丢失用hdfs fsck /path -files -blocks查看块状态必要时从其他副本恢复。4.5 MySQL 元数据和 HDFS 实际文件不一致现象文件列表里显示有某个文件但下载时报 404。原因HDFS 写入成功但 MySQL 插入失败或者反过来。解决在 Service 层用事务包住 MySQL 操作HDFS 操作放在事务提交前如果 MySQL 回滚就补偿删除 HDFS 文件。更稳妥的做法是加一个定时对账任务每天扫描 HDFS 和 MySQL把不一致的记录清理掉。5. 让项目从「能跑」到「能讲」文档说明与答辩演示的进阶技巧文档说明不是把代码注释复制一遍而是要讲清楚三件事系统架构图、核心流程时序、关键配置参数。我一般会在文档里放一张手绘的架构图标出浏览器、Spring Boot、MySQL、HDFS、YARN 五个框箭头标清数据流向。然后挑「文件上传」和「容量统计」两个流程用文字加序号写清每一步调用了什么、参数是什么、失败怎么处理。答辩时老师最爱问的是「你的项目和直接存本地磁盘有什么区别」标准答案是HDFS 有副本机制、能横向扩展、支持 MapReduce 并行分析本地磁盘做不到。演示环节有一个技巧提前准备好一个 100MB 左右的测试文件现场上传然后立刻在 Web UI 上看块分布再跑一次容量统计的 MapReduce让老师看到 Job 从提交到完成的全过程。这比只展示一个静态页面有说服力得多。另外把hdfs fsck /userdata -files -blocks -locations的输出截图放进文档能证明你确实理解块和副本的概念。验证项目是否真正跑通我习惯用三个检查点。第一上传一个文件后用hadoop fs -ls /userdata/用户名能看到文件且副本数为 1。第二删除文件后在 /user/root/.Trash 下能找到七天后自动清理。第三MapReduce 统计结果和 MySQL 里累加的文件大小一致。这三个点过了项目基本就没有暗病。最后一个习惯每次改完配置文件先stop-dfs.sh stop-yarn.sh再重新启动不要热改配置。Hadoop 对配置的加载是启动时一次性的热改不生效还容易让人怀疑人生。希望帮到你。本文还有配套的精品资源点击获取