1. 环境准备:装之前的三个硬性检查
开始之前,先把话说透。伪分布式Hadoop测试这个事,说难不难,但环境不对,后面每一步都是坑。我自己带过不少新人,也看过太多人在第一步就栽跟头,所以我先把前置环境里最容易出问题的三个点拎出来讲清楚,你照着做,后面会顺很多。
第一个检查项:JDK版本。Hadoop 3.x要求JDK 8以上,我实测用JDK 8最稳,JDK 11也能跑,但一些老项目的脚本可能会有兼容性怪癖。检查方法很简单:
java -version如果你输出的版本是1.8.0_xxx,那就没问题。如果没装或者版本太老,先去Oracle官网或者用OpenJDK装一个,路径记住,后面配JAVA_HOME要用。
第二个检查项:SSH免密登录。伪分布式虽然只有一台机器,但Hadoop的脚本会通过SSH连接localhost来启动和停止守护进程,所以必须配好免密。这个不配,你每次启动集群都会被要求输密码,甚至直接失败,非常糟心。
第三个检查项:内存和磁盘。伪分布式跑测试不需要多高的配置,2核4G的虚拟机就够用,磁盘预留10G左右比较稳妥。需要注意的是,NameNode和DataNode都会写大量日志,如果你用的是云服务器,注意系统盘别被撑爆。
这三个检查做完,环境基本上就没大问题了。接下来我们进入正题:下载、解压、配置、启动、测试,一条龙走完。
2. 核心思路拆解:为什么先用伪分布式来学Hadoop
很多人一上来就想搭真正的分布式集群,动辄三台五台机器,结果环境配置就劝退了一半人。我的建议一直很明确:先从伪分布式开始,把HDFS和YARN的机制跑通,再考虑扩展成集群,这是性价比最高的学习路径。
伪分布式的核心逻辑其实非常简单:一台物理机上,用多个Java进程分别模拟Hadoop集群中的不同角色。也就是说,你的机器既当NameNode,又当DataNode,同时还是ResourceManager和NodeManager。听起来有点分裂,但这个设计恰恰是Hadoop最巧妙的入门台阶,它把分布式系统最核心的通信机制、存储机制、调度机制,全部压缩在一台机器上让你能亲手摸到。
为什么要这么做?因为Hadoop的分布式架构里,真正复杂的东西不是安装本身,而是各组件之间的通信关系。比如客户端往HDFS写数据时,要先问NameNode要元数据,再找到DataNode去写块;提交作业给YARN时,ResourceManager要协调ApplicationMaster和NodeManager的协作。这些流程在伪分布式模式下,和真实集群调用的接口、走到的代码路径,几乎完全一样,唯一区别就是所有进程都在同一台机器上。
所以伪分布式不是“玩具”,它是Hadoop官方推荐的单机教学模式,资源配置可以尽可能简化,但流程是真实的。
有个细节要注意:伪分布式和本地模式是有本质区别的。本地模式(standalone mode)下,Hadoop用本地文件系统来模拟HDFS,所有进程跑在一个JVM里,主要是用来调试MapReduce代码的。而伪分布式(pseudo-distributed mode)会真正启动NameNode、DataNode这些守护进程,走真正的RPC通信和HDFS存储协议。你在网上搜教程,一定要分清这两种模式,否则极易混淆。
我自己带项目的经验是:先用本地模式跑通WordCount,确认代码逻辑没问题,再切到伪分布式模式,验证整个集群环境的稳定性,最后才去扩集群,这个阶梯上去基本不会摔。这套流程已经被很多团队验证过,是最稳妥的路径。
3. 伪分布式搭建实操:下载、解压与三大配置文件的逐一解析
现在进入实操环节。我以CentOS 7.9 + Hadoop 3.3.6为例,这套组合经过大量实践验证,非常稳定,踩坑概率最低。Hadoop 2.x虽然还有不少老项目在用,但新学的话没必要回头了,直接上3.x。
3.1 下载与解压
下载地址我推荐用国内镜像,速度快而且稳定,Apache官网的下载速度在部分地区实在感人。镜像站选一个你手边访问最快的就行:
# 以清华源为例 wget https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz tar -xzvf hadoop-3.3.6.tar.gz -C /opt/ mv /opt/hadoop-3.3.6 /opt/hadoop解压完之后,建议顺手把属主和属组改一下,避免后续权限问题:
chown -R hadoop:hadoop /opt/hadoop因为我习惯用专门的hadoop用户来跑集群,不用root。这里多说一句:永远不要用root用户跑Hadoop,虽然能跑,但后续做权限测试时会遇到各种莫名其妙的坑,而且HDFS本身的权限模型会在root下被绕过,这对你理解HDFS的权限机制没有任何帮助。
3.2 三个关键配置文件详解
Hadoop的配置看似文件很多,但伪分布式场景下,真正需要动的就四个文件。我先讲三个:core-site.xml、hdfs-site.xml、mapred-site.xml,yarn-site.xml放下一节单独讲。
第一个是core-site.xml,它定义了HDFS的访问入口和临时目录。核心配置就是fs.defaultFS,指向NameNode的RPC地址:
<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> <property> <name>hadoop.tmp.dir</name> <value>file:///opt/hadoop/data/tmp</value> </property> </configuration>这里的hdfs://localhost:9000就是HDFS的“门户地址”。客户端读写HDFS时,都会先访问这个地址去获取元数据信息。hadoop.tmp.dir是NameNode、DataNode存储数据的公共基础目录,默认在/tmp下,但系统重启会清空/tmp,这就可能导致元数据丢失,所以强烈建议改到自定义路径。初次配置时记得建好目录,比如mkdir -p /opt/hadoop/data/tmp。
第二个是hdfs-site.xml,它决定了副本数和NameNode的元数据存储位置:
<configuration> <property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:///opt/hadoop/data/namenode</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:///opt/hadoop/data/datanode</value> </property> </configuration>dfs.replication必须设为1,这是伪分布式和真实集群最直观的区别:伪分布式只有一台DataNode,如果副本数写3,HDFS会因为没法写满副本数而不断告警,甚至进入安全模式。我在测试环境见过太多人因为这个踩坑,特此提个醒。dfs.namenode.name.dir和dfs.datanode.data.dir分别指定元数据和数据块的存储位置,同样建议放在自定义路径下,别用默认的/tmp。
第三个是mapred-site.xml,它决定了MapReduce作业跑在哪套调度框架上。在Hadoop 3.x里,这等同于把MapReduce从“本地跑”切换到“YARN上跑”:
<configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration>这里设置为yarn,意味着MapReduce作业将由YARN统一调度资源,这样后面你会看到提交作业时,ApplicationMaster启动、Container分配资源这些过程,全部走真实流程,价值非常大。
3.3 环境变量与YARN配置
配置文件改完之后,别忘了设置环境变量。编辑/etc/profile,在末尾追加:
export HADOOP_HOME=/opt/hadoop export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk注意JAVA_HOME一定要写你的实际JDK路径,可以用readlink -f $(which java)查出来,不要直接用/usr/bin/java,因为Hadoop脚本里会对JAVA_HOME做路径拼接,指到/usr/bin/java会直接报错。
然后配置yarn-site.xml。对于伪分布式,YARN配置的关键是让ResourceManager和NodeManager都跑在本机,并且开启yarn.nodemanager.aux-services,否则MapReduce作业无法正常运行:
<configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <property> <name>yarn.resourcemanager.hostname</name> <value>localhost</value> </property> </configuration>这里的mapreduce_shuffle不是随便填的。MapReduce的Reduce阶段需要从各个Map Task所在节点拉取中间结果,这个“拉取”的过程称为Shuffle,是MapReduce性能的核心之一。yarn.nodemanager.aux-services就是告诉NodeManager要开启这个Shuffle辅助服务,如果漏配,作业会卡在SHUFFLE阶段起不来,日志里全是Error: Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster。
还有一个容易被忽略的点:Hadoop 3.x默认使用的hadoop.tmp.dir如果不指定,NameNode格式化时会把元数据写到系统默认路径,重启机器可能丢失。我在生产环境排障时经常遇到这种问题,特别是云服务器,重启后Hadoop直接起不来,一看日志发现元数据文件没了,所以这一步切记不要偷懒。
3.4 格式化NameNode:一次性的初始化操作
配置完成后,启动集群前必须先格式化NameNode。这是整个安装过程中最容易出问题的一步,搞不好后面全白搭。
hdfs namenode -format看到Storage directory ... has been successfully formatted就说明成功。格式化干的事情是把NameNode的元数据存储目录初始化成可以接收HDFS元数据的空仓库结构,里面会用current/VERSION记录集群ID和命名空间ID,同时产生一个fsimage_0000000000000000000镜像文件。格式化只做一次,不要反复格式化,因为每次会生成新的集群ID,如果DataNode里存的集群ID和NameNode不一致,DataNode注册会失败,表现为数据节点明明活着,但HDFS里就是看不到可用空间。
如果不幸已经反复格式化了,对伪分布式来说最简单的解决办法是删掉namenode和datanode目录重新来一次,因为单机测试环境没有真实数据需要保留,这个代价可以承受。但在真实集群里这种操作要格外谨慎,必须停机而且确认没有多余的DataNode在跑,否则容易把数据搞丢。
格式化完之后,可以顺手检查一下目录结构:
ls -l /opt/hadoop/data/namenode/current/里面应该有fsimage_*和VERSION文件,这表示元数据初始化成功。
4. 启动与验证:HDFS和YARN可能各自为政
4.1 启动HDFS服务
首先要确认SSH免密登录配置好了,否则启动脚本会在连接localhost时停下:
ssh localhost如果能直接登进去,不需要输密码,就说明没问题。如果还是会要密码,执行:
ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys配好之后再次验证。这个配置看似简单但极其重要,Hadoop的sbin/start-dfs.sh脚本会通过SSH依次远程启动NameNode和DataNode,如果SSH卡住,后面的服务全部起不来。
启动HDFS:
$HADOOP_HOME/sbin/start-dfs.sh启动成功的标志是日志里出现Starting namenodes on [localhost]、Starting datanodes这类输出,并且进程存在:
jpsjps是JDK自带的一个小工具,专门用来查看Java进程,比ps aux | grep java方便很多。正常情况下你会看到以下进程:
| 进程名 | 角色说明 |
|---|---|
| NameNode | HDFS元数据管理,相当于“图书馆总目录” |
| DataNode | 数据块存储,相当于“书架上的书” |
| SecondaryNameNode | 定期合并NameNode的编辑日志,相当于“定期备份整理员” |
如果jps报错,说明环境变量还没生效,先source /etc/profile或者重开一个终端。
4.2 启动YARN服务
然后启动YARN:
$HADOOP_HOME/sbin/start-yarn.sh启动成功后,jps里会多出ResourceManager和NodeManager。到这里,一台“伪分布式”机器上同时跑着5个守护进程:NameNode、DataNode、SecondaryNameNode、ResourceManager、NodeManager。这就是之前说的,一台机器同时扮演所有角色。
4.3 Web界面验证是否真的起来
Hadoop提供了两个Web界面,这个必须养成习惯去主动打开看,因为JPS只能证明进程起了,真正有没有“干活”,得看状态页面:
| 组件 | 地址 | 主要信息 |
|---|---|---|
| HDFS | http://localhost:9870 | NameNode状态、DataNode列表、HDFS容量 |
| YARN | http://localhost:8088 | 队列资源、运行中的Application、节点状态 |
我个人的习惯是启动之后先看HDFS页面里DataNode的“Live Nodes”是不是1,如果是0,说明DataNode没注册上。这个和jps有无DataNode进程是两回事:进程在跑,不代表它注册成功。常见原因就是之前说的集群ID不一致,或者网络配置问题,把DataNode日志翻出来一看便知。
再看YARN页面,如果打开后能看到Active Nodes有1,说明NodeManager也注册成功了。这里如果只有0,多半是yarn-site.xml里没配yarn.resourcemanager.hostname,或者配的localhost和实际主机名对不上。
4.4 HDFS基础操作:首次真实写入文件
为了确认HDFS能正常工作,先做一次简单的文件操作测试:
hdfs dfs -mkdir -p /test/input echo "hello hadoop hello hdfs" > /tmp/test.txt hdfs dfs -put /tmp/test.txt /test/input/ hdfs dfs -ls /test/input/看到Found 1 items就说明HDFS已经能正常读写。这里如果报错mkdir: Permission denied,可以确认一下当前用户是否有权限,因为HDFS的根目录默认属主是执行格式化的那个用户。实在嫌麻烦,伪分布式测试环境可以直接改权限:hdfs dfs -chmod -R 777 /。但说实话,我更建议你去理解一下HDFS的权限模型,这是面试常问的点。
另外提醒一句,hdfs dfs和hadoop fs在Hadoop 3.x里都可用,hdfs dfs更语义化一些,建议统一用这个。
5. 跑一个真实的MapReduce测试:WordCount实战
5.1 准备示例程序
Hadoop发行包里自带了一批示例JAR包,其中hadoop-mapreduce-examples-3.3.6.jar里就有经典的WordCount程序。这个程序虽然是“教学玩具”,但整个作业在YARN上的执行链路,和真实业务的MapReduce作业完全一致。我们用它在HDFS上跑一次完整作业,验证整个链路的可用性。
5.2 创建测试目录并放数据
hdfs dfs -mkdir -p /test/input hdfs dfs -put /tmp/test.txt /test/input/ hdfs dfs -cat /test/input/test.txt能看到文件内容,说明HDFS读写正常。
5.3 运行WordCount
hadoop jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar wordcount /test/input /test/output这里有几个点注意一下:输出目录/test/output必须不存在,如果已经存在会直接报错,因为MapReduce的输出目录是被作业独占的,如果存在,Hadoop会认为作业冲突,直接拒绝执行。另外,输出目录不能是输入目录的子目录,这是为了保证MapReduce数据流不会产生数据被覆盖或污染的问题。
跑起来之后,屏幕上会刷一整屏日志,重点看两个地方:
Submitted application application_xxx表示作业已提交成功,ApplicationMaster已在队列里。map 100% reduce 100%表示Map和Reduce全部完成,作业执行正常。
5.4 查看结果
hdfs dfs -ls /test/output hdfs dfs -cat /test/output/part-r-00000如果结果里能看到每个单词的计数,说明整条链路完全打通。这里多说一句:MapReduce跑完的结果文件叫part-r-00000,不是part-00000。踩过坑的人知道,找半天文件结果发现后缀还有个-r,网上很多教程不讲这个细节,但实际排障时非常重要。
5.5 想想刚才发生了什么
作业跑完后,强烈建议你趁热做一件事:打开YARN Web界面,找到刚才那个Application,点击进去看一下Container的运行记录。你会发现一个WordCount作业,实际上经历了从客户端提交、ApplicationMaster申请资源、NodeManager启动Container、Map阶段并行处理、Shuffle排序、Reduce合并输出这样一个完整过程。这也是我前面强调“伪分布式不是玩具”的原因,你在这个界面看到的每一个调度行为,在真实集群中依然成立。
唯一要注意的是,伪分布式下资源有限,YARN默认只分配一个Container,所以Map和Reduce的并行度都是1,运行速度自然会比真实集群慢很多。这属于正常现象,不用怀疑配置问题。
6. 停止与清理:别让进程堆在机器上
测试做完,照例要把集群停下来,攒一堆Java进程在后台占着内存,后面其他服务会很难受。
$HADOOP_HOME/sbin/stop-yarn.sh $HADOOP_HOME/sbin/stop-dfs.shjps确认一下,应该只剩下JPS自己了。如果发现停了但进程还在,就是SSH免密配置有问题导致脚本没能连上localhost发送停止指令,检查authorized_keys即可。
最后提醒一个重复测试时的小技巧:如果第二次跑测试时想重新格式化HDFS,标准流程是先全停、再删数据目录、再格式化、最后启动。不要图省事直接格式化,你会发现DataNode全部注册失败。因为格式化会重新生成集群ID,而DataNode目录里存的还是旧集群ID,两边对不上,注册自然被拒。
7. 常见问题与排查技巧实录
这一节是我最想让你认真看的,因为我自己在带人和做支持的过程中,翻来覆去遇到的坑也就这么几个。我把它们单独列出来,配上排查思路,你以后遇到问题先来这里翻一遍。
7.1 JPS没有NameNode进程怎么办
可能原因按概率排序:
- 格式化没有成功。没初始化元数据,NameNode起不来。查看日志文件
$HADOOP_HOME/logs/hadoop-hadoop-namenode-*.log,如果出现NameNode is not formatted,直接hdfs namenode -format重新格式化。 - JDK路径配错了。日志里出现
JAVA_HOME is invalid就是这个问题,检查/etc/profile里的JAVA_HOME指向是否真实存在。 - 端口被占用。默认的
fs.defaultFS端口是9000,和别的服务撞了的话,NameNode会因端口绑定失败而退出。
7.2 DataNode进程在,但Web界面Live Nodes显示0
这是初学者最容易遇到的“玄学问题”。解决顺序:
- 先看DataNode日志
$HADOOP_HOME/logs/hadoop-hadoop-datanode-*.log,找Block pool ID needed或DatanodeRegistration相关报错。 - 如果日志里出现集群ID不一致的报错,说明NameNode被重复格式化过,DataNode里的集群ID已经老了。解决办法:停止集群,删除
namenode和datanode两个数据目录,重新格式化,再启动。 - 如果日志里一直出现
Connection refused,检查有没有被防火墙拦了,或者DataNode配置的RPC地址根本无法连通到NameNode。
7.3 作业提交后卡在ACCEPTED状态不动
作业提交到YARN但一直不跑,ResourceManager页面上显示ACCEPTED。这个状态说明作业已经进了队列,但NodeManager没有资源来分配Container。按下面几步依次排查:
- 先看
jsp,确认NodeManager进程还在不在。 - 不在的话,把
yarn-site.xml里yarn.nodemanager.aux-services单独拿出来检查。这个我之前强调过,漏配会直接在运行时报MapTaskAttemptImpl相关的NoSuchMethodError,挺迷惑的。 - 如果NodeManager在,但是YARN页面显示0个Active Nodes,检查防火墙或
/etc/hosts配置,确保localhost解析正常。
7.4 作业运行失败,日志报找不到Output目录或Input目录
这类问题九成是路径写错了或者根本没有hdfs://前缀,而作业是用本地路径解析的。留意一下:hadoop jar里写的输入输出路径,默认是被当作HDFS路径处理的。如果确实想用本地路径,需要加file:///前缀,比如/home/user/test.txt要写成file:///home/user/test.txt。伪分布式阶段我建议所有路径都走HDFS,把习惯养好,后面上集群会省很多事。
7.5 跑在Windows上怎么处理
有不少朋友是在Windows本机开发环境里跑伪分布式测试。官方原生不支持Windows,但有几个常见做法:用WSL跑Linux环境是最稳的路径,其次是在Windows里装虚拟机跑CentOS,或者用Docker Desktop拉一个Hadoop镜像。网上也有补丁包方式让Hadoop直接跑在Windows Native环境,但这个坑比较多,我见过不少人在NativeIO和Winutils上浪费一整天,不太建议折腾。
7.6 伪分布式排障快查表
| 现象 | 第一排查点 | 第二排查点 |
|---|---|---|
| 启动脚本卡住 | SSH免密是否配置 | /etc/hosts是否解析正常 |
| NameNode起不来 | 是否格式化过 | Java路径是否真实存在 |
| DataNode注册失败 | 集群ID是否一致 | 防火墙是否拦截端口 |
| 作业卡在ACCEPTED | NodeManager是否存活 | aux-services是否配置 |
| 作业跑完但没结果文件 | 是否输出了part-r-00000而非part-00000 | 确认Reduce阶段是否执行完成 |
这份表格是我干活时自己也会对着查的清单,遇到问题先按表格过一遍,能筛掉一半以上的低级坑。
8. 几步之后还能怎么玩
测试链路通了之后,伪分布式的使命其实还可以再往前走几步,让这台机器的价值最大化。
第一,把HDFS的块大小调小一点,比如在hdfs-site.xml里加:
<property> <name>dfs.blocksize</name> <value>1m</value> </property>这样往HDFS里传一个大文件,你可以直观看到HDFS是怎么样把文件切分到多个DataNode块里的。虽然伪分布式只有一个DataNode,但块信息仍然会在NameNode里被记录清楚。跑一个hdfs fsck /test/input/test.txt -files -blocks,你会看到类似“块0、块1...”的清晰输出,分布式文件系统的“分块”概念一下就通了。
第二,试着在YARN上提交一个需要多个Map任务的任务。比如给输入目录塞几十个文件,再用一个PI计算示例程序跑一次,你会看到YARN页面上的Container数量开始变化。虽然NodeManager在同一台机器上,但资源调度的真实流程依然会展现得一清二楚。
第三,把HDFS的权限测试做一下。建一个普通用户,用hdfs dfs -chown改文件属主,再尝试用不同身份访问HDFS上的文件,观察HDFS的权限控制行为。这个对理解HDFS的权限模型帮助极大,也是面试常考的点。
第四,集成Zookeeper。网上经常拿“Hadoop和Zookeeper整合实战”来做高可用练习。伪分布式也能跑起来,因为Zookeeper本身不需要多强配置,跑一个单机ZooKeeper实例,再把HDFS的高可用模式打开,虽然资源紧张时会有点吃力,但整个故障切换流程可以完整跑一圈,对理解HDFS HA机制价值巨大。
我个人在实际操作中的体会是,伪分布式测试环境最厉害的地方不是“能跑个WordCount”,而是它能让你在一台机器上把整个大数据技术栈的骨架搭起来。HDFS、YARN、MapReduce、Zookeeper、Hive、Spark,都能在这个基础上逐个加装起来,形成你个人的专属大数据实验室。后面换工作、做面试、跑Demo项目,这套环境都是你最趁手的工具。