从零搭建Hadoop+HBase多节点集群:原理、配置与踩坑实录 1. 为什么我要在本地从零搭一套 Hadoop HBase 集群先把结论摆在前面如果你只想“跑个 Demo”单机伪分布式就够了但如果你想真正理解大数据底座是怎么运转的想搞清楚一张表的数据到底落在哪台机器、哪个目录、哪个 Region 上那必须老老实实搭一套多节点的 Hadoop HBase 集群。我自己前前后后搭过不下十遍从最早被 SSH 免密卡一整天到后来被 HBase 的时钟漂移坑到怀疑人生踩过的坑基本能写一本小册子。这篇就把整套流程、背后的原理、以及那些文档里不会写的细节一次性讲透。Hadoop 集群解决的是“海量数据怎么存、怎么算”的问题核心是 HDFS分布式文件系统和 YARN资源调度HBase 则建立在 HDFS 之上解决的是“海量数据怎么随机实时读写”的问题它是一个分布式的列式数据库。两者组合起来就是很多公司早期大数据平台的标配底座。这套东西适合谁看适合刚接触大数据的在校同学、需要自己搭环境做验证的后端或数据开发、以及想搞明白“底层到底发生了什么”的运维同学。哪怕你之前只会在云上点几下买个托管服务跟着走一遍你对数据分布、副本、Region 分裂这些概念的理解会完全不一样。我这次搭建的目标很明确三台机器组成的最小可用集群一台做 MasterNameNode HMaster两台做 SlaveDataNode RegionServer全部用普通用户操作不碰 root方便后续迁移和权限管理。下面所有内容都围绕这个目标展开参数、目录、配置项我都会给出具体值和选择理由你可以直接抄也可以按自己机器情况微调。2. 集群规划与前置准备别急着装先把地基打牢2.1 节点角色划分与硬件资源估算很多人一上来就tar -zxvf解压安装包结果装到一半发现内存不够、端口冲突、主机名解析不了。我习惯先把规划表列出来心里有数再动手。三节点规划如下主机名角色建议内存建议磁盘说明node1NameNode、DataNode、HMaster、RegionServer8G 起100G主节点也兼做工作节点省机器node2DataNode、RegionServer、NodeManager8G 起100G纯工作节点node3DataNode、RegionServer、NodeManager8G 起100G纯工作节点为什么主节点也兼做 DataNode因为三台机器的小集群如果 Master 只做管理不存数据资源浪费太严重。生产环境当然要分离但学习和验证阶段合并部署完全没问题Hadoop 本身也支持这种角色叠加。内存方面NameNode 大概吃 2G 到 4GHMaster 吃 1G 到 2G剩下的留给 DataNode 和 RegionServer。如果你机器只有 4G 内存建议把副本数降到 1并且关掉 YARN只玩 HDFS HBase。磁盘规划上有个经验不要把数据目录放在系统盘。我一般会挂一块独立数据盘挂载到/data然后所有 Hadoop 和 HBase 的数据目录都指向/data/hadoop和/data/hbase。这样做的好处是系统盘满了不影响数据迁移的时候直接摘盘就行。如果你只有一块盘那至少把数据目录和安装目录分开别混在一起。2.2 系统层面的必做项主机名、hosts、防火墙、时钟这几项是“不做必出事”的典型。我按重要性排个序。第一是主机名和 hosts 解析。三台机器分别执行hostnamectl set-hostname node1以此类推然后编辑每台机器的/etc/hosts把三台机器的 IP 和主机名对应写进去。为什么必须做因为 Hadoop 和 HBase 的配置文件里到处是主机名如果解析不了节点之间握手直接失败报错还特别隐晦经常是“Connection refused”或者“Unknown host”新手很容易以为是服务没起来。第二是关闭防火墙或者放行端口。学习环境我建议直接systemctl stop firewalld systemctl disable firewalld省得一个个端口去开。生产环境当然要用白名单但那是另一回事。Hadoop 用到的端口很多NameNode 的 8020、9870DataNode 的 9866YARN 的 8088、8032HBase 的 16000、16010、16020、16030全都要通。第三是时钟同步。这一条是 HBase 的命门。HBase 对集群内各节点的时间差非常敏感默认超过 30 秒就会导致 RegionServer 启动失败或者 Region 分配异常。我一般用chronyd或者ntpd让三台机器指向同一个时间源。如果你在纯内网环境可以选一台机器做时间服务器其他两台同步它。命令大概是chronyc sources查看同步状态确认^*标记出现才算成功。第四是SSH 免密登录。在 node1 上生成密钥对ssh-keygen -t rsa然后ssh-copy-id node1、ssh-copy-id node2、ssh-copy-id node3把公钥分发到三台机器。为什么要免密因为 Hadoop 的启动脚本start-dfs.sh会通过 SSH 去各节点拉起进程如果每次都要输密码脚本根本跑不下去。这里有个细节node1 要能免密登录自己很多人只配了到 node2、node3 的免密忘了自己结果启动时报“Permission denied”。2.3 JDK 安装与 JAVA_HOME 的坑Hadoop 3.x 和 HBase 2.x 都要求 JDK 8 或 JDK 11。我实测下来 JDK 8 最稳兼容性最好。安装方式我用的是解压版不用包管理器因为路径可控。解压到/opt/module/jdk1.8然后配置环境变量。这里有个高频坑点JAVA_HOME的配置要写在多个地方。除了/etc/profile里的全局变量Hadoop 的hadoop-env.sh、yarn-env.sh、mapred-env.sh以及 HBase 的hbase-env.sh都要显式指定JAVA_HOME。为什么因为这些脚本执行时不一定加载了/etc/profile尤其是通过 SSH 非交互式登录启动的进程。我踩过的坑就是手动执行hadoop version正常但start-dfs.sh启动的进程报“JAVA_HOME is not set”。解决办法就是在每个 env 脚本里写死绝对路径。提示配置完环境变量后用source /etc/profile生效然后echo $JAVA_HOME确认。三台机器都要做别只做一台。3. Hadoop 集群搭建从配置到启动的完整链路3.1 核心配置文件逐个拆解Hadoop 的配置集中在$HADOOP_HOME/etc/hadoop目录下。我把需要改的文件和关键参数列出来每个都说明为什么这么设。core-site.xml是全局核心配置主要设两个东西默认文件系统和临时目录。configuration property namefs.defaultFS/name valuehdfs://node1:8020/value /property property namehadoop.tmp.dir/name value/data/hadoop/tmp/value /property /configurationfs.defaultFS指向 NameNode 的地址所有客户端默认往这里写。hadoop.tmp.dir是很多临时文件的根目录默认在/tmp下系统重启就没了所以必须改到数据盘。hdfs-site.xml管 HDFS 的具体行为。configuration property namedfs.replication/name value2/value /property property namedfs.namenode.name.dir/name value/data/hadoop/namenode/value /property property namedfs.datanode.data.dir/name value/data/hadoop/datanode/value /property property namedfs.namenode.secondary.http-address/name valuenode2:9868/value /property /configuration副本数设 2 是因为三节点集群设 3 会导致每个块都要全量复制写入变慢学习环境没必要。name.dir和data.dir分开方便排查问题。SecondaryNameNode 我放在 node2避免和 NameNode 抢资源。yarn-site.xml管资源调度。configuration property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property property nameyarn.resourcemanager.hostname/name valuenode1/value /property property nameyarn.nodemanager.resource.memory-mb/name value4096/value /property /configurationaux-services必须设成mapreduce_shuffle否则 MapReduce 任务跑不起来。resource.memory-mb是每个 NodeManager 能用的内存我设 4G留一半给系统和其他进程。workers 文件老版本叫 slaves列出所有 DataNode 节点每行一个主机名node1、node2、node3。这个文件决定了start-dfs.sh会去哪些机器启动 DataNode。3.2 格式化与启动顺序错了就重来配置分发到三台机器后我用scp或者rsync第一件事是格式化 NameNode在 node1 上执行hdfs namenode -format。注意这个命令只能执行一次重复执行会导致集群 ID 不一致DataNode 全部起不来。如果你不小心格式化了两次最简单的办法是把所有节点的name.dir和data.dir清空重新格式化。启动顺序是先start-dfs.sh再start-yarn.sh。启动脚本在$HADOOP_HOME/sbin下。执行完用jps检查进程。node1 上应该看到 NameNode、DataNode、ResourceManager、NodeManagernode2 和 node3 上应该看到 DataNode、NodeManager。如果某个进程没起来去对应的日志目录$HADOOP_HOME/logs下看.log文件错误信息一般都在最后几十行。注意jps看不到进程不代表进程没起有可能是权限问题导致jps读不到。用ps -ef | grep java再确认一遍。3.3 验证 HDFS 是否真的可用启动成功后别急着装 HBase先把 HDFS 验证透。我一般做三件事第一浏览器打开http://node1:9870看 NameNode 的 Web UI确认三个 DataNode 都在线容量正常。第二命令行建目录、传文件、读文件hdfs dfs -mkdir -p /test/input hdfs dfs -put /etc/profile /test/input/ hdfs dfs -cat /test/input/profile第三也是最关键的去看数据到底落在哪。在 node2 上执行ls /data/hadoop/datanode/current/BP-xxx/current/finalized/subdir0/subdir0/你能看到一个个blk_开头的文件。这就是你的数据块。用hdfs fsck /test/input/profile -files -blocks -locations可以看到这个文件被切成了几个块、每个块在哪几个节点上。这一步做完你对“分布式存储”的理解就从抽象变具体了。4. HBase 集群搭建建立在 HDFS 之上的实时数据库4.1 HBase 与 Hadoop 的依赖关系梳理HBase 的架构里HMaster 负责管理表的元数据和 Region 的分配HRegionServer 负责实际的数据读写而数据最终是存在 HDFS 上的。所以 HBase 的搭建必须建立在已经跑通的 HDFS 之上。这里有个关键选择HBase 用自带的 ZooKeeper 还是独立部署 ZooKeeper。我强烈建议独立部署 ZooKeeper原因有三一是自带 ZooKeeper 在集群模式下容易出问题二是独立部署方便后续其他组件复用三是出故障时排查边界清晰。ZooKeeper 我部署在 node1、node2、node3 三台机器上组成一个三节点的仲裁集群。ZooKeeper 的myid文件、zoo.cfg里的server.x配置这些基础操作这里不展开核心是保证zkServer.sh status能看到一个 Leader 两个 Follower。4.2 hbase-site.xml 的关键参数与选择理由HBase 的配置核心在conf/hbase-site.xml。我把关键项列出来configuration property namehbase.rootdir/name valuehdfs://node1:8020/hbase/value /property property namehbase.cluster.distributed/name valuetrue/value /property property namehbase.zookeeper.quorum/name valuenode1,node2,node3/value /property property namehbase.zookeeper.property.dataDir/name value/data/zookeeper/data/value /property property namehbase.unsafe.stream.capability.enforce/name valuefalse/value /property /configurationhbase.rootdir指向 HDFS 上的/hbase目录HBase 的所有数据最终都写在这里。cluster.distributed必须为 true否则就是单机模式。zookeeper.quorum列出 ZooKeeper 集群地址。最后那个unsafe.stream.capability.enforce设 false是为了兼容某些文件系统不支持 hflush 的情况学习环境设上能避免一些启动报错。还有一个文件是regionservers列出所有 HRegionServer 节点node1、node2、node3。这个文件的作用和 Hadoop 的 workers 类似。4.3 启动 HBase 与验证读写启动命令是start-hbase.sh在 node1 上执行。启动后jps应该能看到 HMasternode1和 HRegionServer三台都有。Web UI 在http://node1:16010。验证环节我习惯用 HBase Shell 走一遍完整流程hbase shell create test_table, cf1 put test_table, row1, cf1:name, zhangsan get test_table, row1 scan test_table建表、写入、读取、扫描四步都通了说明集群基本可用。这时候你可以再去 HDFS 上看/hbase/data/default/test_table目录能看到 Region 的目录结构里面有cf1列族的目录再里面就是 HFile 文件。这就是 HBase 数据在 HDFS 上的真实形态。提示HBase Shell 里list命令能看到所有表describe test_table能看到表的列族和 Region 信息。如果建表时报PleaseHoldException别慌这是 HMaster 还在初始化等几十秒再试。5. 踩坑实录那些让我熬夜的典型问题与排查思路5.1 启动失败类问题的排查路径问题一DataNode 起不来日志报“Incompatible clusterIDs”。这是格式化 NameNode 后DataNode 的集群 ID 和 NameNode 不一致导致的。解决办法是删除 DataNode 的数据目录重新启动。根本原因是格式化操作会生成新的集群 ID而老的 DataNode 还记着旧 ID。问题二HRegionServer 启动后马上挂掉日志报“Clock skew too great”。这就是前面强调的时钟同步问题。HBase 默认允许的时间差是 30 秒超过就拒绝启动。用date命令对比三台机器的时间差得多就赶紧同步。问题三HMaster 起不来报“Connection refused”连 ZooKeeper。先确认 ZooKeeper 三台都起来了吗zkServer.sh status看状态。再确认hbase-site.xml里的quorum写对了吗主机名和 hosts 对得上吗我遇到过 hosts 里写错一个字母排查了两小时。5.2 运行过程中的性能与稳定性问题问题四写入越来越慢Region 频繁分裂。这是 HBase 的常见现象。默认情况下一个 Region 超过 10G 就会分裂。如果你的 RowKey 设计是单调递增的所有写入都会集中在一个 Region 上导致热点。解决办法是 RowKey 加盐或者哈希前缀把写入打散到多个 Region。这个不是搭建问题但搭完集群一定要知道。问题五HDFS 空间满了HBase 写入失败。三节点小集群磁盘很容易满。我一般会设置 HDFS 的回收站保留时间短一点定期清理。另外HBase 的 WAL 日志和 HFile 都会占空间hbase.hregion.memstore.flush.size这个参数控制 MemStore 多大时刷写默认 128M调小一点能减少内存压力但会增加 HFile 数量。问题六YARN 和 HBase 抢内存。如果 HBase 和 YARN 部署在同一批机器上NodeManager 的内存设置太大会导致 RegionServer 内存不足被系统杀掉。我的经验是给 NodeManager 留 4GRegionServer 留 4G系统留 2G这样 8G 内存的机器刚好够用。5.3 常见问题速查表现象可能原因排查命令解决方向DataNode 未启动集群 ID 不一致查看 DataNode 日志清空数据目录重启RegionServer 闪退时钟不同步date对比各节点配置时间同步HMaster 连不上 ZKZK 未启动或配置错zkServer.sh status检查 quorum 配置写入报错HDFS 空间满hdfs dfsadmin -report清理或扩容启动脚本卡住SSH 免密未配好ssh node2测试重新分发公钥Web UI 打不开防火墙未关telnet node1 9870关闭防火墙或放行端口6. 搭完之后还能做什么从能跑到好用的进阶方向集群搭起来只是第一步真正让它“好用”还有很多事可以做。我分享几个我后续会做的优化方向你可以按需选择。第一是配置高可用。目前 NameNode 和 HMaster 都是单点挂了就全挂。生产环境要配 NameNode HA 和 HMaster HA需要额外的 JournalNode 和 ZooKeeper。三节点集群做 HA 有点勉强五节点比较合适。第二是调优 JVM 和 GC。HBase 的 RegionServer 默认堆内存可能不够用我一般会改hbase-env.sh里的HBASE_HEAPSIZE设成 4G 左右并且用 G1 GC 替代 CMS减少 Full GC 停顿。第三是集成 Hive 或 Spark。HBase 本身查询能力有限通过 Hive 外部表或者 Spark 的 HBase Connector可以用 SQL 或 DataFrame 的方式分析 HBase 数据实用性大大提升。第四是监控告警。用 Prometheus Grafana 采集 HBase 和 Hadoop 的 JMX 指标能看到 Region 数量、请求延迟、队列长度这些关键数据。没有监控的集群就是盲跑出了问题只能靠猜。我个人在实际操作中的体会是搭建过程本身不难难的是理解每个配置项背后的“为什么”。你把dfs.replication为什么设 2、hbase.rootdir为什么指向 HDFS、时钟为什么必须同步这几个问题搞明白了再遇到报错就不会慌因为你知道该往哪个方向查。最后再分享一个小技巧每次改完配置先在一台机器上重启验证没问题再分发到全部节点这样能把问题范围缩小到单机排查效率高很多。