
1. 从课程名拆解大数据实验一到底在练什么看到“大数据技术实验一”这个标题很多人第一反应是“又是装环境、跑WordCount那一套”。我带过几届学生做这个实验也帮不少跨专业的朋友补过课说实话实验一的核心从来不是让你写出多牛的分布式程序而是逼你把“单机思维”切换成“集群思维”。这个切换过程里环境配置、数据流转、任务提交这三个环节任何一个卡住后面全盘皆输。实验一通常对应的是大数据技术栈的入门模块涉及Linux基础操作、Hadoop伪分布式或完全分布式集群搭建、HDFS基本命令、MapReduce编程模型初探。关键词虽然没给但从课程名称和常见教学大纲推断核心关键词逃不出这几个Hadoop、HDFS、MapReduce、伪分布式、SSH免密、YARN、WordCount。摘要描述为空反而说明这个实验的定位是“基础中的基础”不需要花哨的包装把每一步做扎实就是胜利。适合读这篇的人有三类一是正在上这门课、对着实验指导书发懵的本科生二是想自学大数据但被环境劝退的转行者三是需要快速复现一套可用实验环境、用于教学或演示的从业者。我下面讲的东西不照搬任何一本教材的目录而是按“一个真实动手的人会怎么想、怎么做、怎么翻车、怎么救回来”的顺序来组织。你跟着走一遍实验报告能写环境能跑坑也能提前避开。2. 实验环境搭建为什么你的伪分布式总是起不来2.1 虚拟机与网络模式的选择逻辑实验一的第一步永远是准备一台Linux机器。教学场景下绝大多数人用的是虚拟机。这里第一个分岔路就来了选VMware还是VirtualBox选NAT还是桥接我的建议很直接——如果你只是做实验一NAT模式足够别折腾桥接。NAT模式下虚拟机通过宿主机上网IP由虚拟网络分配你不需要去动实验室路由器的配置也不会因为换了个教室就断网。桥接模式看起来“更真实”但它要求你所在的网络允许动态分配IP很多学校机房是静态绑定桥接上去直接失联。内存分配上伪分布式建议给虚拟机4GB起步8GB更稳。Hadoop的NameNode、DataNode、ResourceManager、NodeManager全塞在一台机器上2GB内存跑起来会频繁触发交换分区你会看到进程莫名其妙被Kill。磁盘给40GB选择“将虚拟磁盘存储为单个文件”还是“拆分成多个文件”其实影响不大但单个文件在拷贝和快照时更省事。注意安装完系统后第一件事是拍快照。后面每次要改SSH配置、改Hadoop配置文件之前再拍一次。这个习惯能帮你省下大量重装系统的时间。2.2 主机名与hosts文件的隐藏关联很多人卡在“格式化NameNode之后DataNode死活起不来”翻日志看到一句“Connection refused”或者“UnknownHostException”。根因往往出在主机名解析上。Hadoop的配置文件里写的是主机名不是IP。如果你在core-site.xml里写了hdfs://localhost:9000那没问题但如果你写的是hdfs://master:9000就必须保证/etc/hosts里有master到127.0.0.1或实际IP的映射。我习惯的做法是先把主机名改成有意义的名字比如master然后在/etc/hosts里加一行127.0.0.1 master。注意不要只写127.0.0.1 localhost就完事很多默认配置里localhost和主机名是分开解析的。改完之后用hostname和ping master各验证一次确保返回的是你期望的地址。还有一个细节如果你之前已经格式化过NameNode后来改了主机名那必须把dfs.namenode.name.dir指向的目录清空再重新格式化。因为NameNode的元数据里已经记录了旧的集群ID和主机名直接重启会报Incompatible clusterIDs。这个错误信息很直白但第一次遇到的人容易慌以为要重装Hadoop其实删掉data和logs目录重来一遍就行。2.3 SSH免密登录不是配了就行得看权限伪分布式虽然只有一台机器但Hadoop的启动脚本仍然会通过SSH去连接本机。所以你必须配置本机免密登录自己。步骤不复杂ssh-keygen -t rsa一路回车然后ssh-copy-id localhost或者手动把公钥追加到~/.ssh/authorized_keys。但这里有个高频翻车点权限。SSH对~/.ssh目录和authorized_keys文件的权限极其敏感。如果~/.ssh是777或者authorized_keys是644以上SSH会直接拒绝使用这个密钥而且日志里只给一句模糊的“Permission denied”。正确的权限是~/.ssh为700authorized_keys为600~/.ssh下的私钥id_rsa为600。配完之后用ssh localhost测试第一次可能会问yes/no输入yes之后如果不再要密码才算成功。提示如果你在ssh localhost时仍然要密码先看/var/log/secureCentOS系或/var/log/auth.logDebian系里的SSH日志里面会明确告诉你是因为权限问题还是密钥类型问题被拒。3. Hadoop配置文件那几个XML到底改了什么3.1 core-site.xml与hdfs-site.xml的最小改动集实验一不需要你把所有配置项都背下来但有几个是必须改的。core-site.xml里核心就两项fs.defaultFS指定HDFS的访问入口伪分布式下写hdfs://localhost:9000或hdfs://master:9000hadoop.tmp.dir指定临时目录默认是/tmp/hadoop-${user.name}但/tmp在重启后可能被清理建议改到/opt/hadoop/tmp这类持久目录。hdfs-site.xml里关键是dfs.replication伪分布式下必须设为1。因为只有一台DataNode如果保持默认的3HDFS会一直报“副本不足”虽然不影响读写但日志里全是警告看着心烦。另外dfs.namenode.name.dir和dfs.datanode.data.dir建议显式指定到你的工作目录下方便出问题时直接删目录重来。这里解释一下“为什么伪分布式要设副本为1”HDFS的副本机制是为了容错默认3副本意味着每个数据块存三份分布在不同的DataNode上。伪分布式只有一台机器三个副本只能挤在同一个DataNode上既浪费空间又触发警告。设成1之后数据只存一份实验场景下完全够用。3.2 mapred-site.xml与yarn-site.xml的取舍mapred-site.xml在较新版本的Hadoop里需要从模板复制生成。核心配置是mapreduce.framework.name设为yarn表示MapReduce任务跑在YARN上。如果你只是跑WordCount其实用本地模式也能出结果但实验一的目的就是让你走一遍完整的YARN调度流程所以这一步不能省。yarn-site.xml里最重要的是yarn.nodemanager.aux-services设为mapreduce_shuffle这是NodeManager为MapReduce提供的Shuffle服务。少了这一项任务会卡在Map阶段完成、Reduce阶段起不来的状态日志里报“Shuffle error”。另外yarn.resourcemanager.hostname指定ResourceManager所在主机伪分布式下就是你的主机名。配置完成后用hdfs namenode -format格式化然后start-dfs.sh和start-yarn.sh分别启动HDFS和YARN。用jps检查进程应该看到NameNode、DataNode、SecondaryNameNode、ResourceManager、NodeManager五个进程。少任何一个都说明对应的配置或启动脚本有问题。配置文件关键配置项伪分布式推荐值作用core-site.xmlfs.defaultFShdfs://master:9000指定HDFS入口core-site.xmlhadoop.tmp.dir/opt/hadoop/tmp持久化临时目录hdfs-site.xmldfs.replication1单机副本数mapred-site.xmlmapreduce.framework.nameyarn任务跑在YARN上yarn-site.xmlyarn.nodemanager.aux-servicesmapreduce_shuffleShuffle服务3.3 格式化NameNode的时机与反复格式化的代价hdfs namenode -format这个命令只能执行一次除非你打算清空整个HDFS。每次格式化都会生成新的集群ID而DataNode启动时会去比对自身存储的集群ID和NameNode的集群ID不一致就拒绝启动。所以如果你格式化了两次但没清空DataNode的数据目录就会看到DataNode启动后立刻退出日志里写着Incompatible clusterIDs。正确的重来姿势是先stop-dfs.sh和stop-yarn.sh停掉所有进程然后删除hadoop.tmp.dir指向的整个目录以及dfs.namenode.name.dir和dfs.datanode.data.dir指向的目录再重新格式化。我见过有人只删了NameNode的目录没删DataNode的结果一样起不来。所以要么全删要么别格式化。4. 第一个MapReduce程序WordCount背后的数据流转4.1 从HDFS读文件到Map输出的完整链路WordCount是MapReduce的“Hello World”但很多人跑通了也没搞明白数据到底怎么走的。我按实际执行顺序拆一遍你先把一个文本文件用hdfs dfs -put上传到HDFS这个文件会被切分成多个Block默认128MB一个。然后你提交WordCount任务YARN的ResourceManager会分配一个ApplicationMaster由它去协调Map任务和Reduce任务。Map任务启动后InputFormat负责把Block读成一个个key, value对默认是TextInputFormatkey是行偏移量value是这一行的文本。然后Mapper类的map方法被逐行调用你在里面把一行拆成单词输出word, 1。这些输出不会立刻写到磁盘而是先放在内存缓冲区缓冲区满了再溢写到磁盘同时按key排序。这个过程叫Spill是Shuffle阶段的一部分。Reduce任务启动后会去各个Map任务所在的节点拉取属于自己的分区数据这叫Shuffle。拉过来之后再做一次归并排序然后按key分组每组调用一次reduce方法。你在reduce里把同一个单词的所有1加起来输出word, sum。最后OutputFormat把结果写到HDFS。理解这条链路的意义在于当你发现任务卡住、报错、或者结果不对时你能定位到是Map阶段、Shuffle阶段还是Reduce阶段的问题。比如日志里一直刷“Spilling map output”说明Map输出太大内存缓冲区不够如果卡在“Reduce shuffle phase”说明网络传输或磁盘IO是瓶颈。4.2 本地模式与YARN模式的切换代价很多教材会先让你在本地模式下跑WordCount不启动HDFS和YARN直接读本地文件、写本地文件。这样做的好处是快不用等集群启动调试也方便。但本地模式下mapreduce.framework.name是local不走Shuffle的完整流程也不经过YARN调度。从本地模式切到YARN模式你需要改mapred-site.xml重新打包程序确保输入输出路径是HDFS路径而不是本地路径。我建议的做法是先在本地模式下调通逻辑确认Mapper和Reducer的输入输出类型正确再切YARN模式跑一遍。这样如果YARN模式报错你能确定是环境问题而不是代码问题。还有一个细节YARN模式下你的程序打成的JAR包需要被上传到HDFS或者通过-files参数分发到各个节点。伪分布式下只有一台机器这个问题不明显但如果你后面做完全分布式忘了分发JAR包任务会报ClassNotFoundException。4.3 任务日志的查看姿势与常见报错对照YARN模式下任务日志不在控制台直接输出而是存在各个NodeManager的本地目录里。你可以通过YARN的Web UI默认8088端口查看任务状态点进具体的Application再点进具体的Container就能看到stdout和stderr。另一种方式是用yarn logs -applicationId appId命令直接拉取日志。常见报错我列几个Container killed by YARN for exceeding memory limitsMap或Reduce任务用的内存超过了mapreduce.map.memory.mb或mapreduce.reduce.memory.mb的限制。伪分布式下默认是1024MB一般够用但如果你的数据量特别大或者逻辑特别重需要调大。Shuffle error: Too many fetch failuresReduce拉取Map输出时失败。伪分布式下通常是NodeManager的Shuffle服务没起来检查yarn.nodemanager.aux-services是否配了mapreduce_shuffle。java.io.IOException: All datanodes are badHDFS写入时所有DataNode都不可用。检查DataNode进程是否存活以及dfs.datanode.data.dir的磁盘空间是否满了。提示看日志时先看stderr再看stdout。stderr里通常是异常堆栈stdout里是程序自己的打印输出。YARN的日志聚合功能默认可能没开如果yarn logs命令报“Log aggregation has not completed”就去NodeManager的本地日志目录找路径通常是$HADOOP_HOME/logs/userlogs/application_xxx/container_xxx/。5. 实验报告里不会写的踩坑实录5.1 防火墙与SELinux两个沉默的杀手实验环境里最容易被忽略的就是防火墙和SELinux。Hadoop的各个组件之间通过多个端口通信NameNode用9000和50070DataNode用50010和50075ResourceManager用8032和8088NodeManager用8042等。如果防火墙开着这些端口之间的连接会被静默丢弃表现就是进程都活着但Web UI打不开或者任务提交后一直卡在ACCEPTED状态。教学环境里我通常直接systemctl stop firewalld和systemctl disable firewalldSELinux用setenforce 0临时关闭再改/etc/selinux/config永久设为disabled。生产环境当然不能这么干但实验一的目标是跑通流程安全策略可以后面再补。5.2 时间同步集群内节点时间不一致的连锁反应伪分布式只有一台机器时间同步问题不明显。但如果你后面扩展成完全分布式或者你的虚拟机长时间挂起后恢复系统时间可能和宿主机偏差很大。Hadoop的某些组件比如Kerberos认证实验一不涉及对时间敏感但即使不涉及认证YARN的任务超时判断也依赖系统时间。我遇到过虚拟机挂起一晚上第二天恢复后任务一直报“Task attempt failed to report status for 600 seconds”其实就是时间跳变导致的心跳超时。解决办法很简单yum install ntp或apt install ntp然后ntpdate同步一下。或者更直接在虚拟机设置里开启“将客户机时间与主机同步”。5.3 磁盘空间与inode耗尽小文件太多的代价HDFS的设计目标是存大文件不是海量小文件。每个文件、每个Block、每个副本在NameNode里都占用一条元数据记录大约150字节。如果你往HDFS里塞了几十万个小文件NameNode的内存会被吃光表现为NameNode启动极慢或者直接OOM。实验一通常不会遇到这个问题但如果你在实验里反复上传下载大量小文件做测试建议定期清理或者用hdfs dfs -count看看文件数量。另外虚拟机的磁盘空间也要留意。Hadoop的日志、临时文件、HDFS数据块都会占空间。我习惯在实验开始前用df -h看一眼根分区确保至少有10GB可用。如果空间不够hdfs namenode -format都可能失败。6. 从实验一到后续实验的衔接思路实验一跑通之后你手里应该有一个能用的伪分布式Hadoop集群以及一个能提交MapReduce任务的开发环境。这个基础可以往几个方向延伸一是把伪分布式扩展成完全分布式用两三台虚拟机搭一个真正的集群体会网络通信和副本分布二是学习Hive或Spark它们底层依赖HDFS和YARN实验一的环境可以直接复用三是深入MapReduce的编程模型比如自定义InputFormat、Partitioner、Combiner理解它们对性能的影响。我个人建议先把实验一的环境做成一个虚拟机模板拍好快照后面每次做新实验都从这个模板克隆。这样即使某个实验把环境搞坏了也能几分钟内恢复不用从头再来。这个习惯我从第一次带实验课就养成了后来做任何需要反复折腾环境的事情都会先建一个“干净基线”。最后分享一个我自己的检查清单每次启动集群后按顺序过一遍jps看五个进程是否齐全hdfs dfsadmin -report看DataNode是否注册成功yarn node -list看NodeManager是否在线浏览器打开50070和8088看Web UI是否正常。这四步都过了再开始跑任务能省下大量“任务报错但不知道是环境问题还是代码问题”的纠结时间。