Hadoop三种模式详解:本地、伪分布式与完全分布式配置实战
2026/9/16 5:02:43 网站建设 项目流程

1. 为什么每个学大数据的人都绕不开这三种安装模式

先说我自己的经历。第一次接触Hadoop时,我照着网上的教程折腾了整整两天,最后集群没起来,倒是把虚拟机搞崩了三次。问题出在哪?教程东一篇西一篇,有的讲单机版,有的直接上三节点集群,我根本分不清它们之间的区别,也不知道自己当前到底该用哪一种。

后来把三种模式彻底理了一遍才明白,Hadoop的安装配置其实就三条路:本地模式(Local Mode)、伪分布式模式(Pseudo-Distributed Mode)、完全分布式模式(Fully-Distributed Mode)。三者的区别不只是“几台机器”这么简单,而是映射了你的实际需求:是想跑通一个示例验证环境,还是想模拟完整的分布式流程,或者是搭建一个真正能用于开发测试的集群。

这篇内容就是我从零开始配置三种模式的完整记录,包含每一步的配置文件和参数含义,以及我在实验过程中遇到的报错和排查过程。适合刚接触Hadoop、准备做实验或者正在搭开发环境的人参考,不管你是用虚拟机、云服务器还是自己的笔记本,思路都是通用的。

有一点先说清楚:这篇文章里所有的路径、版本号和配置参数,我都以Hadoop 3.x和JDK 1.8的组合为例,这也是目前大多数大数据课程和实验环境采用的主流组合。你用2.x版本时部分配置项名称会有差异,我会在对应位置标注出来。

2. 开始之前必须想明白的三个问题

配置Hadoop之前,先别急着解压安装包。我把身边同学踩过的坑归拢了一下,发现大部分问题都出在下面这三个环节,提前搞定它们能省下大量排查时间。

2.1 JDK版本和Hadoop版本怎么匹配

很多人的第一个坑就是JDK版本不对。Hadoop对JDK的版本要求非常明确,以Hadoop 3.x为例,官方文档标注支持Java 8和Java 11,但实际实验中最稳的是JDK 1.8。我试过用JDK 17跑Hadoop 3.3.x,结果启动NameNode的时候直接报UnsupportedClassVersionError,折腾了半小时查日志才发现是版本问题。

安装完JDK后,第一件事就是在终端里确认版本号:

java -version

正常情况下应该输出类似这样的内容:

java version "1.8.0_202" Java(TM) SE Runtime Environment (build 1.8.0_202-b08) Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)

同时需要配置JAVA_HOME环境变量。网上的教程让你改/etc/profile~/.bashrc都行,我的习惯是写在~/.bashrc里,这样只对当前用户生效,不会影响系统全局环境:

export JAVA_HOME=/usr/local/jdk1.8.0_202 export PATH=$JAVA_HOME/bin:$PATH

改完之后执行source ~/.bashrc让它立即生效,再用echo $JAVA_HOME验证一下,能正常输出路径就说明配好了。

2.2 主机名、IP和hosts映射最好提前规划

这一点在做完全分布式模式的时候特别重要,但哪怕只是搭伪分布式,我也建议提前规划好。因为Hadoop内部组件之间通信时用的是主机名,如果主机名解析不对,轻则启动慢,重则节点之间互相找不到对方。

修改主机名用这个命令:

hostnamectl set-hostname hadoop01

然后编辑/etc/hosts文件,把IP和主机名的映射关系写进去:

192.168.10.10 hadoop01 192.168.10.11 hadoop02 192.168.10.12 hadoop03

注意:不要用127.0.0.1或者localhost来代替集群中其他节点的IP,否则分布式模式下NameNode和DataNode之间的心跳通信会出问题。我见过有人直接在hosts里写127.0.0.1 hadoop01,结果三台机器互相访问的时候全指向本机了,DataNode一直注册不上。

2.3 SSH免密登录要提前配好

Hadoop的守护进程启动时,需要远程到各个节点去拉起来,这个过程就是靠SSH来做的。如果不配置免密,每次启动集群都要输一堆密码,而且脚本自动化执行的时候根本没法输入,所以免密登录是必需项。

最简单的验证方法是先对当前用户生成密钥:

ssh-keygen -t rsa -P ''

一路回车,-P ''的意思是不设置密码短语,生成后直接测试:

ssh localhost

如果不需要输密码就能登录,说明本机免密已经生效。做成完全分布式的时候,还需要把公钥分发到各台机器,具体操作我在后面完全分布式的部分会详细讲。

3. 本地模式:十分钟验证Hadoop环境能跑起来

本地模式是Hadoop最简单的一种部署方式,它的特点是:所有进程都在同一个Java虚拟机里运行,不启动HDFS,不启动YARN,也不涉及任何分布式文件系统和资源调度。它存在的意义就是让你快速验证Hadoop环境是否安装正确、依赖是否完整。

3.1 本地模式的原理和适用场景

很多人不理解为什么要有本地模式,觉得“不就是能跑个wordcount吗,有什么用”。这种想法不太对。本地模式的价值在于,它是一个最底层的环境自检:如果连本地模式都跑不起来,那伪分布式和完全分布式就更不用谈了。

本地模式下,Hadoop会使用本地文件系统作为输入输出,没有NameNode和DataNode这些角色的概念。比如在本地模式运行一个WordCount示例,大致流程是:MapReduce框架在当前JVM里读本地文件,经过Map阶段和Reduce阶段,再把结果写到本地目录。整个过程可以理解为“用Hadoop的API在本地模拟了一次MapReduce计算”,因为不涉及跨进程和跨节点调度,所以速度非常快,适合做功能验证。

3.2 解压和配置的完整流程

首先,把下载好的Hadoop安装包解压到你想要的目录:

tar -zxvf hadoop-3.3.4.tar.gz -C /usr/local/

解压后进入Hadoop目录,你会看到一系列子目录。第一次接触的人可能有点懵,我简单列一下最关键的几个:

目录作用
binHadoop命令存放位置,后续所有操作都要用到这里面的脚本
etc/hadoop所有配置文件所在目录,配置工作主要就是改这里
sbin守护进程启动和停止脚本,比如start-dfs.sh
share自带的示例包和jar包,WordCount示例就在这里

接着需要修改etc/hadoop/hadoop-env.sh文件,把JDK路径告诉Hadoop,因为Hadoop启动脚本需要找到Java:

export JAVA_HOME=/usr/local/jdk1.8.0_202

修改完这个之后,检查一下Hadoop的版本号,看看安装是否正常:

cd /usr/local/hadoop-3.3.4 bin/hadoop version

如果输出了类似下面的内容,说明Hadoop本身已经能正常用Java运行了:

Hadoop 3.3.4 Java 1.8.0_202 ...

3.3 跑通官方自带的WordCount示例验证环境

官方自带的示例包在share/hadoop/mapreduce/目录下,是一个名为hadoop-mapreduce-examples-3.3.4.jar的jar包。我们直接在本地模式跑一下WordCount,作为环境验证的标准动作。

先在Hadoop目录下创建一个临时输入文件,随便写几行内容:

mkdir input echo "hello hadoop hello world" > input/test.txt

然后执行:

bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.4.jar wordcount input output

执行过程中会打印一堆日志,看到类似于Map-Reduce Framework的输出信息时,说明任务正在走MapReduce流程。执行完成后,查看输出文件:

cat output/part-r-00000

如果正常输出:

hadoop 1 hello 2 world 1

就说明本地模式完全没问题了。

这里有一个我踩过的细节:第二次运行wordcount之前,必须先把output目录删掉,否则会报Output directory output already exists错误。这是因为Hadoop的MapReduce框架出于安全考虑,不允许不经确认就覆盖已有输出目录。实验的时候每次重跑都要rm -rf output,这个动作要养成肌肉记忆。

4. 伪分布式模式:一台机器上模拟出完整集群

本地模式跑通之后,下一步就是伪分布式。伪分布式的核心价值在于,它让HDFS、YARN、MapReduce这些分布式组件都以真实进程的形式在你本机上运行,虽然都挤在一台机器里,但角色之间的通信、调度逻辑和完全分布式是一致的。对于学习Hadoop的运行机制来说,伪分布式是最划算的投入。

4.1 伪分布式和本地模式的关键差异

伪分布式模式下,格局发生了变化:

  • HDFS:启动了NameNode和DataNode两个进程,一个负责元数据管理,一个负责实际数据块存储
  • YARN:启动了ResourceManager和NodeManager进程,开始有资源调度和任务分配的概念
  • 分布式文件系统:输入输出的存储介质不再是本地文件系统,而是HDFS
graph TD A[本地模式] --> B[进程全在一个JVM] A --> C[没有HDFS/YARN] D[伪分布式] --> E[每个守护进程独立JVM] D --> F[有HDFS/YARN] D --> G[部署在一台机器上]

4.2 核心配置文件逐个拆解

伪分布式模式需要修改两组核心配置文件:core-site.xmlhdfs-site.xml。网上教程往往一句话“把如下内容粘贴进去”就完了,但如果你不知道每个参数的含义,后面出了问题的排查成本非常高。我把参数拆开讲。

第一个是etc/hadoop/core-site.xml,它的作用是指定HDFS的NameNode地址,以及临时文件目录。

<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> <property> <name>hadoop.tmp.dir</name> <value>file:///usr/local/hadoop-3.3.4/tmp</value> </property> </configuration>

fs.defaultFS的值是hdfs://localhost:9000,意味着所有HDFS操作默认连接到本机9000端口上的NameNode。hadoop.tmp.dir参数指定元数据和数据块的存储根目录。注意这个参数默认值是/tmp/hadoop-${user.name},而系统/tmp目录重启后在大多数Linux发行版中会被清空,这就可能导致NameNode格式化后的元数据丢失,所以务必改到自己的Hadoop安装目录下。

第二个是etc/hadoop/hdfs-site.xml,主要配置数据块副本数量。伪分布式因为只有一个DataNode,副本数只能设为1,如果保持默认的3,DataNode会一直尝试复制副本,报出一堆健康警告。

<configuration> <property> <name>dfs.replication</name> <value>1</value> </property> </configuration>

4.3 格式化NameNode这一步不能省

配置改完之后,需要执行一次NameNode格式化。这个操作的作用是初始化文件系统元数据存储结构,相当于给磁盘文件系统做一次格式化。以后的每次启动都是基于这次格式化产生的结果。

bin/hdfs namenode -format

执行成功的标志是日志中出现了类似successfully formatted的提示,以及在/usr/local/hadoop-3.3.4/tmp/dfs/name/current目录下生成了VERSIONedits_0000000000000000000fsimage_0000000000000000000等文件。

这是我踩得最惨的坑:Hadoop只能格式化一次,或者更准确地说,重复格式化会让NameNode生成的clusterID和DataNode已存储的clusterID不一致,导致DataNode启动后无法向NameNode注册。实验中如果你必须重新格式化,一定要先删掉tmp目录下的所有内容,让NameNode和DataNode在相同的clusterID下重新初始化,否则你就得在日志里看到我见过的那句Incompatible clusterIDs了。

4.4 启动HDFS并验证进程状态

格式化完成后就可以启动HDFS了:

sbin/start-dfs.sh

在启动过程中,会要求你输入SSH密码,如果你提前配置了ssh localhost免密,就会直接跳过。启动完成后,用JPS命令检查Java进程:

jps

正常情况下应该看到四个进程:

进程名作用
NameNodeHDFS的命名节点,管理文件系统的命名空间
DataNode数据节点,存储实际数据块
SecondaryNameNode辅助NameNode合并编辑日志
JpsJPS命令自身,不用管它

如果少了其中任何一个,优先去Hadoop根目录下的logs/目录看对应日志文件。日志是最好的排错信息源,我在后面的排错部分会再展开。

4.5 验证HDFS读写和Web UI

启动后,在HDFS上创建一个目录,再上传一个文件测试读写:

bin/hdfs dfs -mkdir -p /user/root/input bin/hdfs dfs -put input/test.txt /user/root/input/ bin/hdfs dfs -cat /user/root/input/test.txt

能正常显示文件内容,就说明HDFS的读写链路是通的。

另外,NameNode提供了一个Web UI界面,浏览器访问:

http://localhost:9870

这是Hadoop 3.x的默认端口,2.x版本是50070。界面上能看到集群的健康状态、DataNode在线列表和HDFS存储使用情况。一个容易出现的坑是端口访问不了,如果你是在云服务器或者虚拟机上配置的,检查一下防火墙和安全组有没有放通9870端口。

5. 完全分布式模式:三节点集群从规划到启动的完整记录

完全分布式才是Hadoop“分布式”的真正体现:多台机器、各自独立的进程、通过网络通信协同工作。实验环境和生产环境大多采用这种模式,所以这一部分值得仔细过一遍。

5.1 节点规划:主节点和从节点怎么分工

我的实验环境是三台虚拟机,操作系统都是CentOS 7.9。规划如下:

节点主机名角色
主节点hadoop01NameNode、ResourceManager
从节点1hadoop02DataNode、NodeManager
从节点2hadoop03DataNode、NodeManager

为什么这样规划?完全分布式的核心角色中,NameNode负责管理整个文件系统的命名空间,ResourceManager负责YARN的资源管理和作业调度,这两个角色对机器的资源要求较高,放在主节点。DataNode负责数据块存储,NodeManager负责具体计算任务的执行,它们是真正干活的,可以分布在多台从节点上。

如果你还想加一个SecondaryNameNode角色,我记得常见的做法是把它放到另一台机器上,避免和NameNode同机,这样可以分散单点压力。实验环境里如果不加也不影响核心功能验证。

5.2 三台机器共用的环境准备

三台机器都需要准备一份相同的JDK和Hadoop安装环境。快手做法是在一台机器上配置好,然后通过SCP分发过去:

scp -r /usr/local/jdk1.8.0_202 root@hadoop02:/usr/local/ scp -r /usr/local/hadoop-3.3.4 root@hadoop02:/usr/local/

别忘了修改每台机器的/etc/hostname/etc/hosts。还有hadoop-env.shJAVA_HOME的路径,三台机器要保持一致。

5.3 完全分布式的五个核心配置文件

相比伪分布式,完全分布式需要配置的文件数量更多。我按表格列出每个文件的职责,再逐个说明关键参数:

配置文件作用
core-site.xmlHDFS地址、临时目录等核心配置
hdfs-site.xml副本数、NameNode和SecondaryNameNode地址
yarn-site.xmlYARN资源调度相关配置
mapred-site.xmlMapReduce运行框架配置
workers声明哪些主机是DataNode/NodeManager

core-site.xml,配置在主节点上:

<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://hadoop01:9000</value> </property> <property> <name>hadoop.tmp.dir</name> <value>file:///usr/local/hadoop-3.3.4/tmp</value> </property> </configuration>

注意这里fs.defaultFS的值由localhost换成了主节点的主机名hadoop01,因为从节点需要通过主机名找到NameNode,用localhost的话从节点就会尝试连自己,导致整个集群完全无法通信。

hdfs-site.xml

<configuration> <property> <name>dfs.replication</name> <value>2</value> </property> <property> <name>dfs.namenode.secondary.http-address</name> <value>hadoop02:50090</value> </property> </configuration>

副本数设为2而不是3,这是实验环境下的常见选择。因为只有三个节点,如果设3,三个DataNode各存一份也没有问题,但从节省空间的角度没必要。设为2表示除了本节点之外再找一个节点存一份副本,在节点故障时能恢复数据即可。

yarn-site.xml

<configuration> <property> <name>yarn.resourcemanager.hostname</name> <value>hadoop01</value> </property> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> </configuration>

第一个参数指定ResourceManager跑在哪台机器上,第二个参数mapreduce_shuffle是MapReduce任务执行时的辅助服务,属于YARN运行MapReduce作业的必要配置。很多教程会漏掉第二项,漏掉之后作业提交到YARN时会在Shuffle阶段报错。

mapred-site.xml

<configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration>

这个参数告诉MapReduce作业的运行框架是YARN,而不是内置的本地框架。漏了它的话作业不会提交到集群上执行。

workers文件(Hadoop 3.x叫workers,2.x叫slaves):

hadoop02 hadoop03

这个文件的作用是声明哪些节点是Worker节点,启动脚本会根据内容去远程拉起DataNode和NodeManager。注意文件里每行一个主机名,不能有空格或者多余字符。

5.4 把配置同步到所有节点

所有配置都在主节点上改好之后,用SCP把整个Hadoop配置目录同步到从节点:

scp -r /usr/local/hadoop-3.3.4/etc/hadoop/* root@hadoop02:/usr/local/hadoop-3.3.4/etc/hadoop/ scp -r /usr/local/hadoop-3.3.4/etc/hadoop/* root@hadoop03:/usr/local/hadoop-3.3.4/etc/hadoop/

从节点上不需要单独改配置,因为核心配置里写的是主节点的主机名,从节点启动时会自动去连接主节点。

5.5 SSH免密登录的完整配置动作

完全分布式模式下,主节点需要无密码登录到所有从节点,才能远程启动守护进程。前置条件是把主节点的公钥写到从节点的authorized_keys文件里:

# 在主节点上执行 ssh-keygen -t rsa -P '' ssh-copy-id root@hadoop01 ssh-copy-id root@hadoop02 ssh-copy-id root@hadoop03

然后逐台验证:

ssh hadoop01 ssh hadoop02 ssh hadoop03

能不打密码直接进去就说明免密配置成功。

5.6 格式化NameNode并启动集群

完全分布式模式下,格式化操作只需要在主节点上执行一次:

bin/hdfs namenode -format

格式化完成后启动HDFS和YARN:

sbin/start-dfs.sh sbin/start-yarn.sh

启动完成后,在主节点上执行jps,应该看到:

NameNode ResourceManager

在从节点上执行jps,应该看到:

DataNode NodeManager

再到Web UI上检查集群状态。HDFS的Web UI和伪分布式一样是http://hadoop01:9870,YARN的Web UI是http://hadoop01:8088。YARN的界面上能看到NodeManager列表,正常情况下应该有两台节点在线。

5.7 提交一个真正的分布式作业

在生成环境中验证集群是否工作正常,最直接的方式是提交一个作业到集群上跑。先在HDFS上建目录、传文件:

bin/hdfs dfs -mkdir -p /user/root/input bin/hdfs dfs -put input/test.txt /user/root/input/

然后提交WordCount:

bin/yarn jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.4.jar wordcount /user/root/input /user/root/output

执行完之后用命令检查结果:

bin/hdfs dfs -cat /user/root/output/part-r-00000

到这一步,完全分布式集群就算真正搭建完成并且能跑作业了。

6. 三台机器搭建过程中最容易翻车的五个问题

配置过程很少是一帆风顺的,我把自己实验中遇到过的问题列出来,这些问题有一定的共性,提前了解能省下不少排查时间。

6.1 DataNode进程起不来:clusterID不一致

现象:主节点NameNode正常启动,但从节点的DataNode进程反复挂掉,日志里报Incompatible clusterIDs或者java.io.IOException: NameNode is not formatted

原因:重复格式化了NameNode,导致NameNode生成了新的clusterID,而DataNode数据目录里存的还是旧的clusterID。

解决方式:在所有节点上删除临时目录下的DFS数据,然后回到主节点重新格式化:

rm -rf /usr/local/hadoop-3.3.4/tmp/dfs/ bin/hdfs namenode -format

格式化后同步到所有从节点,重启start-dfs.sh。这一步做完之后我特地对比了一下tmp/dfs/name/current/VERSIONtmp/dfs/data/current/VERSION里的clusterID,确认一致后才启动,此后DataNode就没有再掉线过。

6.2 虚拟内存超出限制导致Container被杀死

现象:作业提交到YARN后,Map或Reduce任务反复失败,日志里频繁出现Container is running beyond virtual memory limits之类的报错。

原因:默认情况下,每个NodeManager容器能被分配的内存有限,虚拟内存超过阈值就会被杀死。这在虚拟机环境下非常常见,因为虚拟机的内存本来就小。

解决方式:打开YARN的yarn-site.xml,把虚拟内存比调大或者直接关掉这个检查:

<property> <name>yarn.nodemanager.vmem-check-enabled</name> <value>false</value> </property>

如果希望更精确地限制,也可以同时调整yarn.nodemanager.vmem-pmem-ratio的值为4或更高。关掉检查实测最省心,前提是集群只用于实验环境。

6.3 SSH免密配置好依然要输密码

现象:主节点SSH到从节点仍然要求输密码。

原因:SSH对目录和文件的权限要求非常严格,.ssh目录的权限必须为700,authorized_keys文件的权限必须为600,权限过宽会导致SSH拒绝读取公钥。

解决方式:

chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys

另一个容易被忽略的点是,你当前登录的用户必须和生成密钥的用户一致。比如用root生成密钥,就要确保远程连接时用的也是root用户。

6.4 端口不通:Web UI无法访问

现象:在宿主机浏览器上访问http://hadoop01:9870,页面一直打不开,但节点内部访问正常。

原因:最常见的是防火墙未放行端口,或者是云服务器的安全组配置没加规则。

解决方式:

systemctl stop firewalld systemctl disable firewalld

如果是在云服务器上,还需在控制台的安全组中添加9870和8088端口的入站规则。这一步容易被忽略,但实验环境对安全性要求不高的情况下,直接关闭防火墙是最快的方法。

6.5 主节点执行start-dfs.sh后从节点没有任何反应

现象:主节点上执行start-dfs.sh,只启动了本机的NameNode和DataNode,从节点上什么进程都没起。

原因:workers文件配置有问题,或者主节点没有配置到从节点的SSH免密。

解决方式:首先确认workers文件里的内容,注意文件名在Hadoop 3.x是workers,在2.x是slaves,如果你改了Hadoop版本却沿用旧教程,很可能就是在改一个不再起作用的文件。然后验证SSH免密:ssh hadoop02,如果无法免密进入,重新执行ssh-copy-id

另外一个容易犯的错误是workers文件里包含hadoop01主节点自身,如果你希望主节点不启动DataNode,就不要把它写进去。

7. 三种模式里我在实际配置中的选择建议

站在实验角度把三种模式都过了一遍的人,最后多半会回到一个问题上:实际场景中我应该选哪种模式?

我的建议很简单。如果你只是验证Hadoop安装成功没有,本地模式就够了,五分钟跑完一个WordCount,不需要处理任何配置文件的复杂度;如果你想学习HDFS的读写流程、YARN的调度逻辑,或者准备做后续的HBase、Hive集成实验,伪分布式是最合适的,因为单机就能模拟出完整链路,排错成本也低;如果你想模拟真实的集群环境,或者需要跑多个节点的实验,比如MapReduce的分布式计算效果验证、HDFS副本机制观察,完全分布式才值得你花时间搭一遍。

我见过不少同学一上来就搭三节点集群,结果配置了三天毫无进展,最后回头先把伪分布式摸透了,再回来看完全分布式就觉得豁然开朗。这背后的原因是分布式系统涉及的角色多、网络通信链路长,如果对单机版运行机制不理解,多机环境的问题会让你根本不知道从哪个日志开始看起。

就我自己而言,三台虚拟机的配置目前依然保留着,虽然实验已经结束,但后续再做Spark、Flume或者HBase的集成实验时,直接在这个集群上扩展就行,不用一切从零开始。这也是我建议你把完全分布式搭好的原因——它不只是这周实验的交付物,更是后面整个大数据学习周期的底层平台。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询