2026/10/9 15:58:29

Hadoop零基础入门:从伪分布式到集群与HA高可用实战

Hadoop零基础入门:从伪分布式到集群与HA高可用实战 如果你正准备转行大数据或者已经在准备相关岗位面试Hadoop基本是绕不开的第一道坎。很多教程一上来就甩名词HDFS、MapReduce、YARN、NameNode、DataNode……看十分钟直接劝退。这篇文章我用一套自己能完整跑通的路径来拆解从“到底在解决什么问题”讲到单机伪分布式搭建再扩展到三节点集群和HA高可用最后用一个WordCount任务把InputSplit这类高频面试点也串进去。适合零基础、准备第一次搭环境、以及面试前去补底层概念的人。1. 先搞明白Hadoop解决的是什么问题从单机装不下的场景说起1.1 一个日志翻倍的业务场景假设你在一家小电商公司业务量涨得很快每天产生的访问日志从几GB变成几十GB统计脚本越跑越慢。你接手了一个需求统计最近三十天用户最常搜索的Top 100商品词。用单机程序去读几十GB日志内存直接爆掉即使硬着头皮跑完也要几个小时。这时候你面对的其实是三个问题单机存储装不下、单机算力不够用、磁盘和机器一旦坏了数据就全完。Hadoop的原始设计目标就是解决这三个问题的。它的思路很朴素用一堆普通机器代替一台超级计算机。每台机器只负责一部分数据存储压力被分散计算也被分散单台坏了还有别的机器上的副本数据不丢。这个思路放到今天仍然是大数据生态的地基。Hadoop不是某个单一软件它是一套分布式基础架构包含存储、计算、资源调度三块。弄懂这三块之间的关系后面所有大数据技术栈都会顺很多。1.2 三大组件不是一个东西HDFS、MapReduce、YARN各管一段HDFS是分布式文件系统负责存储。文件会被切成固定大小的块默认128MB一块分散存到集群不同机器上每块默认保存3份副本。你可以类比成图书馆把一本书拆成很多章节每个章节复印三份放在不同分馆其中一个分馆失火另外两个还能凑出完整内容。MapReduce是分布式计算框架负责算。它把一个大任务拆成Map映射和Reduce归约两个阶段。Map阶段在数据所在节点上做初步处理Reduce阶段把结果汇总。打个比方老板要统计一万个仓库的库存他不会让所有仓库把货拉到总部而是让每个仓库各自报数最后汇总。MapReduce的基本思想就是数据不动、计算动把程序分发到数据附近执行。YARN是资源调度层负责管。它统一管理整个集群的CPU和内存资源决定某个任务能用多少资源、跑到哪些节点上。没有YARN多个框架同时抢资源会乱套。这三者关系可以简单理解成HDFS是仓库MapReduce是加工流水线YARN是排班系统。现在很多文章把Hadoop直接说成“大数据操作系统”虽然不完全准确但对新手理解定位是有帮助的。1.3 版本选型为什么我建议直接上3.3.x市面上的教程从Hadoop 1.x到3.x都有1.x基本见不到了2.x资料最多但属于“考古级”。我自己现在的习惯是直接装Apache Hadoop 3.3.x原因有三一是和当前主流生态组件兼容性最好Spark、Flink跑在上面都正常二是原生支持HA高可用中的多个NameNode场景面试被问到也不至于说错版本三是最新版资料渐渐多起来踩坑反而容易搜到答案。我在虚拟机里用的是hadoop-3.3.6搭配OpenJDK 8。这个组合我自己测试下来最稳不建议一上来就搞最新版加最新JDK的组合后面排障会非常痛苦。2. 环境准备不是小事虚拟机、JDK版本和SSH免密的真实考量2.1 一台还是三台先想清楚你要练什么学习路径上我强烈建议分两步先在单台虚拟机上搭伪分布式跑通之后再扩成三节点集群。伪分布式意味着所有进程都跑在同一台机器上但它包含了完整的NameNode、DataNode、ResourceManager、NodeManager这些进程你能学到完整的启动流程、配置方法和日志排查一个人就能模拟一整条链路。如果直接上三台集群很多新手会因为网络、免密、配置同步的问题连环境都起不来更别说深入学习。单台虚拟机配置建议内存至少4GB硬盘40GB起步我实际训练用的4GB内存加上2核CPU跑伪分布式的WordCount任务完全没问题。如果到了三节点集群阶段每台虚拟机给2-3GB内存整体物理机内存别低于16GB。也可以用现成的Docker镜像快速起一个Hadoop环境。但我不建议零基础一上来就用镜像因为镜像里的配置路径、版本和自己装的往往有差异出了问题你连日志在哪都找不到反而更乱。2.2 JDK版本选错了后面全是泪Hadoop是用Java写的所以环境里必须有JDK。Hadoop 3.3.x官方支持Java 8和Java 11我推荐OpenJDK 8。为什么不用Java 17Hadoop脚本在解析某些参数时对版本敏感Java 17默认不支持我试过会直接报不兼容错误。安装完成后不要只配PATH一定要在/etc/profile或者~/.bashrc里设置JAVA_HOME。Hadoop的启动脚本会主动查找JAVA_HOME如果找不到会报“JAVA_HOME is not set”直接退出。很多新手只在命令行能敲出java -version就以为配好了结果启动Hadoop时报错排查才知道问题出在这。另外HADOOP_HOME也要配建议把$HADOOP_HOME/bin和$HADOOP_HOME/sbin都加进PATH这样后面敲命令方便很多。这里顺便说一个Windows本地开发的问题如果你在Windows上跑MapReduce本地模式光配JAVA_HOME不够还会遇到“Failed to locate the winutils.exe in the Hadoop binaries”的报错。这是Hadoop在Windows上需要一份和版本对应的已编译bin目录里面要有winutils.exe和hadoop.dll然后把HADOOP_HOME指到这份已编译的Hadoop包。这类问题在Windows环境做开发时很常见面试偶尔也会被问到心里有数就行。2.3 SSH免密集群自动化启动的前提Hadoop的start-dfs.sh、start-yarn.sh脚本本质上是远程SSH到各个节点去启动进程。如果不配置免密每启动一个进程就要输一次密码集群根本跑不起来。很多第一次搭集群的人卡在这一步还以为是集群配置写错了。配置步骤其实简单用ssh-keygen -t rsa -P -f ~/.ssh/id_rsa生成密钥对然后ssh-copy-id把公钥拷贝到本机和其他节点。注意伪分布式阶段也要配因为脚本会通过SSH连接localhost来启动本地进程。我在第一次学习时生成密钥后忘记ssh-copy-id localhost结果start-dfs.sh时一直要密码整整排查了一下午。这个细节网上很多教程有提但真正操作的时侯特别容易漏掉。3. 伪分布式搭建五份配置文件折腾明白你就入门了3.1 下载解压与环境变量先到Apache官网下载hadoop-3.3.x的tar.gz包。下载好后解压到/opt/hadoop目录sudo tar -zxvf hadoop-3.3.6.tar.gz -C /opt sudo mv /opt/hadoop-3.3.6 /opt/hadoop然后编辑/etc/profile加入以下几行export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64 export HADOOP_HOME/opt/hadoop export PATH$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin改完执行source /etc/profile用hadoop version验证是否生效。这一步出错常见于JAVA_HOME路径写错可以先去/usr/lib/jvm确认一下实际路径。3.2 五份核心配置文件的每一行含义Hadoop的配置集中在$HADOOP_HOME/etc/hadoop目录下伪分布式只需要关注五份文件。第一份是hadoop-env.sh。找到里面的export JAVA_HOME改成你的JDK路径这是启动脚本读取Java位置的兜底入口。很多教程说“这里一般不用改”但我的习惯是无论如何都显式写上避免后续环境变量异常时脚本找不到Java。第二份是core-site.xml它定义集群的全局属性。核心配置如下configuration property namefs.defaultFS/name valuehdfs://localhost:9000/value /property property namehadoop.tmp.dir/name value/data/hadoop/tmp/value /property /configurationfs.defaultFS告诉客户端NameNode在哪儿这是整个HDFS的入口地址。hadoop.tmp.dir默认是/tmp/hadoop-${user.name}系统一旦重启临时文件被清空NameNode元数据丢了又要重新格式化。我自己的实践是统一指定到/data/hadoop/tmp这也是生产环境的标准做法。第三份是hdfs-site.xml指定HDFS的存储相关参数configuration property namedfs.replication/name value1/value /property property namedfs.namenode.name.dir/name value/data/hadoop/name/value /property property namedfs.datanode.data.dir/name value/data/hadoop/data/value /property /configuration伪分布式只有一台DataNode副本数必须设成1否则写入的数据永远达不到副本要求NameNode会一直停留在安全模式看起来像整个集群卡死。这里也是新手最常见的坑之一。第四份是mapred-site.xmlHadoop 3.x下载包中默认叫mapred-site.xml.template需要先复制出mapred-site.xmlcp $HADOOP_HOME/etc/hadoop/mapred-site.xml.template $HADOOP_HOME/etc/hadoop/mapred-site.xml里面配置一行核心参数configuration property namemapreduce.framework.name/name valueyarn/value /property /configuration这行告诉MapReduce任务跑在YARN上而不是本地模式。不配的话任务会在本地独立运行你根本看不到分布式调度的效果。第五份是yarn-site.xml指定资源调度器的辅助服务configuration property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property /configurationMap和Reduce之间要交换中间数据这个过程叫ShuffleNodeManager必须知道用什么辅助服务来支持它。不配这一项Map跑完输出结果后Reduce接不到数据任务会一直卡住。这份文件的目录结构也可以顺手确认一下$HADOOP_HOME/etc/hadoop里还会有workers文件伪分布式阶段保持默认内容为localhost即可。3.3 格式化与启动为什么顺序不能乱配置改完之后先启动HDFS前要格式化NameNode命令如下hdfs namenode -format格式化的本质是初始化NameNode的元数据目录生成clusterID。这条命令执行的时候会看到很长一串日志不用怕最后出现“successfully formatted”就算成功。如果第二次重复执行Hadoop会提示“has been successfully formatted again”但你要警惕格式化次数越多DataNode的clusterID和新NameNode越容易不一致这是后面DataNode起不来的根源。格式化完成后依次启动start-dfs.sh start-yarn.sh两者顺序尽量不要颠倒。启动之后用jps命令验证进程正常能看到五个Java进程NameNode、DataNode、SecondaryNameNode、ResourceManager、NodeManager。3.4 用jps和Web页面确认集群健康jps是Java自带的小工具专门列出当前Java进程。看到五个进程都在说明伪分布式基本搭建成功。少一个就可能有问题比如DataNode没起来需要去日志目录排查。Hadoop的日志在$HADOOP_HOME/logs下不同进程有各自的日志文件比如hadoop-hadoop-datanode-你的主机名.log。看日志习惯先看结尾部分的Exception或ERROR不要从头往后翻效率太低了。最后打开浏览器访问http://localhost:9870这是HDFS的NameNode Web界面。另外访问http://localhost:8088这是YARN的ResourceManager界面。两个页面能打开且能看到活着的节点信息环境才算真正跑通了。4. 升级到集群节点角色、同步配置和HA高可用的完整思路4.1 三节点角色分配谁当领导、谁干活伪分布式跑通之后集群只是顺水推舟的事情。三节点的经典分配方式如下节点角色职责masterNameNode、ResourceManager、SecondaryNameNode管理元数据、调度资源、定期合并元数据镜像worker1DataNode、NodeManager存储数据块、执行容器中的计算任务worker2DataNode、NodeManager存储数据块、执行容器中的计算任务NameNode是集群的“大脑”专门管理文件系统的目录树和文件块位置DataNode是“手脚”负责真正存储数据和处理读写请求。ResourceManager是YARN的大脑NodeManager是每台机器上的执行者。生产环境里通常会把NameNode和ResourceManager分开部署避免单台机器压力过大。但学习阶段放在master一台机器上没有太大问题关键是理解角色逻辑NameNode和ResourceManager负责管理决策DataNode和NodeManager负责干活。4.2 集群搭建的关键步骤配置同步与只格式化一次干活的机器可以基于同一台虚拟机模板克隆保证三台机器的JDK、Hadoop版本完全一致。克隆完成后需要做几件事分别修改三台机器的hostname和固定IP。CentOS改hostname用hostnamectl set-hostname masterUbuntu则改/etc/hostname文件然后确认/etc/hosts里写入三台机器的IP和hostname映射。保证三台机器使用同一个系统用户。我建议统一创建一个hadoop用户把Hadoop目录归属权也改成它避免不同机器用户不同导致权限错乱。配置master到三台机器的SSH免密包括master到自身。修改master上的core-site.xml把fs.defaultFS从hdfs://localhost:9000改成hdfs://master:9000。修改$HADOOP_HOME/etc/hadoop/workers文件把localhost删掉改成worker1和worker2的主机名每行一个。注意Hadoop 3.x的文件名是workers不是老版本的slaves。把master上的整个配置同步到worker节点最简单的命令是scp -r $HADOOP_HOME/etc/hadoop hadoopworker1:/opt/hadoop/etc/。这些做完了再到master上执行一次hdfs namenode -format然后启动。我把这个整理成一句口诀配置同步到位、仅在master格式化一次、启动只看master。三节点起来后在master执行jps能看到NameNode、ResourceManager、SecondaryNameNode分别到worker1和worker2执行jps能看到DataNode和NodeManager。如果你在自己机器上测了好几台集群启动后worker的DataNode一直起不来先别急着看配置文件大概率是刚才说的clusterID不一致。格式化NameNode会生成新的clusterID而worker上存储的DataNode目录还保存着旧clusterID两边对不上DataNode直接罢工。4.3 HA高可用ZooKeeper在里面到底负责什么单点故障是大数据系统的噩梦。整个HDFS只有一个NameNode它要挂了整个文件系统就不可用了。HA的方案是部署两个NameNode一个Active一个StandbyStandby实时同步Active的元数据变更。Active挂了Standby自动升级为Active客户端无缝切换。这里需要两个配套组件。JournalNode负责保存元数据变更日志Active NameNode把每一次修改都写到JournalNodeStandby持续读取并应用到内存保持两个NameNode状态一致。ZooKeeper负责选主和故障切换这里面有一个关键角色叫ZKFCDFSZKFailoverController它跟NameNode部署在同一台机器上负责监控NameNode健康状态。一旦Active NameNode失联ZKFC会触发自动切换并通过fencing机制把旧Active踢掉防止两个节点同时认为自己Active也就是脑裂。这就是“Hadoop和ZooKeeper整合实战”的核心场景。ZooKeeper集群通常部署3个节点奇数个成员才能通过多数派投票选出唯一Active。具体配置时需要在core-site.xml加ha.zookeeper.quorum在hdfs-site.xml里配置nameservices、两个NameNode的RPC地址、JournalNode地址还要执行hdfs zkfc -formatZK初始化ZooKeeper状态。我的建议是入门阶段先把这个原理理解透不要急着在虚拟机里配完整HA。因为HA涉及ZooKeeper、JournalNode、ZKFC三层角色任何一个节点配置错了排障的时候你会同时面对多个层面的问题对新手打击非常大。先把三节点普通集群跑熟练能熟练定位日志和进程异常再考虑部署HA效果会好很多。5. 第一次运行任务WordCount背后隐藏的InputSplit原理5.1 三步跑通WordCount示例集群搭好后用官方自带的WordCount例子验证整个流程。第一步准备输入数据在HDFS上建目录并上传文件hdfs dfs -mkdir -p /input hdfs dfs -put /data/test.txt /input第二步提交任务。Hadoop安装包自带示例jar包位置在$HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar执行hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar wordcount /input /output这里有个重要细节输出目录/output在任务运行前必须不存在否则MapReduce直接报“Output directory already exists”。这个错误非常常见我自己初学时反复遇到好几次。第三步查看结果hdfs dfs -cat /output/part-r-00000能看到每个词和对应的统计次数。如果一切顺利说明存储、计算、调度整条链路都通了。5.2 InputSplit面试题背后的数据本地性逻辑很多面试都会问“什么是InputSplit”这也是一个被热点词带着高频出现的问题。我用大白话解释一下。MapReduce把输入数据划分成若干个逻辑分片每个分片叫InputSplit一个InputSplit对应一个Map任务。关键点在于InputSplit是一个逻辑概念不是物理文件的块。默认情况下一个InputSplit的大小等于一个HDFS Block也就是128MB。为什么这样设计是数据本地性原则的体现NameNode的元数据可以快速告诉我们某个split对应的block分布在哪些DataNode上YARN调度时会优先把Map任务分到存有该block的DataNode上运行。计算移到数据旁边省掉大量跨机器网络拷贝。在WordCount场景里输入文件被切分成split之后每个split会交给一个RecordReader解析。默认的TextInputFormat按行读取文本把每行的字节偏移量作为key整行内容作为value输入到Map阶段。Map阶段做分词输出每个单词和1Shuffle阶段按单词分组后Reduce阶段把相同单词的1累加得到最终结果。面试时如果能主动说出“InputSplit是Map任务的输入逻辑单元默认大小和Block对齐是为了数据本地性”基本就能拿分。5.3 运行任务时最常见的两类失败第一类是任务提交后卡住不动Client一直显示进度0%。优先去YARN的8088页面看Application状态再进日志查看。如果没开启日志聚合需要登录运行节点到$HADOOP_HOME/logs/userlogs目录下找对应application的日志。第二类是依赖问题。WordCount这种官方示例不会踩坑但你以后写自己的MapReduce程序如果用了第三方依赖jar包集群节点上没有运行时就会报ClassNotFoundException。解法是用-libjars参数把依赖带上或者把依赖打进一个fat jar提交。这个问题在我带过的人里出现频率很高提前留个印象。6. 排错笔记那些让新手熬夜的Hadoop经典故障6.1 DataNode起不来clusterID不一致的经典坑症状jps看不到DataNode但NameNode正常。看日志会发现提示NameNode的clusterID和DataNode存储的clusterID不一致。原因格式化NameNode后它生成了一个新的clusterID。而DataNode的dfs.datanode.data.dir指定的目录里保留着之前写入的clusterID。两边不一致DataNode拒绝启动。解决停掉集群把/data/hadoop/data和/data/hadoop/name下的内容都清空然后重新执行hdfs namenode -format再启动。这个操作会清掉已有数据但是新手阶段没有真实业务数据损失可以忽略。这里我的建议很直接除非必要不要反复格式化NameNode。每次格式化都会生成新集群身份数据目录不匹配就会连锁报错。很多教程让你“多格式化几次没关系”实操下来完全不是那么回事。6.2 安全模式卡死先别急着leave症状刚启动完集群执行hdfs dfs -put时报“Name node is in safe mode”。安全模式是NameNode启动初期的一种保护状态只读不可写目的是让NameNode先加载元数据并等待数据块上报。正常情况下等副本数量达到要求后自动退出。如果一直停在安全模式通常说明整体可用数据块比例不达标。不要一上来就执行hdfs dfsadmin -safemode leave。虽然能强制推出但根因没解决后续写入可能丢数据。正确的排查方式是用hdfs dfsadmin -report看当前活的DataNode和块副本情况。如果副本数一直为0先检查DataNode是否真的启动、进程是否存活。如果刚才提到clusterID问题导致DataNode没起来那安全模式的根因也是它解决了前者后者自然恢复。6.3 页面打不开与Windows环境变量Hadoop各组件Web界面端口经常搞混我做个简单整理服务端口说明HDFS NameNode Web UI9870查看文件系统状态、数据块分布YARN ResourceManager Web UI8088查看任务提交、资源使用情况MapReduce JobHistory19888查看历史任务运行详情页面打不开优先检查防火墙状态开发环境直接关掉防火墙最简单systemctl stop firewalld。另外注意浏览器访问的是虚拟机IP或hostname不是写死了的localhost。如果用的NAT模式还需要考虑端口转发。还有一个Windows场景我上一节提过Windows本地提交任务报winutils缺失一定要把HADOOP_HOME指到一份带winutils.exe和hadoop.dll的已编译Hadoop包。这个坑通常出现在Windows开发、Linux集群生产这种混合模式下配置HADOOP_HOME时顺手把版本核对好省得后面版本不匹配又折腾一遍。7. 我踩过几次坑后总结的学习节奏最后忍不住多说一句。我刚开始学Hadoop的时候也是被各种名词唬住后来发现只要按“单机装好、伪分布式跑通、集群扩展、HA理解、提交任务验证”这个节奏走真的是越学越顺。中间有几个动作特别值得养成习惯每次改完配置先看日志永远记住格式化只在第一次做遇到多进程问题用jps和逻辑判断别瞎猜。伪分布式阶段被DataNode起不来折腾两天之后我最大的体会是动手排障的能力比记命令更重要。这套环境搭完你对分布式系统的感知完全不同了再看Spark、Flink、HBase这些上层组件会发现它们都是站在HDFS和YARN的肩膀上做文章。先把地基打牢后面所有东西都会简单很多。