ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

大数据实验从零上手:Hadoop伪分布式搭建、HDFS命令与MapReduce编程实战

大数据实验从零上手:Hadoop伪分布式搭建、HDFS命令与MapReduce编程实战 简介这份实验报告PDF面向大数据技术入门学习者对应《大数据技术原理与应用》课程系统整理了Linux基本操作与Hadoop平台使用的实验过程与结果分析。内容覆盖Linux发展历史、Shell常用命令与快捷键、用户及文件权限管理、目录结构与文件操作以及Hadoop单机模式与伪分布式部署、配置文件修改、HDFS读写原理、NameNode与DataNode角色、MapReduce的Map与Reduce阶段工作机制等核心知识点并记录了实验环境搭建中Java JDK配置、SSH免密登录、Hadoop编译等常见问题的排查思路。资源包共1个PDF文件大小约1.92MB结构完整、便于打印或对照复习。目前已有114人学习下载适合正在完成课程实验、需要参考实验步骤与结果分析模板的高校学生也可作为梳理Linux与Hadoop基础操作的复习材料。1. 从一份实验报告说起大数据技术栈到底该怎么上手很多人第一次接触大数据是从课程实验报告开始的。标题里这份《大数据技术与应用》微课视频版实验报告背后对应的其实是一整套从零搭建的动手路径Linux 环境准备、Hadoop 伪分布式搭建、HDFS 常用命令、MapReduce 编程实例最后落到一个综合实训。它解决的不是大数据是什么这种概念问题而是我手上只有一台电脑怎么把这一整套东西跑起来、跑通、跑出结果。适合谁看在校学生做课程设计、毕业设计转行的人想补一套能写进简历的实操经验还有已经会写 SQL 但没碰过分布式存储和计算的人。这篇笔记按实验报告里最常见的推进顺序拆开先把 Linux 和 Hadoop 环境立住再讲 HDFS 的读写流程和命令然后进 MapReduce 编程最后给一套综合实训的落地思路和排错清单。每一步都给可复制的命令和参数说明新手能跟着走熟手能对照边界。2. 环境先立住Linux 准备与 Hadoop 伪分布式搭建2.1 为什么实验环境几乎都选 Linux 加伪分布式Hadoop 原生就跑在 Linux 上Windows 上要么用 WSL要么用 Docker 镜像坑多且和教材对不上。伪分布式Pseudo-Distributed指的是所有守护进程——NameNode、DataNode、ResourceManager、NodeManager——都跑在同一台机器上但走的是完整的分布式通信逻辑。它和单机模式Standalone的区别很关键单机模式用的是本地文件系统根本不碰 HDFS伪分布式才会真正启动 HDFS 和 YARN你写的 MapReduce 程序才会走完整的提交、调度、执行链路。选它的理由很实际一台 8G 内存的笔记本就能跑实验报告里的所有环节——HDFS 命令、MapReduce 作业、甚至和 ZooKeeper 整合——都能覆盖。生产集群部署策略那是另一回事实验阶段先把伪分布式吃透理解清楚每个进程干什么后面上真集群只是把进程分散到多台机器。Linux 发行版选哪个教材一般用 CentOS 或 Ubuntu。现在 CentOS 停更了我一般建议用 Ubuntu 22.04 LTS 或者 Rocky Linux命令体系和教材基本兼容。虚拟机安装 Linux 偶尔会遇到蓝屏多半是虚拟化没在 BIOS 里打开或者 Hyper-V 和 VMware 冲突这个先排查掉。2.2 从零安装 Hadoop 的关键步骤先确认 Java 环境Hadoop 3.x 需要 JDK 8 或 11# 检查 Java 版本没有就装 java -version sudo apt update sudo apt install openjdk-8-jdk -y # 配置 JAVA_HOME写进环境变量 echo export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64 ~/.bashrc echo export PATH$JAVA_HOME/bin:$PATH ~/.bashrc source ~/.bashrc逻辑说明Hadoop 的所有守护进程都是 Java 进程JAVA_HOME 必须能被 Hadoop 启动脚本读到否则启动时报 JAVA_HOME is not set。参数上JDK 8 兼容性最好JDK 11 在 Hadoop 3.3 之后也支持但教材实验用 8 最稳。下载并解压 Hadoop配置 SSH 免密伪分布式必须否则启动脚本会反复要密码# 下载 Hadoop版本按教材这里以 3.3.6 为例 wget https://archive.apache.org/dist/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz tar -zxvf hadoop-3.3.6.tar.gz -C /usr/local/ mv /usr/local/hadoop-3.3.6 /usr/local/hadoop # 配置 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 # 测试能免密进去就对了接下来是核心配置文件一共要改五个都在$HADOOP_HOME/etc/hadoop/下配置文件关键参数作用core-site.xmlfs.defaultFShdfs://localhost:9000指定默认文件系统为 HDFScore-site.xmlhadoop.tmp.dir/usr/local/hadoop/tmp临时目录必须手动建hdfs-site.xmldfs.replication1伪分布式只有一份副本mapred-site.xmlmapreduce.framework.nameyarnMapReduce 跑在 YARN 上yarn-site.xmlyarn.nodemanager.aux-servicesmapreduce_shuffleNodeManager 的辅助服务# 建临时目录忘了这步启动必失败 mkdir -p /usr/local/hadoop/tmp # 格式化 NameNode只能执行一次 hdfs namenode -format # 启动 HDFS 和 YARN start-dfs.sh start-yarn.sh # 验证进程 jpsjps应该看到 NameNode、DataNode、SecondaryNameNode、ResourceManager、NodeManager 五个进程。少一个就去看对应日志日志在$HADOOP_HOME/logs/下。提示hdfs namenode -format只能执行一次。重复格式化会导致 clusterID 不一致DataNode 起不来报 Incompatible clusterIDs。真格式化了就把 tmp 目录清掉重新来。2.3 参数怎么改、失败看什么dfs.replication在伪分布式下必须设 1设 3 会一直报副本不足的警告因为只有一个 DataNode。hadoop.tmp.dir默认在 /tmp 下重启机器可能被清掉导致集群数据丢失所以一定要改到持久目录。启动失败最常见的三类一是 JAVA_HOME 没配好看hadoop-env.sh里有没有显式指定二是 SSH 免密没配通start-dfs.sh会卡在输入密码三是端口占用9000、8088、9870 这几个端口被别的服务占了。排查顺序就是先jps看进程再翻 logs 目录下对应组件的 .log 文件报错信息一般很直白。3. HDFS 读写流程与常用命令别只会 put 和 get3.1 HDFS 写入数据的流程到底走了几步理解写入流程排错时才知道卡在哪。客户端调FileSystem.create()写文件时背后是这样一条链路第一步客户端向 NameNode 发起创建请求NameNode 检查路径是否存在、权限够不够通过后在命名空间里记一条新文件记录但此时不分配任何数据块。第二步客户端开始写数据数据先被切成块默认 128MB每个块向 NameNode 申请一组 DataNode 位置NameNode 按机架感知策略返回一个管道pipeline比如三副本就是 DN1→DN2→DN3。第三步客户端把数据包发给 DN1DN1 收到后转发给 DN2DN2 再转发给 DN3形成流水线。第四步每个 DN 写完落盘后逐级回传 ack全部成功客户端才继续写下一个包。第五步文件写完客户端调close()NameNode 才把元数据落盘。读流程相对简单客户端向 NameNode 请求文件块位置NameNode 返回按网络距离排序的 DataNode 列表客户端直接连最近的 DataNode 读数据读完一个块再读下一个。NameNode 不参与实际数据传输这也是 HDFS 能扛高吞吐的原因。3.2 hdfs 常用命令与基本操作命令行是实验报告里出现频率最高的部分这些命令必须练到不用查# 查看 HDFS 根目录 hdfs dfs -ls / # 创建目录 hdfs dfs -mkdir -p /user/student/input # 上传本地文件到 HDFS hdfs dfs -put localfile.txt /user/student/input/ # 从 HDFS 下载到本地 hdfs dfs -get /user/student/input/localfile.txt ./ # 查看文件内容 hdfs dfs -cat /user/student/input/localfile.txt # 查看文件大小和副本信息 hdfs dfs -ls -h /user/student/input/ # 删除文件-r 删目录 hdfs dfs -rm -r /user/student/input/localfile.txt # 查看磁盘使用情况 hdfs dfs -df -h参数说明-put和-copyFromLocal等价-get和-copyToLocal等价教材里两种写法都出现过。-ls -h的-h是把字节数转成人类可读的 KB/MB/GB。-rm -r删目录必须带-r否则报错。还有一个容易被忽略的命令hdfs fsck用来检查文件系统健康度# 检查整个文件系统 hdfs fsck / # 检查指定文件列出块和副本位置 hdfs fsck /user/student/input/localfile.txt -files -blocks -locationsfsck会报缺失块、副本不足、块损坏等问题。这里要提醒一句hdfs fsck这类管理接口如果暴露在公网且没做权限控制是存在未授权访问风险的实验环境无所谓但任何对外提供服务的集群都必须配好 Kerberos 或至少限制访问来源这是运维底线。3.3 读写流程里最容易翻车的两个点第一个是小文件问题。HDFS 每个文件、每个块在 NameNode 内存里都占约 150 字节元数据上传几万个几 KB 的小文件NameNode 内存会被吃光。实验里数据量小感觉不到真上生产就是灾难。常见做法是先合并再上传或者用 HAR 归档。第二个是副本因子和块大小的配合。块大小默认 128MB改大改小要看场景块大寻址开销小但单块失败重传代价高块小并行度高但 NameNode 压力大。伪分布式下副本设 1别照抄生产的三副本配置否则一直报副本不足。4. MapReduce 编程实例从 WordCount 到自定义排序4.1 MapReduce 的执行模型和编程套路MapReduce 把计算拆成 Map、Shuffle、Reduce 三个阶段。Map 阶段读输入分片每行调一次 map 函数输出键值对Shuffle 阶段把相同 key 的数据拉到同一个 Reduce 节点中间包含分区、排序、合并Reduce 阶段对每个 key 的 value 列表做聚合。写一个 MapReduce 程序套路固定Mapper 类继承MapperKEYIN, VALUEIN, KEYOUT, VALUEOUT重写map()Reducer 类继承ReducerKEYIN, VALUEIN, KEYOUT, VALUEOUT重写reduce()Driver 里配 Job 的输入输出路径、Mapper、Reducer 类、输出键值类型。4.2 WordCount 完整代码与运行import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.Mapper; import org.apache.hadoop.mapreduce.Reducer; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import java.io.IOException; import java.util.StringTokenizer; public class WordCount { // Mapper每行文本切词输出 单词, 1 public static class TokenizerMapper extends MapperObject, Text, Text, IntWritable { private final static IntWritable one new IntWritable(1); private Text word new Text(); public void map(Object key, Text value, Context context) throws IOException, InterruptedException { StringTokenizer itr new StringTokenizer(value.toString()); while (itr.hasMoreTokens()) { word.set(itr.nextToken()); context.write(word, one); } } } // Reducer对相同单词的计数求和 public static class IntSumReducer extends ReducerText, IntWritable, Text, IntWritable { private IntWritable result new IntWritable(); public void reduce(Text key, IterableIntWritable values, Context context) throws IOException, InterruptedException { int sum 0; for (IntWritable val : values) { sum val.get(); } result.set(sum); context.write(key, result); } } public static void main(String[] args) throws Exception { Configuration conf new Configuration(); Job job Job.getInstance(conf, word count); job.setJarByClass(WordCount.class); job.setMapperClass(TokenizerMapper.class); job.setCombinerClass(IntSumReducer.class); // Combiner 减少网络传输 job.setReducerClass(IntSumReducer.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); FileInputFormat.addInputPath(job, new Path(args[0])); FileOutputFormat.setOutputPath(job, new Path(args[1])); System.exit(job.waitForCompletion(true) ? 0 : 1); } }逻辑说明Mapper 里StringTokenizer按空白切词每个词输出word, 1。Reducer 把相同 word 的 1 累加。setCombinerClass是关键优化——Combiner 在 Map 端先做一次局部聚合把word, 1合并成word, n再发给 Reducer能大幅减少 Shuffle 阶段的网络传输。Combiner 逻辑和 Reducer 一样时可以直接复用但前提是操作满足结合律和交换律求和、求最大值可以求平均值不行。编译打包运行# 编译 javac -classpath $(hadoop classpath) -d classes WordCount.java # 打包 jar -cvf wordcount.jar -C classes/ . # 准备输入数据并上传 hdfs dfs -mkdir -p /user/student/wordcount/input echo hello world hello hadoop input.txt hdfs dfs -put input.txt /user/student/wordcount/input/ # 运行 hadoop jar wordcount.jar WordCount \ /user/student/wordcount/input \ /user/student/wordcount/output # 查看结果 hdfs dfs -cat /user/student/wordcount/output/part-r-00000参数说明hadoop classpath会输出所有依赖 jar 路径编译时必须带上。输出目录必须不存在否则 Job 直接报FileAlreadyExistsException这是新手最常踩的坑。4.3 自定义排序与分组排序怎么做MapReduce 默认按 key 的自然顺序排序。要做自定义排序实现WritableComparable接口重写compareTo()。比如按温度降序排public class TempKey implements WritableComparableTempKey { private int year; private int temp; Override public int compareTo(TempKey o) { // 先按年份升序同年按温度降序 if (this.year ! o.year) { return Integer.compare(this.year, o.year); } return Integer.compare(o.temp, this.temp); } Override public void write(DataOutput out) throws IOException { out.writeInt(year); out.writeInt(temp); } Override public void readFields(DataInput in) throws IOException { year in.readInt(); temp in.readInt(); } // getter/setter 省略 }分组排序二次排序要额外写一个GroupingComparator让相同年份但不同温度的记录进同一个 reduce 调用public class YearGroupingComparator extends WritableComparator { protected YearGroupingComparator() { super(TempKey.class, true); } Override public int compare(WritableComparable a, WritableComparable b) { TempKey k1 (TempKey) a; TempKey k2 (TempKey) b; return Integer.compare(k1.getYear(), k2.getYear()); } }Driver 里设置job.setGroupingComparatorClass(YearGroupingComparator.class)。这样排序按年份升序温度降序但分组只按年份reduce 里拿到的 value 列表就是同一年按温度排好序的。这个模式在求每年最高温度求每组 TopN这类需求里非常常用。注意自定义 key 必须实现WritableComparable否则序列化会失败。compareTo的返回值决定排序返回 0 表示相等会影响分组写的时候要清楚自己在控制排序还是分组。5. 避坑与排查实验里最常翻车的五个地方5.1 格式化后 DataNode 起不来现象jps里只有 NameNode没有 DataNode日志报 Incompatible clusterIDs。原因重复执行了hdfs namenode -formatNameNode 的 clusterID 变了DataNode 里存的还是旧的。解决停掉集群删掉hadoop.tmp.dir下所有内容重新格式化一次再启动。记住格式化只做一次。5.2 输出目录已存在导致 Job 失败现象运行 MapReduce 报org.apache.hadoop.mapred.FileAlreadyExistsException。原因FileOutputFormat要求输出路径不存在防止覆盖已有结果。解决每次运行前删掉输出目录hdfs dfs -rm -r /output或者代码里在 Driver 加判断自动删除。别图省事直接改源码绕过这是保护机制。5.3 内存不足导致容器被杀现象YARN 报 Container killed on request. Exit code is 143或者 beyond physical memory limits。原因伪分布式默认给每个容器分配的内存和机器实际内存不匹配或者数据倾斜导致某个 reduce 处理的数据量远超预期。解决调yarn-site.xml里的yarn.nodemanager.resource.memory-mb和mapreduce.map.memory.mb、mapreduce.reduce.memory.mb按机器实际内存合理分配。数据倾斜的话检查 key 分布必要时加随机前缀打散。5.4 中文乱码现象MapReduce 处理含中文的文本输出乱码。原因输入文件编码和 Hadoop 默认读取编码不一致或者Text类型按 UTF-8 处理但源文件是 GBK。解决统一用 UTF-8 保存输入文件Linux 下用file -i确认编码必要时iconv转换。别在代码里硬编码编码容易顾此失彼。5.5 端口被占用启动失败现象start-dfs.sh后进程起不来日志报 Address already in use。原因9000、9870、8088 等端口被其他进程占用或者上次集群没停干净。解决netstat -tlnp | grep 端口号找到占用进程要么杀掉要么改 Hadoop 对应配置文件的端口。停集群用stop-dfs.sh和stop-yarn.sh别直接 kill -9容易留下 pid 文件导致下次启动异常。6. 综合实训怎么落地从招聘数据清洗到可视化综合实训是实验报告里分值最高的部分常见题目是招聘数据清洗或交通信息分析。这类题目的通用套路是原始数据CSV/JSON→ 上传 HDFS → MapReduce 清洗去重、去空、字段规整、格式统一→ 输出结构化结果 → 导入 Hive 做 SQL 分析 → 可视化。清洗阶段的 Map 只做过滤和规整不改变数据粒度Reduce 做去重时用 key 的唯一性天然去重。比如招聘数据清洗把公司职位薪资拼成 keyvalue 留整条记录Reduce 里只输出第一条就完成了去重。字段规整用正则提取薪资区间、把面议统一成特定标记这些逻辑写在 map 里。验证清洗效果别只看输出条数。我一般会做三件事一是抽样对比随机抽 100 条原始记录和清洗后记录人工核对二是统计字段空值率清洗前后各算一遍三是用hdfs fsck确认输出文件块完整。最后把结果导到 Hive 建外部表跑几个聚合 SQL 验证数据可用性。有个习惯我保持了几年每做完一个实训把踩过的坑和对应的报错原文记到一个 markdown 里下次遇到直接搜。大数据这套东西命令和配置记不住很正常但排错的思路和日志位置记熟了什么问题都能顺着摸下去。希望帮到你。本文还有配套的精品资源点击获取
返回列表