Hadoop 3.3.3集群部署实战:从单机伪分布式到完全分布式配置与调优

Hadoop 3.3.3集群部署实战:从单机伪分布式到完全分布式配置与调优 简介Apache Hadoop 3.3.3 是面向大数据分布式计算领域的核心开源框架适用于高校学生、大数据初学者及运维开发人员用于搭建本地伪分布式或集群环境开展HDFS存储、MapReduce计算、YARN资源调度等基础实验与工程实践。压缩包共22536个文件涵盖18870个HTML文档含完整API参考与配置手册、763个JPG/GIF/PNG图像含架构图与流程示意图、449个JAR包含核心运行时依赖、75个Shell脚本含hdfs/yarn启动与管理工具以及大量XML配置模板、CSS/JS前端资源和原生库SO文件如libhadoop.so、libhdfs.so等全面支撑编译、部署、调试与二次开发。资源大小为615.16MB结构完整、开箱即用。已有640人学习下载读者可直接获取官方二进制发行版、全量文档体系、可执行脚本及原生扩展库快速构建稳定可靠的大数据处理平台避免源码编译复杂性显著降低入门门槛。1. 项目概述hadoop-3.3.3.tar.gz 到底在解决什么问题最近团队又在搭新的数据处理环境我从归档里翻出这个老熟人——hadoop-3.3.3.tar.gz。如果你也是做数据平台、数仓底座或者离线计算集群的那对这份 500 多 MB 的压缩包绝对不陌生。Apache Hadoop 这一套生态从 2006 年诞生到现在依然是很多企业离线数据处理的事实标准。虽然现在 Spark、Flink 满天飞但几乎所有跑在 YARN 上的计算引擎底层都离不开 HDFS 这套分布式存储和 YARN 的资源调度。这次我把 3.3.3 版本的部署过程、配置细节和踩坑点完完整整走了一遍从单机伪分布式到完全分布式集群把每一步的关键决策都记录下来。这篇文章适合两类人一类是刚接触 Hadoop、想在一台机器上快速跑通 Hello World 的新手另一类是准备搭正式集群、需要理解每个配置项到底在起什么作用的运维和开发同学。不管你是哪种照着这篇文章走一遍至少能少踩 80% 的坑。先把这个项目的核心拆一下。hadoop-3.3.3.tar.gz是 Apache Hadoop 3.3.3 版本的官方源码编译产物采用 tar.gz 格式打包解压即用。3.3.x 是 Hadoop 3.x 系列里比较成熟的稳定分支修复了一堆 3.2.x 时代的 NameNode 内存泄漏和 YARN 调度器在超大规模集群下的性能问题。相比 3.5.0 那种刚发布不久的新版本3.3.3 在生产环境的验证案例更多踩坑参考也更好找。如果只从功能上看Hadoop 3.x 和 2.x 最大的分水岭就是支持了NameNode 的多个备节点Observer NameNode、基于纠删码Erasure Coding的存储方案和YARN 的 GPU/FPGA 资源调度。这些能力让 Hadoop 3.3.3 在存储利用率和异构计算支持上比老版本上了一个台阶。而 3.3.3 这个具体版本号则在 3.3.0 和 3.3.2 的基础上修了一大批 CVE 漏洞和稳定性问题比如 HDFS 的OpenFile并发处理、RBFRouter-Based Federation的跨命名空间挂载问题。2. 版本选型思路为什么我最终选了 3.3.3 而不是最新版很多朋友一看官网发现 Apache Hadoop 已经出到 3.5.0 了就会纠结我是不是应该直接用最新版这里我想先分享一下版本选型的逻辑因为这直接决定了你后续所有配置和踩坑路线。2.1 3.3.3 与新版本的定位差异Apache Hadoop 的版本迭代节奏和大数据生态不太一样它不像某些前端框架那样追求快速发布而是更看重稳定性。3.3.x 系列从 2021 年发布 3.3.0 开始到现在经历了大量生产环境验证。我选择 3.3.3 的核心原因有三条第一Java 版本兼容面广。3.3.3 官方支持 Java 8 和 Java 11而 3.5.0 虽然也支持但官方已经开始把默认构建往 Java 11/17 方向倾斜。对于很多企业内部还停留在 JDK 8 的环境来说3.3.3 是更平滑的选择。很多时候不是我们不想升 JDK而是历史任务、老 Spark 版本、自研框架都绑死在 JDK 8 上为了一个存储层把整个计算生态都升一遍风险太大了。第二生态组件兼容性。Hive、Spark、Flink、HBase 这些上层组件官方在适配时往往滞后于 Hadoop 的新版本发布周期。以 Spark 为例Spark 3.2.x 和 3.3.x 官方测试过和 Hadoop 3.3.x 的兼容性但如果你去看 Spark 的官方文档它对 Hadoop 3.5.0 的支持说明相对较少很多 SQL 引擎自带的 Shuffle 插件在 Hadoop 3.5.0 上还没有足够的生产级验证。换句话说当你用 3.5.0 跑 Spark 任务时万一出问题你很难判断是 Hadoop 的 bug 还是 Spark 的适配问题。第三社区经验和文档积累。这里要说得直白一点——用 3.3.3 遇到问题你去搜解决方案能翻到大量真实的生产案例和踩坑帖用 3.5.0 遇到问题很多时候只能啃源码或者在社区里等待回复。我见过太多人追新版最后卡在一个很冷门的 bug 上几天出不来。做基础设施的稳比新重要得多。2.2 3.3.3 的关键能力盘点既然决定用 3.3.3那至少得知道这个版本能给我们带来什么。我挑几个实际用得上、感受明显的能力说一下。首先是HDFS 纠删码Erasure Coding。原先是默认三副本存储一份数据占三倍空间纠删码用 RS-6-3 等算法一份数据只占 1.4 倍空间左右可靠性还更高。这在冷数据存储场景下能把存储成本砍掉一半。唯一要注意的是纠删码不适合随机写、小文件多的场景它更适合大文件、顺序读写的离线数仓底层。3.3.3 对纠删码的支持已经相当成熟hdfs ec命令可以直接在线配置。其次是YARN 的资源类型扩展。3.3.3 支持在yarn-site.xml里自定义资源类型比如 GPU、FPGA配合resource-types.xml可以给节点配置 GPU 数量和控制任务调度的资源维度。这意味着你可以让一个 Hadoop 集群同时跑 CPU 任务和 GPU 训练任务而不是再单独搭一套资源管理。第三是NameNode 的性能优化。3.3.x 针对大规模目录和文件数量做了不少优化包括改进的 XAttr 处理、更高效的 EditLog 批量同步在千万级文件数量下NameNode 响应延时有明显改善。这一点可能很多同学感知不到但如果你的集群文件数是百万级以上升级到 3.3.x 后 NameNode 的 GC 频率会降低不少。3. 部署前环境准备与核心决策在真正解压hadoop-3.3.3.tar.gz之前有几个前置工作必须做扎实。这个阶段最容易被赶进度的人跳过结果后面全是在补锅。我按自己的实操顺序来梳理。3.1 主机规划与角色分配假如你现在要搭一个三节点的生产测试集群我建议这样分配角色节点角色分配说明node1NameNode、ResourceManager、SecondaryNameNode主节点建议内存 32G 以上node2DataNode、NodeManager计算存储节点node3DataNode、NodeManager计算存储节点生产环境我一般不建议把 NameNode 和 ResourceManager 拆到两台机器上倒不是技术上行不通而是一方面这两个角色都吃内存拆开更能分散风险另一方面如果真的需要高可用NameNode 的 Active/Standby 集群本身就有两台物理机再多拆就没有必要了。如果只有一台机器拿来学习那可以走伪分布式模式所有角色都在这台机器上但这时候要注意内存资源是共享的默认配置下 NameNode 和 DataNode 各自都要分配 1G 以上内存加上 ResourceManager 和 NodeManager一台 8G 内存的机器跑起来已经有点吃力了。建议内存至少 12G。3.2 JDK 版本选择和安装细节前面说了3.3.3 支持 Java 8 和 Java 11。我在实际部署中选的是 Java 8 的最后一个免费版本OpenJDK 8u392 之后为什么不选 Java 11原因很简单生态兼容。企业内部如果还要跑 Hive on MR 的老任务或者有一些基于 MR 的二次开发JDK 8 是兼容性最保险的选择。而且 3.3.3 官方文档明确写了支持 Java 8那就没必要给自己找不痛快。安装 JDK 的时候建议直接用tar.gz包解压安装然后配置/etc/profileexport JAVA_HOME/opt/jdk8 export PATH$PATH:$JAVA_HOME/bin配置完记得source /etc/profile然后执行java -version验证。这里有个小坑Hadoop 的启动脚本会优先使用JAVA_HOME环境变量如果配置不生效NameNode 会直接启动失败报错信息是Error: JAVA_HOME is not set and could not be found。我看到过很多次这问题最后发现不是没装 Java而是/etc/profile没生效。3.3 SSH 免密登录配置集群部署的第二个前置条件就是 SSH 免密。Hadoop 的启动脚本在分发和执行远程命令时需要通过 SSH 登录到其他节点如果每次都要输密码start-dfs.sh就会被卡住。配置很简单在主节点上执行ssh-keygen -t rsa -P -f ~/.ssh/id_rsa ssh-copy-id node1 ssh-copy-id node2 ssh-copy-id node3ssh-copy-id会把公钥追加到目标机器的authorized_keys文件里。这里注意如果你自己改了 SSH 端口需要加-p参数。验证方式ssh node2 hostname如果你看到返回的是node2的主机名而不是让你输密码那就说明通了。很多同学忽略了这一步验证结果后面集群起一半、报错连接超时再回来补浪费时间。3.4 目录规划与文件下载我这边的目录规划也比较固定分享一下/opt/hadoop # Hadoop 安装目录 /opt/hadoop/data # HDFS 数据目录DataNode 存储目录 /opt/hadoop/logs # 日志目录 /opt/hadoop/tmp # 临时目录为什么要单独把数据和安装目录分开因为 DataNode 的数据目录如果和安装目录放在同一个分区数据量涨起来之后磁盘空间满了会把安装目录也一起堵死到时候连日志都写不出来。这个分区规划问题很多新手根本想不到等出了问题再收拾就晚了。下载hadoop-3.3.3.tar.gz我推荐从 Apache 官方镜像站获取直接去镜像站列表里选一个离你近的下载后一定要校验 SHA-512。官方下载页旁边会提供对应的.sha512文件用下面的命令校验echo 官方sha512值 hadoop-3.3.3.tar.gz | sha512sum -c -如果输出OK说明文件没有损坏。这一步不能省我之前有一次下载了不完整的包解压后集脚本能运行但第二天格式化 NameNode 一直失败最后还是回到校验文件才发现问题。4. 单机伪分布式部署全流程实操先别急着直接上集群我建议第一次部署的读者一定先在单机上跑通伪分布式模式。这样你能把 HDFS、YARN 的核心配置和启动流程理解清楚同时方便排查问题。单机模式跑通了再往集群扩展就是改配置和分发文件的事。4.1 解压安装与环境变量配置拿到hadoop-3.3.3.tar.gz之后执行tar -zxvf hadoop-3.3.3.tar.gz -C /opt/hadoop解压完成后目录名是hadoop-3.3.3。我习惯把它重命名成hadoop方便后面版本升级时切换cd /opt/hadoop mv hadoop-3.3.3 hadoop然后编辑/etc/profile添加环境变量export HADOOP_HOME/opt/hadoop/hadoop export PATH$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin export HADOOP_CONF_DIR$HADOOP_HOME/etc/hadoop这里有必要解释一下这几个环境变量的作用HADOOP_HOME是 Hadoop 的安装根目录所有脚本都靠它定位命令PATH加路径是为了让你直接敲hdfs、yarn就能找到可执行文件HADOOP_CONF_DIR指定配置文件目录这个变量在你用hadoop-daemon.sh启停单个进程时特别有用。还有一个环境变量必须改就是$HADOOP_HOME/etc/hadoop/hadoop-env.sh里的JAVA_HOME。vi /opt/hadoop/hadoop/etc/hadoop/hadoop-env.sh找到export JAVA_HOME这一行改成你自己的 JDK 路径。我见过很多人只配置了系统的JAVA_HOME没改hadoop-env.sh结果start-dfs.sh执行到hdfs --daemon start namenode时还是报找不到 Java。这是因为 Hadoop 的某些守护进程脚本会覆盖系统环境变量直接加载hadoop-env.sh里的值。4.2 核心配置文件修改core-site.xml 和 hdfs-site.xml伪分布式模式下核心配置集中在两个文件里。先改core-site.xmlconfiguration property namefs.defaultFS/name valuehdfs://localhost:9000/value /property property namehadoop.tmp.dir/name value/opt/hadoop/tmp/value /property /configurationfs.defaultFS不解释了就是你的 NameNode 地址。hadoop.tmp.dir是 NameNode、DataNode 存放元数据、数据块的根目录这个目录一定要提前建好并且权限要可写。我把 tmp 目录独立出来就是为了防止系统/tmp被清理导致元数据丢失。曾经有个生产事故服务器重启时/tmp被 systemd 的 tmpfiles 机制清空HDFS 元数据没了虽然是属于该丢的数据全挂在 0 Byte 下最后还是恢复了才堪堪救回来。这个配置真的别偷懒。再改hdfs-site.xmlconfiguration property namedfs.replication/name value1/value /property property namedfs.namenode.name.dir/name valuefile:///opt/hadoop/data/namenode/value /property property namedfs.datanode.data.dir/name valuefile:///opt/hadoop/data/datanode/value /property property namedfs.namenode.http-address/name value0.0.0.0:9870/value /property /configuration伪分布式模式副本数只能配 1因为你只有一个 DataNode配成 3 会出现Zero targets found的调度错误。dfs.replication这个参数等扩展到三节点集群时改回 3 就行。dfs.namenode.name.dir和dfs.datanode.data.dir是元数据目录和数据块目录注意这里用的是file:///协议不是hdfs://。4.3 NameNode 格式化与启动验证这里有个特别重要的操作顺序第一次启动 HDFS 前必须先格式化 NameNode。hdfs namenode -format格式化其实就是初始化 NameNode 的元数据目录创建fsimage文件。操作时间很短但有一点必须强调格式化操作只有首次部署或者确认元数据没问题时才做一个认真跑过业务的集群随便格式化就等于删库跑路。所以很多老手在脚本里会加一个确认提示防止手误。格式化后启动start-dfs.sh执行完你可以通过jps查看 Java 进程jps伪分布式模式下你至少应该看到NameNode、DataNode、SecondaryNameNode三个进程。如果只有jps自己那说明启动失败了去/opt/hadoop/logs/hadoop-hadoop-namenode-*.log里找具体原因。启动 HDFS 后验证手段hdfs dfs -mkdir -p /user/hadoop hdfs dfs -put /etc/hosts /user/hadoop/ hdfs dfs -ls /user/hadoop然后把 YARN 也启动起来start-yarn.shstart-yarn.sh会拉起 ResourceManager 和 NodeManager再次用jps验证应该能看到四个进程NameNode、DataNode、SecondaryNameNode、ResourceManager、NodeManager这里其实是五个。注意上述在伪分布式下start-yarn.sh拉起的 NodeManager 可能与 DataNode 同机是正常的。完整验证可以在浏览器打开http://localhost:9870看到 NameNode 的 Web 界面里面能查看 HDFS 的存储容量、存活节点数、文件块状态。YARN 的界面在http://localhost:8088。4.4 伪分布式模式下的常见坑伪分布式部署看似简单但有几个问题很容易出现。第一个是DataNode 起不来这通常是因为dfs.datanode.data.dir指向的目录没有创建或者权限不对。第二个是NameNode 的 Web 界面打不开检查防火墙是不是把 9870 端口封了我这边云服务器第一次部署经常遇到。第三个比较隐蔽的是启动时可能会提示堆内存不足因为 Hadoop 默认的 NameNode 堆内存只有 1G如果你机器内存够大可以调大后面讲生产配置时会细说。第四个是格式化失败大概率原因是hadoop.tmp.dir目录下有上次部署残留的数据需要把hadoop.tmp.dir、dfs.namenode.name.dir、dfs.datanode.data.dir三个目录全部清空再重新格式化不然会报Storage directory already exists之类的错误。我在伪分布式模式下还遇到过一个问题DataNode 启动后很快自动退出查看日志提示There appears to be a gap in the transaction ID。这个的根源是 NameNode 元数据目录和 DataNode 数据目录不是同一次格式化生成的你可能是先启动了 NameNode然后再配好 DataNode 数据目录再启动导致 NameNode 的clusterID和 DataNode 的不一致。解决办法就是清空 DataNode 数据目录或者把记录在VERSION文件里的clusterID改成和 NameNode 一致然后重启 DataNode。5. 完全分布式集群搭建核心环节单机伪分布式跑通之后扩展成三节点集群就很顺畅了。这里我把最核心的配置和启动流程完整走一遍。5.1 集群配置文件修改与分发我上面说的三节点规划node1是主节点node2和node3是数据节点。在node1上修改配置后要把整个配置目录分发到node2和node3。core-site.xml的修改相对简单configuration property namefs.defaultFS/name valuehdfs://node1:9000/value /property property namehadoop.tmp.dir/name value/opt/hadoop/tmp/value /property /configuration这里变化只有一处localhost改成了node1。注意node1必须能被所有节点解析。我习惯在/etc/hosts中静态绑定 IP 和主机名而不是依赖 DNS减少一个故障点。hdfs-site.xml则要把副本数调回 3configuration property namedfs.replication/name value3/value /property property namedfs.namenode.name.dir/name valuefile:///opt/hadoop/data/namenode/value /property property namedfs.datanode.data.dir/name valuefile:///opt/hadoop/data/datanode/value /property property namedfs.namenode.http-address/name value0.0.0.0:9870/value /property property namedfs.permissions.enabled/name valuefalse/value /property /configuration这里加了一个dfs.permissions.enabledfalse我在测试环境这么开是为了省去权限麻烦。但生产环境千万别关否则所有用户都能删 HDFS 文件权限审计直接废掉。YARN 的配置在yarn-site.xmlconfiguration property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property property nameyarn.resourcemanager.hostname/name valuenode1/value /property property nameyarn.nodemanager.env-whitelist/name valueJAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME/value /property /configurationyarn.nodemanager.aux-services这个参数特别容易漏掉它的作用是让 NodeManager 能启动 MapReduce Shuffle 服务。如果不配置MR 任务在 Shuffle 阶段会一直卡住日志里报错却和这个参数毫无关系排查起来非常痛苦。yarn.resourcemanager.hostname指定 ResourceManager 所在节点。还有一个yarn.nodemanager.env-whitelist这个是让 NodeManager 在启动容器时保留JAVA_HOME等环境变量不配置的话某些 Spark 任务在 container 里会找不到 Java。mapred-site.xml原本叫mapred-site.xml.template需要重命名configuration property namemapreduce.framework.name/name valueyarn/value /property property namemapreduce.application.classpath/name value$HADOOP_MAPRED_HOME/share/hadoop/mapreduce/*:$HADOOP_MAPRED_HOME/share/hadoop/mapreduce/lib/*/value /property /configurationmapreduce.framework.nameyarn表示 MapReduce 作业提交到 YARN 上运行如果不配这个默认是 local 模式作业只在提交节点本地跑完全无法利用集群资源。mapreduce.application.classpath是因为 Hadoop 3.x 之后如果没有显式指定 classpath作业提交时经常报找不到mapred-site.xml里的类。最后要修改的是workers文件。在 Hadoop 3.x 中这个文件名是workers2.x 里叫slaves。它告诉 Hadoop 哪些节点是 DataNode 和 NodeManagernode1 node2 node3注意在完全分布式模式下主节点node1是否参与数据存储取决于你写不写进workers。我这边三节点集群让node1也参与存储这样数据均衡和吞吐量更好。如果数据节点资源非常大、想隔离角色可以不写node1。配置文件修改完成后把整个etc/hadoop目录分发到node2和node3scp -r /opt/hadoop/hadoop/etc/hadoop node2:/opt/hadoop/hadoop/etc/ scp -r /opt/hadoop/hadoop/etc/hadoop node3:/opt/hadoop/hadoop/etc/有个地方要注意node2和node3的 JDK 路径和 Hadoop 路径必须和node1完全一致否则启动时找JAVA_HOME和HADOOP_HOME就会报路径不存在。我配了那么多集群90% 的启动失败都是路径不一致而不是配置语法错误。5.2 集群启动顺序和验证在完全分布式模式下格式化 NameNode 只是在node1上执行千万不要在每台节点上分别格式化不然clusterID不一致DataNode 全部拒绝连接。hdfs namenode -format格式化完成后启动 HDFSstart-dfs.sh脚本执行时会通过 SSH 远程拉起每个节点的 DataNode最后输出各个节点的启动情况。然后启动 YARNstart-yarn.sh这时候在各节点上分别执行jps你期望看到节点进程列表node1NameNode、SecondaryNameNode、ResourceManager、NodeManager、DataNodenode2DataNode、NodeManagernode3DataNode、NodeManager我见过很多人启动完start-dfs.sh后在主节点看到NameNode和SecondaryNameNode起来了但 DataNode 迟迟不出现。原因绝大多数都是workers文件里的主机名不对或者 SSH 免密没配全。执行start-dfs.sh时脚本会逐个 SSH 到workers列表里的节点如果某个节点 SSH 不通它只是打印一行警告不会整体报错。验证集群状态的命令hdfs dfsadmin -report这个命令会列出所有 DataNode 的存储容量、剩余空间、最后心跳时间。正常节点状态应该是In Service如果显示DECOMMISSIONED或NODE_EXPIRED多半是网络通信或者心跳配置有问题。还可以执行hdfs dfsadmin -safemode get如果输出Safe mode is OFF说明集群可以正常读写。如果处于 safe mode用hdfs dfsadmin -safemode leave强制退出或者等它自动退出。5.3 集群核心参数调优经验集群能正常启动只是第一步生产级集群还需要做内存和并发层面的调优。这里列几个我会重点关注的参数。HDFS 端最核心的是 NameNode 堆内存。默认值是 1G但文件数量超过百万级后NameNode 堆内存很快就扛不住。调整方式在hadoop-env.sh中设置export HADOOP_NAMENODE_OPTS-Xms16g -Xmx16g对于千万级文件16G堆是起步水平。同时注意dfs.namenode.handler.count这个参数控制 NameNode 处理 RPC 请求的线程数默认值是 10文件操作频繁时建议调到 32 以上。计算方式大致是20 * log2(集群规模)三节点集群调到 32 就够了。YARN 端主要看yarn-site.xml里的内存调度配置property nameyarn.nodemanager.resource.memory-mb/name value16384/value /property property nameyarn.scheduler.maximum-allocation-mb/name value8192/value /property property nameyarn.scheduler.minimum-allocation-mb/name value1024/value /property这说明每台 NodeManager 能管理 16G 内存单个容器最大申请 8G、最小申请 1G。这里有个容易踩的坑yarn.nodemanager.resource.memory-mb不要配置成物理内存的 100%要给操作系统、DataNode 和其他进程留至少 30% 的余量。我之前有台机器 32G 内存直接配了 28G 给 YARN结果 DataNode 频繁 GC最后反而给 Namenode 挤崩了。并发参数里yarn.nodemanager.resource.cpu-vcores我一般配成物理核数减 1留一个核给系统。yarn.scheduler.maximum-allocation-vcores则限制单个容器最多能拿多少核防止一个吃 CPU 的任务把集群跑挂。5.4 重启流程与平滑操作在完全分布式集群上重启 Hadoop一定要有顺序意识。正常顺序是先停 YARN再停 HDFS启动时反过来先启 HDFS再启 YARN。顺序错了虽然不一定会直接报错但会造成 ResourceManager 找不到 NameNode 地址、任务提交时超时等诡异问题。# 停止 stop-yarn.sh stop-dfs.sh # 启动 start-dfs.sh start-yarn.sh还有一个经验改配置后不一定需要重启整个集群。比如只改了hdfs-site.xml的副本数用hdfs dfsadmin -refreshNodes或者hdfs dfsadmin -refreshSuperUserGroupsConfiguration很多参数能热刷新。但 YARN 的调度器参数改动通常需要在 ResourceManager 界面点击 Active 节点页面里的Refresh Queues或者执行yarn rmadmin -refreshQueues这个操作不需要重启能大幅减少集群停机时间。我维护的集群里改队列配额、加用户权限基本都是热刷新完成的只有改yarn-site.xml里的基础参数才需要滚动重启 ResourceManager。6. 常见问题与故障排查手册这部分是我最想分享的。Hadoop 集群就是这样能启动不等于能正常用正常用不等于永远不出问题。我整理了一线运维中经常遇到的高频问题每个都附带排查思路和解决方案。6.1 启动类问题DataNode 起不来/连不上 NameNode现象jps看不到 DataNode 进程或日志里反复出现Connection refused。排查步骤先看日志DataNode 日志默认在/opt/hadoop/logs/hadoop-hadoop-datanode-*.log。常见的三个原因一是workers文件里的主机名写错了二是dfs.datanode.data.dir对应的目录不存在或权限不足三是 DataNode 启动时发现clusterID与 NameNode 不一致。我用过的排查命令# 在主节点上查看 DataNode 是否有存活注册 hdfs dfsadmin -report # 在 DataNode 节点上查看日志 tail -n 50 tail -n 50 /opt/hadoop/logs/hadoop-hadoop-datanode-*.log # 直接查看注册信息 hdfs dfsadmin -printTopology如果是clusterID不一致日志里会有这么一句Incompatible clusterIDs in ...。修复办法是把 DataNode 的VERSION文件里的clusterID改成和 NameNode 的一致文件路径在数据目录下current/VERSION或者干脆清掉 DataNode 数据目录后重新初始化。提示如果集群已经写了数据清空 DataNode 数据目录会导致这个节点上的所有块重新复制在有副本的情况下能自动恢复但复制过程会占用大量网络和磁盘 IO生产环境要谨慎操作。6.2 存储类问题HDFS 写入失败/磁盘空间不足现象hdfs dfs -put报There are X missing blocks或者No available replicas。这个报错我看到很多新手一脸懵。首先确认有没有活着的数据节点hdfs dfsadmin -report如果 DataNode 全部 In Service再看是不是磁盘满了。hdfs dfsadmin -report输出里每一行的DFS Used%能直接看出每个节点的磁盘占比。Hadoop 默认有一个阈值当 DataNode 的磁盘使用率超过dfs.datanode.du.reserved时这个节点不会再接受新的数据块写入。还有一种隐蔽情况是block 损坏。用下面的命令检查hdfs fsck / -files -blocks -locations如果fsck报告某个路径下有CORRUPT块但你的副本数是 3且确实有 3 个 DataNode那大概率是某个节点上的磁盘有坏道或者文件被外部程序篡改了。这时可以先看具体坏块位置通常有两种处理一是找到对应 DataNode删掉坏块文件让 HDFS 从其他副本重新复制二是如果副本本来就只剩一个那就得从快照或者备份里恢复了。生产环境建议开启 HDFS 快照定期备份。6.3 性能类问题MapReduce 任务卡住/运行极慢MapReduce 任务跑得慢不一定都是 Hadoop 配置的问题。我从排查顺位来说看 YARN 资源够不够打开 ResourceManager 的 Web 界面看集群可用资源。如果有大量任务排队可能是yarn.scheduler.maximum-allocation-mb配小了单个任务申请不到足够的容器。看 Map 阶段是否卡在 Shuffle如果 Reduce 进度一直停在 33% 左右通常是mapreduce.reduce.shuffle.parallelcopies配置太低导致 Reduce 拉取 Map 输出的并发度不够。可以适当调高比如从默认的 5 调到 20。看数据倾斜如果某些 Reduce 处理的数据量明显多于其他典型特征是有几个 task 跑得特别慢而大部分已经完成。这时候要检查 Map 输出是不是有热点 key。解决方案可以在业务侧做二次 Key 加盐或者在 Hive 里开启hive.groupby.skewindatatrue。看网络和磁盘如果某个节点上的 Map 任务普遍比别的节点慢用df -h和iostat看看是不是磁盘 IO 满了或者网络有人跑了大流量任务抢带宽。还有个小细节Hadoop 默认的压缩配置很保守如果任务中间结果很大可以在mapred-site.xml里开启压缩property namemapreduce.map.output.compress/name valuetrue/value /property property namemapreduce.map.output.compress.codec/name valueorg.apache.hadoop.io.compress.SnappyCodec/value /property这一步对 Shuffle 阶段可以减少 60% 以上的网络传输量尤其是中间数据大的任务效果立竿见影。6.4 版本升级与 3.5.0 新版本参考最后说下和热词相关的话题Apache Hadoop 3.5.0。如果你的集群还没有上线或者你还在规划阶段完全可以直接用 3.5.0 在新环境里做验证但如果是存量生产集群我建议先了解 3.5.0 和 3.3.3 的差异再评估迁移价值。3.5.0 有几个值得关注的改进点HDFS 支持了更灵活的 EC 策略能够在线调整纠删码策略的写入带宽对冷数据存储场景更友好。YARN 的 Federation 功能进一步成熟能在一个集群里通过 Router 管理多个子集群适合超大规模部署。更多的 Java 优化和依赖清理包体积更小启动更快。对 S3A 连接器做了性能优化如果你使用公有云对象存储作为 HDFS 的补充这条会比较实用。但升级之前必须做一件事查看 HDFS 的升级兼容文档。Hadoop 3.x 内部的 RPC 协议和存储格式不一定保证向后兼容老集群直接升级到 3.5.0可能出现 EditLog 格式不兼容导致无法回滚的情况。我见过一个团队从 3.2 直接升 3.5升完发现 Hive 的 metastore 还在用旧版 Hadoop 客户端协议不兼容全部查询失败花了整整两天才把版本回退。如果你确实要升级我建议的路径是先开一个测试集群从 3.3.3 升级到 3.5.0跑完整业务回归再通过hdfs upgrade滚动升级或者用新集群做数据迁移确保万无一失。7. 一些小建议和实际体验部署 Hadoop 这件事做多了你会发现真正的难点不在安装本身而在对整个系统的理解。hadoop-3.3.3.tar.gz只是一个压缩包但解压之后你面对的是一个需要精心调教的分布式系统。我个人在实操中最深的体会是配置参数一定要有目的性地去改不要照搬网上的模板。每台机器硬件不同、业务不同默认配置只能保证能跑没法保证跑得好。比如dfs.replication默认是 3单机测试必须改成 1但如果我们只是拿它跑实验性任务副本数设为 2 就够了省下的存储空间很可观。最后分享一个小技巧就是一定把配置变更纳入版本管理。我在团队里推广的是把hadoop/etc/hadoop整个目录放进 Git 仓库每次改配置都 commit 一次。等出了问题能清楚地看到哪次改动导致了集群异常而不是靠翻聊天记录去猜。这套流程看似简单但真正坚持下来的人不多可它确实能让你在维护集群时省下大量时间。建议所有搞 Hadoop 的朋友都试一下养成习惯后你会回来感谢我的。本文还有配套的精品资源点击获取