隔了小半年回头看,之前那版单节点搭建教程确实有些地方写得太想当然了。后台时不时有人来问,照着旧文走到一半卡在DataNode起不来、页面打不开、格式化完了进程还是缺两个,我一度怀疑是不是自己漏写了什么。仔细排查下来,问题基本都集中在JDK版本选择、SSH免密自测、格式化后clusterID不一致这几处,旧文确实没把这几个坑讲透。这次借着在新机器上重装测试环境的机会,把整个单节点集群搭建流程按Hadoop 3.x的现状重新捋了一遍,操作步骤全部实测过,这也是“跟韩工学Hadoop系列”第3篇的优化版正文。
先说明这篇内容适合谁:打算入门Hadoop但不想一上来就搞三台机器的人,做Hadoop课程设计需要在本地跑通MapReduce的人,以及准备大数据面试想亲手摸一遍NameNode、DataNode、ResourceManager这些核心进程的人。单节点集群,也就是常说的伪分布式模式,把HDFS和YARN的所有核心进程部署在同一台机器上,虽然只有一台物理节点,但配置项、启动流程、参数含义和真实多节点集群基本一致。按本文操作完,你会得到一套能跑WordCount、能通过Web界面观察节点状态、并且清楚每个配置文件在干什么的本地Hadoop环境。
1. 单节点集群为什么值得认真搭一次:伪分布式的边界和用途
很多初学者一上来就奔着“三台机器真集群”去,觉得单节点是玩具,搭了没用。这个想法我理解,但不太赞同。单节点集群从来不是拿来撑生产流量的,它的定位是学习、调试和验证,而这个定位恰恰决定了它在整个Hadoop学习路径上不可跳过。
1.1 伪分布式到底“伪”在哪里:从进程视角看单节点集群
伪分布式的“伪”,并不是功能阉割,而是把原本应该分散在多台服务器上的进程,全部压缩到一台机器上。以Hadoop 3.x为例,一个标准的单节点集群启动后应该有这些Java进程:
| 组件 | 守护进程 | 职责 | 主要配置文件 |
|---|---|---|---|
| HDFS | NameNode | 管理文件系统元数据、目录树、数据块映射 | hdfs-site.xml |
| HDFS | DataNode | 存储实际数据块,处理读写请求 | hdfs-site.xml |
| HDFS | SecondaryNameNode | 定期合并NameNode的edits日志,辅助恢复 | hdfs-site.xml |
| YARN | ResourceManager | 集群资源调度,分配Container | yarn-site.xml |
| YARN | NodeManager | 管理单节点上的Container生命周期 | yarn-site.xml |
在真实集群里,NameNode通常单独跑在一台机器上,DataNode各占一台,ResourceManager又在另一台机器上。单节点模式只不过是把这五个进程以多进程方式同时跑在同一台机器上,进程之间的通信走的是真实的RPC协议,文件读写走的是真实的HDFS数据流。这意味着你在单节点上学到的配置逻辑、启动顺序、故障排查思路,迁移到多节点集群时几乎可以原样复用。
有人会问,那为什么不直接用Docker起五个容器,效果不是一样吗?容器方案后面我会单独说,但初学阶段不建议。因为容器把网络、端口、环境变量这些都做了隔离和简化,很多真实集群中会遇到的问题被掩盖了,比如节点间SSH互信、hostname解析、数据目录权限这些,恰恰是面试和工作中最容易出问题的环节,裸机手动安装反而能让你把底层机制看个透。
1.2 单节点环境能帮你解决的四类实际问题
我见过很多不同身份的使用者,归纳下来单节点集群主要解决四类问题。第一是课程设计。大部分高校的大数据课设只需要提交一个能跑的MapReduce程序,比如词频统计、日志分析、天气数据排序,单节点完全够用,跑作业的逻辑和集群环境一模一样。第二是源码调试。想看NameNode启动时加载了哪些配置,想在DataNode上报心跳的代码里打日志,单节点环境是最轻量的实验场。第三是面试准备。面试官问你“NameNode和SecondaryNameNode怎么配合工作”,你如果亲手看过启动日志和HDFS Web界面上的检查点时间,回答起来和死记硬背完全不是一个层次。第四是本地开发测试。写好的MapReduce代码先在本地伪分布式跑通,再提到真实集群执行,能省掉大量排队时间。
单节点的边界也需要说清楚。它不适合做性能测试,因为所有进程争抢同一台机器的CPU和内存;也不适合模拟网络分区、节点宕机这类分布式故障。这些内容应该留到多节点集群或者后续的HA章节去实践。搞明白单节点能做什么、不能做什么,你就不会对它抱有不切实际的期待,也不会因为“只有一个节点”而轻视它。
2. 动手前必须先过的三道关:JDK版本、SSH免密和目录规划
很多搭建教程一上来就贴配置文件,但实际操作中卡住的往往不是配置文件本身,而是环境前置条件。这次优化版把这部分单独拉出来,是因为我实测下来一大半的“起不来”都和这三件事有关。
2.1 JDK版本选择:Hadoop 3.x官方支持线是Java 8和11,别装太新
先说结论:Hadoop 3.3.x版本官方支持Java 8和Java 11,你在这两个版本里选一个就好。我自己测试环境用的是Java 8,稳定省心。
为什么不要装Java 17甚至更高?Hadoop的很多核心组件在编译时针对JDK 8做了优化,升级到更高版本JDK后,会遇到两类典型问题。一类是启动时报UnsupportedClassVersionError或者直接无法加载Native库;另一类是跑MapReduce作业时出现各种奇怪的序列化异常。这些问题的根因不是你的代码有bug,而是Hadoop官方在3.3.x版本里只做了一定程度的高版本JDK适配,很多第三方依赖并没有完全跟上。网上确实有人用Java 17跑通Hadoop的教程,但那是额外折腾了一堆补丁和编译参数的结果,入门阶段完全没必要给自己加这个难度。
安装JDK时还容易踩一个坑:系统自带的OpenJDK可能已经存在,但版本是系统默认的较新版本。装完Hadoop后跑java -version,看到的是系统默认版本而不是你装的那个,Hadoop脚本又会诚实地去读JAVA_HOME。所以装完JDK后建议你确认两件事:
java -version echo $JAVA_HOME如果JAVA_HOME为空,或者指向了错误路径,在/etc/profile里补上并刷新环境变量。
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 export PATH=$PATH:$JAVA_HOME/bin source /etc/profile2.2 SSH免密登录:设置完一定要自测,否则启动脚本会卡住
Hadoop的启动脚本会通过SSH免密方式连接到localhost并拉起各个进程。这一步很多人觉得无所谓,直接跳过,结果执行start-dfs.sh时看到要求输入密码,或者报错Connection refused,整个过程直接卡住。
设置SSH免密的标准流程不复杂,但要注意每一步的权限和路径。
ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys chmod 700 ~/.ssh然后在同一台机器上自测:
ssh localhost如果不需要输入密码直接进了新会话,说明免密配置生效。这里有个容易被忽视的细节:自测时用ssh localhost,但Hadoop启动脚本里访问的可能是你的机器hostname,比如ssh myhost。如果hostname解析不到127.0.0.1,会导致即使ssh localhost通了,启动脚本仍然卡住。所以更稳妥的做法是在/etc/hosts里加一行:
127.0.0.1 localhost your_hostnameyour_hostname换成你机器实际的主机名,可以用hostname命令查看。这一步在虚拟机上安装Hadoop时尤其重要,因为虚拟机的网络配置经常导致主机名解析异常。
提示:很多教程让你配置主机名映射的时候只写了
localhost,没写你实际的主机名。Hadoop脚本默认会使用hostname命令的结果作为当前节点地址,真正容易出问题的就是这里。这一步做完务必ssh 你的主机名再测一次。
2.3 目录规划和HADOOP_HOME环境变量:决定你之后升级和排障的顺畅度
安装路径和数据路径尽量分开规划。Hadoop程序目录放/opt/hadoop,数据和元数据目录放独立路径,比如/home/hadoop-user/data目录,而且目录所有者必须是启动Hadoop的用户,否则后续启动会遇到权限不足的问题。
下载Hadoop安装包时,认准Apache官网或国内镜像上的“已编译”二进制包。有些教程会让你自己用Maven编译源码,那是特殊环境下的需求,入门阶段完全没必要。下载的文件名类似hadoop-3.3.6.tar.gz,下载完解压到/opt/hadoop。解压后配置环境变量:
export HADOOP_HOME=/opt/hadoop/hadoop-3.3.6 export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop这里面的HADOOP_CONF_DIR很多人容易漏,但Hadoop后续读取配置文件时首先找这个变量。如果你发现改了配置文件后启动行为没变化,多半是这个变量没有生效,导致Hadoop读取了默认路径。配置完环境变量后,可以用hadoop version检查安装是否正常,这一步通过后开始进配置环节。
3. 四个配置文件逐项拆解:每个参数都说明白为什么要这么配
很多人喜欢直接拿现成的配置模板复制粘贴,跑通了就完事。但这样做的风险是,一旦报错你根本不知道错在哪,因为你不理解每个参数的作用。我建议至少花半小时把下面几个文件过一遍,它们都在$HADOOP_HOME/etc/hadoop目录下。
3.1 core-site.xml:fs.defaultFS和hadoop.tmp.dir这对关键配置
core-site.xml是Hadoop的核心配置,最值得关注的是两个参数。第一个是fs.defaultFS,它决定了Hadoop文件系统的默认地址。单节点模式下设置为hdfs://localhost:9000,其中9000是NameNode接受客户端连接的RPC端口。第二个是hadoop.tmp.dir,这个参数非常多人踩坑。默认值指向系统临时目录/tmp/hadoop-${user.name},开机重启后系统会清理临时文件,导致NameNode元数据丢失,启动时报各种找不到路径的错误。
正确做法是把临时目录和数据目录都指向持久化路径:
<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/home/hadoop-user/data/tmp</value> </property> </configuration>确认这个目录已经创建并且当前用户可写。fs.defaultFS设置成hdfs://localhost:9000后,你在命令行里执行hdfs dfs -ls /这类操作时,Hadoop自动知道该连哪个NameNode,不需要每次手动指定完整路径。
3.2 hdfs-site.xml:副本数、NameNode目录、DataNode目录
hdfs-site.xml是HDFS的核心配置。单节点模式下有几个值需要重点调整。
第一个是dfs.replication,副本数。真实集群中一般默认3,即一个数据块在三台机器上各存一份,用于容灾。但单节点只有一台机器,如果副本数保持3,DataNode会不断尝试在同一个节点上复制同一个块,最终因为无法达到副本数而进入安全模式或者一直报块缺失。单节点必须把这个值改为1。
第二个是dfs.namenode.name.dir,NameNode元数据的存储路径。默认情况下这个目录在hadoop.tmp.dir下面,问题仍然出在临时目录被清空。建议改成之前规划的持久化目录。
第三个是dfs.datanode.data.dir,DataNode数据块的存储路径。同样建议指定到持久化目录。
<configuration> <property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:///home/hadoop-user/data/namenode</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:///home/hadoop-user/data/datanode</value> </property> </configuration>注意file:///前缀不能少。如果你看到某些教程里没有这个前缀,那是把本地文件系统路径和HDFS路径搞混了。这里的参数是指本地磁盘上的物理路径,必须用file://协议前缀。
3.3 yarn-site.xml和mapred-site.xml:把资源调度和计算框架接起来
YARN负责资源调度,MapReduce跑在YARN之上。这两个文件配合工作时,有一个标志性配置不能漏。
yarn-site.xml中,yarn.nodemanager.aux-services必须设置为mapreduce_shuffle。Shuffle是MapReduce框架在Reduce阶段从Map端拉取中间结果的机制,NodeManager需要这个辅助服务来配合完成。如果不配置,作业会卡在Map完成后的Shuffle阶段,日志里报错各种Shuffle相关的异常。
mapred-site.xml中,mapreduce.framework.name必须设置为yarn。这个参数告诉Hadoop:MapReduce作业提交到YARN集群上运行,而不是本地模式。如果你忘了配置这个文件,程序可能会以本地模式运行,表面上“能跑通”,但完全不是分布式执行,失去了学习意义。
<!-- yarn-site.xml --> <configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> </configuration><!-- mapred-site.xml --> <configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration>3.4 配置完成后先自查:一个命令看穿所有配置错误
配置改完后,用hadoop checknative检查Native库加载情况,用hadoop version确认版本信息,然后重点确认一件事:配置文件目录是否真的指向你改的那份配置。
最简单的自查方法是查看Hadoop启动时的日志路径。启动日志里会明确打出Configuration: /opt/hadoop/hadoop-3.3.6/etc/hadoop/core-site.xml这类信息。如果打出来的路径不是你以为的那个,说明HADOOP_CONF_DIR没生效。另一个方法是直接在core-site.xml里故意写一个明显的错误值,然后用hdfs getconf -confKey fs.defaultFS读取,如果返回不符预期的值,说明配置读取有问题。这个技巧排查环境变量异常时非常高效。
4. 首次启动的完整操作流:格式化、启停顺序、验证三板斧
配置完文件后,真正的考验才开始。首次启动最怕的就是不知道步骤之间的依赖关系,上来就start-all.sh,出错了也不知道是哪个环节引起的。我把完整的首次启动流程拆开,每一步都告诉你为什么要这么做。
4.1 格式化NameNode:一个只能执行一次的关键操作
格式化是在NameNode上初始化文件系统元数据的过程。执行方式:
hdfs namenode -format看到“Storage initialized”或者类似日志说明格式化成功。格式化会做几件事:生成Cluster ID、Block Pool ID、创建NameNode的目录和VERSION文件。这些信息之后DataNode启动时会和NameNode核对,如果两边对不上,DataNode会拒绝连接。
这里必须强调一个原则:格式化操作正常执行一次就够了,不要反复执行。很多人因为后续启动报错,就重新格式化,结果DataNode之前的运行记录还在,clusterID和新格式化的不一致,导致DataNode永远启动不了,也就是我标题里说的那种“单节点集群搭建”最容易翻车的操作。如果你想重置整套环境,正确的做法是停掉所有进程,清掉namenode和datanode两个目录里的数据文件,再重新格式化。只执行格式化而不清理datanode数据,几乎必然踩中clusterID不匹配的坑。
提示:格式化时把日志里输出的
cluster ID复制下来记一下,排查DataNode无法启动时会用到。这个方法虽然土,但排查效率比在日志里翻强得多。
4.2 启动脚本的依赖关系:先HDFS,后YARN,原因很现实
启动命令建议分开执行,而不是偷懒跑start-all.sh:
start-dfs.sh start-yarn.sh先启动HDFS有两个原因。第一,YARN的ResourceManager在初始化时可以感知到HDFS上的文件系统状态,如果HDFS没就绪,资源调度器的某些状态可能不对。第二,启动HDFS时NameNode会先进入安全模式,等待足够的DataNode上报数据块报告,这个过程需要一点时间。如果你同时启动HDFS和YARN,日志混在一起很难分辨哪个组件报错。分开执行、逐步确认,排障时思路会清晰很多。
启动过程会通过SSH连接localhost,每个节点拉起进程后,屏幕输出“starting namenode, logging to /opt/hadoop/logs”之类的信息。等命令执行完,JPS检查开始。
4.3 验证三板斧:jps、Web界面、跑一次WordCount
这一步是验证你的Hadoop环境是否真正可用。第一板斧是jps,这个命令列出当前用户启动的所有Java进程。一个健康的单节点Hadoop环境,jps输出应该包含:NameNode、DataNode、SecondaryNameNode、ResourceManager、NodeManager。缺哪个,对应的组件就有问题。
第二板斧是Web管理界面。Hadoop 3.x版本两个端口和2.x不同,这一点是很多人用旧教程时卡住的重灾区。
| 组件 | Web界面地址 | 说明 |
|---|---|---|
| NameNode | http://localhost:9870 | 查看HDFS文件系统、DataNode列表 |
| ResourceManager | http://localhost:8088 | 查看YARN集群状态、作业运行情况 |
如果页面能打开,能看到一个活的NameNode状态、DataNode节点数显示1,说明HDFS没问题。8088页面上能看到Active Nodes为1,并且这里也提供了“Run a wordcount example”这类快捷入口。
第三板斧也是最有说服力的一步:在HDFS上创建目录,上传一个文本文件,用Hadoop自带的示例包跑WordCount。具体命令:
hdfs dfs -mkdir -p /user/hadoop/input echo "hello world hello hadoop" > /tmp/test.txt hdfs dfs -put /tmp/test.txt /user/hadoop/input/ hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar wordcount /user/hadoop/input /user/hadoop/output hdfs dfs -cat /user/hadoop/output/part-r-00000最后一条命令能看到每个单词出现次数,任务就算真正跑通了。这一步包含了HDFS文件上传、MapReduce作业提交、YARN容器调度、任务执行和结果回写,是检验环境可用性的“期末考试”。
5. 单节点集群的故障速查:从日志侧和进程侧排查问题
前面的流程走完,正常情况下环境是可用的。但万一没走通,这个章节按排查链路把单节点最常见的三个问题讲透,每个问题都从“怎么发现”开始,而不是直接给结论。
5.1 DataNode进程消失或启动后立刻退出:多半是clusterID不匹配
典型表现:执行start-dfs.sh后jps能看到NameNode和SecondaryNameNode,但DataNode这一行要么没有,要么几分钟后自动消失。第一次遇到这个现象不用慌,按这个链路排查。
先看DataNode的日志,位置在$HADOOP_HOME/logs目录下,文件名类似hadoop-hadoop-datanode-机器名.log。打开日志搜索clusterID,一般会看到类似“Incompatible clusterIDs”或者“does not match”的报错。原因我之前提过:格式化NameNode时生成了新的clusterID,而dataNode目录之前已经有旧版本的clusterID,两边核对不一致,DataNode拒绝上报NameNode。
修复方式有两种。第一种是彻底重置法,适合环境刚搭、没有重要数据的时候:
stop-dfs.sh rm -rf /home/hadoop-user/data/namenode/* rm -rf /home/hadoop-user/data/datanode/* hdfs namenode -format start-dfs.sh第二种是保留label修复:手工修改datanode目录下VERSION文件里的clusterID,让它和namenode目录下VERSION里的值一致。这个方式适合数据量不大但不想重新格式化的场景。找到两个VERSION文件,把datanode一侧的clusterID改成namenode一侧的值,然后重启DataNode即可。第二种方式不需要重新格式化,相对温和,但你要手动操作,注意备份。
从排查链路的角度说,上面两个方案的起点都是“先看日志,再动数据”,这是排障的基本功。永远不要在没看日志的情况下盲目删除数据目录重来,那样虽然可能碰巧解决,但你会失去定位问题根因的机会。
5.2 Web界面打不开或外部机器访问受限
典型表现:本机curl能访问localhost:9870,但局域网内另一台机器浏览器打不开。这个问题多半不是Hadoop配置的问题,而是当前机器防火墙策略和端口监听范围。
首先确认9870端口被正确监听:
ss -tlnp | grep 9870输出说明NameNode的Web服务在监听。如果是0.0.0.0:9870,说明监听所有网卡;如果只监听127.0.0.1:9870,需要检查dfs.namenode.http-address是否没有配置为0.0.0.0。在hdfs-site.xml中显式配置:
<property> <name>dfs.namenode.http-address</name> <value>0.0.0.0:9870</value> </property>其次检查防火墙。Linux下常见防火墙分为ufw和firewalld两类,查看是否放行了9870和8088端口。测试环境图省事的话,可以临时关闭防火墙验证端口是否通了,通后再决定是放行端口还是永久关闭防火墙,生产环境则一定要保持防火墙开启并精确放行端口。虚拟机场景下还要额外确认虚拟网络设置是否启用了端口转发或桥接模式。
5.3 YARN作业一直处于ACCEPTED状态或Container反复失败
典型表现:提交WordCount后,8088页面上作业一直处于ACCEPTED,或者能看到作业运行但Container日志反复报内存溢出。
原因在于YARN默认的容器内存参数在低配机器上过于激进。ResourceManager需要为单个Container分配内存,而默认yarn.nodemanager.resource.memory-mb以及yarn.scheduler.maximum-allocation-mb这些值通常按8GB甚至更大内存的物理机配置。如果你的测试机总内存只有8GB,再算上NameNode、DataNode、操作系统占用的内存,留给YARN容器用的可能不够,容器就会因为申请内存失败而不断重试。
解决方案是在yarn-site.xml里显式调低资源上限,按实际物理内存的一半以上量级设置:
<property> <name>yarn.nodemanager.resource.memory-mb</name> <value>4096</value> </property> <property> <name>yarn.scheduler.maximum-allocation-mb</name> <value>4096</value> </property> <property> <name>yarn.scheduler.minimum-allocation-mb</name> <value>512</value> </property>修改后重启YARN。这个坑在低配笔记本上极其常见,但日志提示往往不会直接告诉你“内存参数不合理”,而是表现为Container反复失败。遇到就优先检查YARN资源参数。
6. 单节点不是终点:向多节点集群、ZooKeeper和Docker化延伸的思路
环境搭好、WordCount跑通,单节点集群搭建这一步就算完整闭环了。但如果你学Hadoop的目标不止于应付课设,接下来的延伸方向可以按这个次序考虑。
6.1 从单节点到多节点:最低成本的迁移路径
单节点配置改成多节点,核心是改三个地方。第一,把core-site.xml里的fs.defaultFS从localhost:9000改成NameNode所在机器的hostname或IP,例如hdfs://hadoop-master:9000。第二,在/etc/hosts里配置所有节点的主机名映射,包括master和slaves节点。第三,创建workers文件(Hadoop 3.x中叫workers,2.x中叫slaves),列出所有DataNode或NodeManager的主机名。
迁移的常见误区是分别到每一台机器上去手工改配置文件。推荐做法是先在master上把配置改好,然后用scp或rsync同步到所有节点,再逐台启动。这样能保证配置文件完全一致,避免因为某台机器少一个参数导致节点间行为不一致,排查起来非常痛苦。
6.2 ZooKeeper在HA架构里的位置,以及什么时候值得开始学
单节点集群没有单点故障问题,因为只有一台机器,挂了就是全挂。但学习HA(High Availability)时,ZooKeeper是绕不开的组件。Hadoop HA架构中,ZooKeeper用于协调Active NameNode和Standby NameNode的选举切换。Hadoop 3.x的ResourceManager HA同样依赖ZooKeeper。
建议的学习路径是:先把本地单节点环境用熟练,包括文件读写、作业提交、日志查看,然后尝试搭建一个三节点的HA测试环境,再引入ZooKeeper来模拟NameNode故障时的自动切换。如果一上来就同时学ZooKeeper和Hadoop,概念太多容易混淆。课程设计和面试里常问的“NameNode HA如何实现自动故障转移”,本质上是在问ZooKeeper的选举和分布式锁机制,花时间把这两个组件的协同逻辑理清,收获会非常大。
6.3 Docker镜像适合学习和不适合学的地方
Docker方式搭建Hadoop这几年越来越流行,很多网上热词都在讨论“hadoop的docker镜像”。确实,一条docker compose up就能拉起一个多节点拓扑的Hadoop集群,对快速验证框架行为特别方便。
但我不建议完全用Docker替代手工搭建。原因在于Docker容器将网络通讯、数据卷、进程管理全部抽象掉了。你无法切身感受SSH免密配置的过程,看不到hostname解析失败时的报错,也难以理解为什么某台容器里的DataNode始终起不来。这些“麻烦”恰恰是分布式系统运维的核心知识。折中方案是:先用裸机方式搭好一个单节点,理解清楚了,再用Docker方式去搭建一个多节点环境,专门用来做更复杂的实验,比如HA切换、资源队列测试。这样两条路都走一遍,你的知识才是立体的,而不是只会复制粘贴某个镜像里的配置。
写到这,这台测试机上的单节点Hadoop环境我已经重搭完一遍了。还是那句话:配置不熟的时候慢慢来,宁可每一步都敲命令验证,也不要一口气执行完再回头查。尤其是格式化和目录清理这类破坏性操作,动之前一定想清楚。学Hadoop就像爬山,单节点是山脚的第一段路,路走扎实了,后面多节点、HA、源码阅读才有真正的地基。