简介:《大数据技术与应用》课程配套实验报告,面向高校大数据专业学生和Hadoop入门者。报告涵盖Linux基本操作、Hadoop安装配置、HDFS与MapReduce三大实验:从Shell常用命令、用户与文件权限管理、Linux目录结构,到Hadoop单机/伪分布式部署、core-site.xml等关键配置修改、HDFS读写流程和MapReduce编程模型,均有操作步骤记录,并梳理了实验过程中遇到的JDK下载配置、Hadoop编译、环境变量设置等常见问题及解决思路,可帮助读者减少重复踩坑。资源为PDF格式,共1个文件,压缩包大小约1.92MB,已有115人浏览学习。对需要完成同类实验报告、搭建Hadoop学习环境或巩固大数据基础操作的读者,这份报告可作为实验步骤参考和排错指南。
1. 大数据技术与应用实验报告,为什么我把 HDFS 当作实验主线
翻开《大数据技术与应用(微课视频版)》配套的实验报告 PDF,很多人第一反应是“视频里都讲过了,照着敲就行”。真打开虚拟机开始敲,才发现光是 SSH 免密登录就能卡掉一个下午,更别提 NameNode 格式化后 DataNode 失联这种黑匣子问题。这份实验报告想验证的其实不是 API 记得多熟,而是你能否在一台干净机器上把 Hadoop 生态从零拉起,让每个作业的输出目录里都长出文件。下面就把这份报告拆成一条可复现的路径:先选型、再搭环境、跑三个必修实验、最后排错——覆盖 HDFS、MapReduce、Hive 和 Spark 的完整链路。适合正在读数据科学与大数据技术专业、期末要交报告的同学,也适合想用最小成本亲手跑一遍大数据全链路的自学者。
2. 大数据实验技术栈:三套工件、两个计算层和一本原理书的定位
2.1 三套工件:HDFS、YARN、MapReduce 在实验报告里的分工
实验报告第一章往往从 HDFS 文件操作开始,这不是为了凑页数,而是因为整个 Hadoop 生态的计算都建立在“文件已经进了分布式存储”这个前提上。HDFS、YARN、MapReduce 三件套各有各的进程和职责:HDFS 管数据放哪,YARN 管作业排到哪,MapReduce 管数据怎么算。把这三件事拆开,后面看配置参数和排错日志才不会一头雾水。
| 组件 | 核心进程 | 实验报告里的角色 |
|---|---|---|
| HDFS | NameNode、DataNode、SecondaryNameNode | 上传数据、查看文件块分布、读写验证 |
| YARN | ResourceManager、NodeManager | 作业调度、查看 Application 状态、配置资源上限 |
| MapReduce | MapTask、ReduceTask | WordCount、倒排索引、排序等离线批处理实验 |
| Hive | metastore、HiveServer2 | 用 SQL 表达聚合统计,底层翻译成 MapReduce 或 Spark |
| Spark | Driver、Executor | 日志分析、迭代计算、RDD/DataFrame 加工 |
实验里最常出现的判断标准不是“命令背得熟”,而是 NameNode 的 Web UI 上能看到文件路径和块分布。伪分布式环境下,NameNode 监听 9870 端口,浏览器打开就能看到用户目录下每个文件的 Blocks 数量。实验报告里如果写了“数据已上传至 HDFS”,最好附一张这个页面的截图,比贴十行命令都管用。
MapReduce 在报告里的位置更偏向“理解 shuffle”。实验通常要你统计一段英文文本的词频,作业运行时可登录 ResourceManager 的 8088 页面,看 Map 阶段和 Reduce 阶段的进度条。我一般会建议学生在报告里写一句“shuffle 阶段洗牌了多少字节”,这句来自 Web UI 的真实数据,回答“MapReduce 为什么慢”这类追问时非常好用。
2.2 两个计算层:Hive 与 Spark 的选择,以及原理书怎么配合
Hive 和 Spark 的先后顺序在不同课程里不太一样,但我经手的教学配套里,绝大多数先讲 Hive 再讲 Spark。原因是 Hive 用 SQL 表达计算,学生不需要先掌握 RDD 的算子思维,就能把 GROUP BY 这类聚合跑通;Spark 再上难度,用 Scala 或 Python 写算子时,前面 SQL 实验的“输入输出语义”已经打下底子。这份实验报告 PDF 里的实验顺序如果也是先 Hive 后 Spark,那是合理的教学节奏。
在实验环境层面,Hive 默认的执行引擎是 MapReduce(Hive on MR),这意味着你在 Hive CLI 里敲一条 SELECT,底层会生成一个 MR 作业。Hive on Tez 或 Hive on Spark 能提速,但实验报告不必追求这个,伪分布式下数据量很小,执行引擎的差异看不出来。真正值得在报告里写的是:Hive 把 SQL 翻译成了什么作业、作业在 YARN 上花了多长时间、数据倾斜发生在哪一个 KEY 上。这些观察在原理类教材《大数据技术原理与应用(第四版)》里能找到理论解释,在那本书里读 HDFS 容错和 shuffle 机制,再回到实验报告里跑命令,是效率最高的组合。
如果学校还配了在线实验平台做对照练习,比如头歌的 Hadoop 系列实验,我的建议是把在线平台的题目当作“作业题”来刷,本地伪分布式环境当作“考场”来用。在线沙箱帮你把域名、内存、网络都包好了,学不到本机进程调度和端口占用这些真实经验;本地环境虽然配置起来费时间,但踩过一次坑胜过在线跑十次题。
3. 本地搭建一个可复现的大数据实验环境:最小命令与五个关键参数
3.1 为什么伪分布式是实验报告的最优解,而不是三节点集群
第一次做大数据实验就搭三个节点的读者,多半是看了生产环境架构图。但对一篇课程实验报告来说,三节点虚拟机是典型的自我感动:本机内存被三个 Ubuntu 撑满,YARN 的资源竞争反而让每个作业都慢一倍。常见做法是开一台 2 核 4G 的虚拟机,装 Ubuntu 20.04 或 22.04,跑 Hadoop 伪分布式模式。伪分布式下 NameNode、DataNode、ResourceManager、NodeManager 这四个进程都挤在同一台机器上,但 HDFS 的目录树、YARN 的调度、MapReduce 的 shuffle 全是真实走一遍的,区别只在于副本数必然是 1。
用虚拟机的另一个理由是快照后悔药。配置 Hadoop 前给虚拟机打一个快照,后面无论格式化错了目录还是把配置文件改乱,都能秒回初始状态。这比在物理机上反复卸载重装 Hadoop 要省心得多。实验报告的“实验环境”一节只需要写“Ubuntu 20.04 + Hadoop 3.3.x + JDK8,伪分布式部署”,评审老师不会因为你没起三节点而扣分,反而会认可环境描述清晰。
3.2 从零到五个进程的安装命令与五个必调参数
下面这组命令是我在干净 Ubuntu 虚拟机上跑通 Hadoop 的最小集合,每一步都对应一个常见的失败点。JDK 选 8 是因为 Hadoop 3.x 在 JDK 8 下最稳,OpenJDK 11 也能跑,但某些发行版的默认配置会触发 SSL 相关的兼容异常。
# 安装 JDK8、SSH 和 rsync # rsync 是 Hadoop 启动脚本的依赖,没有它 DataNode 进程会静默失败 sudo apt update && sudo apt install -y openjdk-8-jdk ssh rsync # 解压 Hadoop 到 /usr/local,并将属主改为当前用户 # archive.apache.org 有所有历史版本,stable 版本号和课程要求对齐即可 wget https://archive.apache.org/dist/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz sudo tar -xzf hadoop-3.3.6.tar.gz -C /usr/local sudo mv /usr/local/hadoop-3.3.6 /usr/local/hadoop sudo chown -R $USER /usr/local/hadoop # 配置 SSH 本地免密:伪分布式里所有节点都是 localhost ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keysJDK 的安装路径如果不确定,用update-alternatives --config java查看实际路径再写环境变量。下面这段追加到~/.bashrc里,Hadoop 的启动脚本会读取这些变量。
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 export HADOOP_HOME=/usr/local/hadoop export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin export HADOOP_CONF_DIR=/usr/local/hadoop/etc/hadoop配置文件在$HADOOP_HOME/etc/hadoop下,修改前先备份原始文件。核心的core-site.xml和hdfs-site.xml按下面设置,注意hadoop.tmp.dir一定不要用默认值。
<!-- core-site.xml --> <configuration> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/home/student/hadoop_tmp</value> </property> </configuration><!-- hdfs-site.xml --> <configuration> <property> <name>dfs.replication</name> <value>1</value> </property> </configuration>fs.defaultFS写成localhost:9000,NameNode 就能绑定到本地地址;hadoop.tmp.dir指向家目录下的固定路径,避免系统重启后/tmp被清空导致 NameNode 无法启动。dfs.replication在伪分布式下必须写 1,写 3 的话文件块永远处于 under-replicated 状态,Web UI 上会一直报黄色告警。
YARN 的资源配置是低配虚拟机最容易翻车的地方。物理内存只有 4G 时,默认的 NodeManager 内存上限会直接吃掉大半内存导致后续作业挤爆容器,建议按下面调整。
<!-- yarn-site.xml --> <configuration> <property> <name>yarn.nodemanager.resource.memory-mb</name> <value>2048</value> </property> <property> <name>yarn.scheduler.maximum-allocation-mb</name> <value>2048</value> </property> <property> <name>yarn.nodemanager.pmem-check-enabled</name> <value>false</value> </property> </configuration>yarn.scheduler.maximum-allocation-mb如果不跟着调,单个 container 的申请内存会超过 NodeManager 的可分配内存,作业永远卡在 ACCEPTED 状态。pmem-check-enabled设为 false 是关掉物理内存超限检查,这是低配机器跑 Hive 和 Spark 时 container 频繁被杀的头号原因。
初始化并启动,顺序不能颠倒:
# 格式化只在第一次初始化时执行,重复格式化会引发第 5 章的 DataNode 失联问题 hdfs namenode -format start-dfs.sh start-yarn.sh # 看到 NameNode、DataNode、SecondaryNameNode、ResourceManager、NodeManager 五个进程 jps验证存储层是否就绪:
hdfs dfsadmin -report | head -n 20 # 输出里出现 Live datanodes (1) 说明数据节点已注册到这步为止,一个可复现的 Hadoop 实验环境就立住了。浏览器打开http://localhost:9870能看到 NameNode 页面,打开http://localhost:8088能看到 YARN 的作业列表。实验报告的环境截图就拍这两个页面,比拍命令行更直观。
4. 三个必修实验的最小打通路径:WordCount、Hive 聚合与 Spark 日志分析
4.1 WordCount:用 Hadoop Streaming 五分钟跑出第一个作业
不少课程把 WordCount 的提交方式限定为“用 Java 写一个 MapReduce 作业”,但对实验报告来说,核心是让你理解 Map 阶段产出的键值对如何经过 shuffle 进入 Reduce。Java 版本要处理 Maven 编译和依赖,很容易让新手把时间耗在构建工具上。更快的路径是用 Hadoop Streaming:把 mapper 和 reducer 写成独立脚本,Hadoop 会把 stdin/stdout 作为数据通道。常见做法是用 Python 写脚本,代码如下。
#!/usr/bin/env python3 # mapper.py:逐行读取 stdin,把每个词输出为 “词\t1” 的键值对 import sys for line in sys.stdin: line = line.strip() if not line: continue for word in line.split(): print(f"{word}\t1")#!/usr/bin/env python3 # reducer.py:对相同 key 的 1 求和,输出词频 import sys from collections import Counter counts = Counter() for line in sys.stdin: try: word, count = line.strip().split("\t", 1) counts[word] += int(count) except ValueError: pass for word, count in counts.items(): print(f"{word}\t{count}")先把一段英文文本上传到 HDFS,再提交 Streaming 作业:
# 准备实验数据 hdfs dfs -mkdir -p /input hdfs dfs -put /home/student/book.txt /input/ # 提交作业:输出目录不能提前存在,否则作业直接失败 hadoop jar $HADOOP_HOME/share/hadoop/tools/lib/hadoop-streaming-*.jar \ -D mapreduce.job.reduces=1 \ -mapper "python3 /home/student/lab/mapper.py" \ -reducer "python3 /home/student/lab/reducer.py" \ -input /input/book.txt \ -output /output/wc_resultStreaming 作业本身是一个 Java 进程,它把 mapper.py 和 reducer.py 当作外部程序调用。-D mapreduce.job.reduces=1强制只有一个 ReduceTask,这样输出目录里只有一个part-00000文件,实验报告截图时路径清晰。作业运行中可以在 8088 页面看到完整的日志,如果 mapper 脚本报错,点开对应 container 的 stderr 就能看到 Python 的 traceback,不用瞎猜。
4.2 Hive 聚合:从 CREATE TABLE 到 GROUP BY 的完整链路
Hive 实验的价值在于把 SQL 语义“翻译”成 MapReduce 作业。建一张销售表,导入本地文件,再做城市维度聚合,这组操作在实验报告里能体现三条知识:Hive 表的存储格式、LOAD DATA 的文件移动语义、GROUP BY 变成 MR 作业的过程。
-- 建库建表:TEXTFILE 是最直观的存储格式,适合实验报告展示 CREATE DATABASE IF NOT EXISTS lab; USE lab; CREATE TABLE IF NOT EXISTS sales ( dt STRING, city STRING, amount DOUBLE ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' STORED AS TEXTFILE; -- LOCAL 表示从本地文件系统导入,导入后文件会进入 Hive 表目录 LOAD DATA LOCAL INPATH '/home/student/sales.txt' INTO TABLE sales; -- 城市维度聚合统计,按订单金额倒序输出前 10 个城市 SELECT city, COUNT(*) AS order_cnt, ROUND(SUM(amount), 2) AS total_amount FROM sales GROUP BY city ORDER BY total_amount DESC LIMIT 10;这里最容易翻车的两个点,一个是FIELDS TERMINATED BY '\t'必须和导入文件真实的分隔符一致。很多同学拿一个 CSV 文件导入,表定义里却写的是 tab,结果整张表读出来只有一列。另一个是 CSV 自带表头,导入后 SELECT COUNT(*) 会比文件行数少一行或者把列名当脏数据,下一章会给出完整排查办法。
Hive 3.x 在本地跑实验时默认用 Derby 作为 metastore,只允许单会话访问。打开多个 Hive CLI 窗口做操作时,第二个窗口会在初始化时报数据库锁错误。实验报告阶段不要开多窗口,一条 SQL 一条 SQL 地执行即可,避免被这个噪声干扰。要验证“GROUP BY 真的变成了 MR 作业”,可以在执行 SELECT 时看屏幕上出现的 MapReduce 进度条,把它截到报告里,比任何文字描述都直观。
4.3 Spark 日志分析:用 PySpark 算 Top IP,并证明它比 MapReduce 省一个排序
Spark 实验在课程里通常用来讲“内存计算”和“DAG 执行”。第三个实验我一般选 Web 访问日志分析:计算 404 状态码出现次数最多的十个 IP。这道题既涉及数据清洗,又涉及分组聚合,还能对比 Hive 的 SQL 写法与 Spark 的算子写法差异。
#!/usr/bin/env python3 # spark_log.py:读取 access.log,统计 404 请求最多的 Top10 IP from pyspark.sql import SparkSession spark = (SparkSession.builder .appName("web_log_analysis") .getOrCreate()) # 读取 HDFS 上的日志文件,得到 RDD[String] logs = spark.sparkContext.textFile("hdfs://localhost:9000/input/access.log") def parse_line(line): # combined 格式的 access.log,状态码在倒数第二列 parts = line.split(" ") if len(parts) < 7: return None ip = parts[0] status = parts[-2] return (ip, status) # 过滤出 404 请求,映射为 (IP, 1),聚合后排序取出 Top10 records = logs.map(parse_line).filter(lambda x: x is not None and x[1] == "404") top_ips = (records .map(lambda x: (x[0], 1)) .reduceByKey(lambda a, b: a + b) .sortBy(lambda x: x[1], ascending=False) .take(10)) for ip, cnt in top_ips: print(f"{ip}\t{cnt}") spark.stop()提交到 YARN:
# --master 必须写 yarn,写 local 的话只在本地单线程跑,实验报告无法证明集群调度 # executor-memory 设 1g 而不是更大,伪分布式下 Driver 和 Executor 共享同一台机器的内存 spark-submit \ --master yarn \ --deploy-mode client \ --executor-memory 1g \ --num-executors 1 \ /home/student/lab/spark_log.py如果提交时报AuxService: shuffle相关的错误,需要回到yarn-site.xml里检查yarn.nodemanager.aux-services是否配置了mapreduce_shuffle,Spark on YARN 依赖这个辅助服务来传输 shuffle 数据。reduceByKey会在本地做一次 combine,这正是 Spark 对比 MapReduce 在 shuffle 上的主要优势——MapReduce 的 combine 是可选的,而 Spark 的 reduceByKey 天然自带这个优化。实验报告的“结果分析”一节写这一点,比写“Spark 快”更有说服力。
5. 实验排错避坑:五个典型事故的现象、原因与解决
5.1 SSH 免密失效导致 Hadoop 启动卡在 localhost
现象:按照教程配置完ssh-keygen和authorized_keys,执行ssh localhost仍然提示输入密码,start-dfs.sh在连接 localhost 时卡住不动。
原因:SSH 服务对密钥文件的权限非常敏感。~/.ssh目录权限如果是 755,或者authorized_keys文件权限是 644,sshd 为了安全会直接忽略这个密钥文件。这个问题很玄学,因为终端不报错,只是每次连接都退回密码认证。
解决:执行chmod 700 ~/.ssh和chmod 600 ~/.ssh/authorized_keys,重新试ssh localhost。如果还不行,在虚拟机上执行sudo systemctl status sshd确认 sshd 服务本身在运行,再查看/var/log/auth.log里的Authentication refused条目定位原因。
5.2 格式化 NameNode 后 DataNode 失联
现象:执行了hdfs namenode -format之后,jps显示 DataNode 进程还在,但hdfs dfsadmin -report报告Live datanodes (0),NameNode Web UI 上也看不到任何节点。
原因:namenode -format会重新生成 clusterID,而 DataNode 的current/VERSION文件里记录的是旧 clusterID。DataNode 启动时会拿自己的 clusterID 和 NameNode 的 clusterID 比对,不一致就拒绝注册。
解决:先停掉所有 Hadoop 进程,删除hadoop.tmp.dir目录下dfs/data和dfs/name两个子目录,再重新执行hdfs namenode -format和start-dfs.sh。另一种做法是手工把 DataNode VERSION 文件里的 clusterID 改成和 NameNode 一致,但实验报告阶段不建议,重来一次更快。记住:格式化不是后悔药,它清空的不只是 name 目录,还包括所有元数据。
5.3 WordCount 提交后作业卡在 ACCEPTED 状态
现象:作业提交到 YARN 后,8088 页面上 Application 状态一直是ACCEPTED,就是不进入RUNNING,日志里也没有明确报错。
原因:虚拟机物理内存只有 4G,YARN 可调度的内存被配置得太高。单个 container 申请内存超过 NodeManager 剩余内存,资源调度器就一直等待。这个现象在低配机器上重复出现,本质是yarn-site.xml里两个内存参数没有同步调整。
解决:把yarn.nodemanager.resource.memory-mb和yarn.scheduler.maximum-allocation-mb都改为 2048,重启 YARN。如果机器内存实在紧张,建议关闭宿主机上不必要的进程,再给虚拟机多分 1G 内存。实验报告里写“观察到资源不足导致作业排队”并附上修改后的参数值,这本身就是加分项。
5.4 Hive 统计结果总比文件行数少一行
现象:导入一个 100 行的 CSV 文件,SELECT COUNT(*) FROM sales返回 99,排查半天也没发现数据过滤逻辑有问题。
原因:CSV 文件自带列名表头,LOAD DATA 导入时不会自动跳过第一行,表头被当成普通数据加载。如果表名和列名刚好能对应,这行脏数据不会被报错,只会让统计结果少一行。
解决:建表时在 TBLPROPERTIES 里声明跳过表头行:
CREATE TABLE IF NOT EXISTS sales ( dt STRING, city STRING, amount DOUBLE ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' STORED AS TEXTFILE TBLPROPERTIES ("skip.header.line.count" = "1");注意FIELDS TERMINATED BY ','这次要和文件真实分隔符一致,前面提到过这个坑。验证方式是在导入前用hdfs dfs -cat查看 HDFS 上文件的原始内容,确认第一行确实是列名再做判断。
5.5 HDFS 进入安全模式,上传文件被拒绝
现象:执行hdfs dfs -put时提示Name node is in safe mode,文件无法写入,但jps显示进程都在。
原因:NameNode 刚启动或副本率不足时会自动进入 safe mode,只读不写。伪分布式下最常见的原因是磁盘空间不足,或者dfs.replication配置为 3 但只有 1 个 DataNode,文件块始终无法达到副本要求。
解决:先执行hdfs dfsadmin -safemode leave临时退出,再用hdfs dfsadmin -report检查磁盘和副本状态。长期对策是把dfs.replication改回 1,并清理虚拟机磁盘空间。这里不要只记命令,要看副本率的上下文——实验报告里写“调整副本数至 1 以适配伪分布式环境”,比只写一条绕开问题的命令更专业。
6. 用一条自检命令验证全链路,并补一个数据量翻倍测试
6.1 把五层验证串成一个可以放进报告附录的脚本
实验报告写成厚厚一沓截图,不如附一段环境自检脚本。下面这段脚本按 HDFS、YARN、Hive、Spark 的顺序检查每层是否就绪,全部通过后输出 ALL PASS。把这个脚本放进报告附录,评审老师能在你离开后复现环境,这比任何截图都更能说明实验是真实的。
#!/bin/bash set -e echo "== HDFS ==" hdfs dfsadmin -report | grep "Live datanodes" || exit 1 echo "== YARN ==" yarn node -list 2>/dev/null | grep -q "localhost" || exit 1 echo "== WORDCOUNT 输出 ==" hdfs dfs -ls /output/wc_result | grep part-00000 || exit 1 echo "== HIVE ==" hive -e "SELECT COUNT(*) FROM lab.sales;" | grep -E "^[0-9]+$" || exit 1 echo "== SPARK ==" spark-submit --master yarn --deploy-mode client \ --executor-memory 1g --num-executors 1 \ /home/student/lab/spark_log.py | grep -q "404" || exit 1 echo "ALL PASS"脚本四段分别验证存储层、调度层、离线批处理和 SQL 翻译层。写报告时把这段脚本放在“实验环境与验证”一节,再把执行结果截图贴上,整个实验的可信度会明显提升。
6.2 数据量翻倍时该看什么指标
最后一个建议:把日志数据复制成两份再跑一次 Spark 作业,把两次作业的运行时间做成一行对比。这个测试不需要新的技术,只需要一条hdfs dfs -cp命令,却能验证你对分布式计算的直觉——数据翻倍后作业时间是否也会翻倍,Map 阶段并行度有没有生效,shuffle 数据量增加了多少。我当年交 WordCount 报告时只贴了一张part-00000的截图,被老师一个“数据分布在哪”问住。后来养成了每次实验都跑一遍hdfs fsck /output -files -blocks看块分布的习惯,回答这类问题再也没虚过。希望这条习惯对你也有用。
本文还有配套的精品资源,点击获取