ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Hadoop分布式存储核心:HDFS与HBase架构与实践解析

Hadoop分布式存储核心:HDFS与HBase架构与实践解析 先说个结论Hadoop这些分布式组件核心逻辑没那么玄乎。你把HDFS想成一台拆开来用的网盘把HBase想成一张能撑住亿级数据的巨型Excel表很多概念一下就通了。这篇内容面向刚接触大数据、正准备做课程设计或者刚入职数据平台的新手重点拆HDFS和HBase的整体架构把搭建过程、常用命令、读写流程和典型报错都过一遍。我见过不少新人一上来就盯着MapReduce和Spark啃反而把最底层的存储架构忽略了后面排查问题完全没头绪。实际上无论是Hive、HBase还是其他上层组件底层都跟HDFS脱不开关系。把存储这层搞明白整个生态的学习曲线能平缓一大半。1. 扒开Hadoop生态的整体脉络1.1 为什么入门要先厘清生态组成Hadoop不是单一软件而是一整套分布式基础设施的集合。提起Hadoop通常至少包含四大块HDFS负责分布式存储YARN负责资源调度MapReduce负责批处理计算再加上围绕它们衍生出的HBase、Hive、ZooKeeper、Flume、Sqoop等组件。这里有个新手最常见的误区以为Hadoop就等于数据分析。其实Hadoop的核心定位更像是一个底座——它不直接解决业务问题而是解决数据太多、单台机器放不下、算不动的问题。数据放哪里、怎么调度计算、如何协调多台机器这三件事才是Hadoop的看家本领。我把这套体系用仓储物流来类比你会更容易理解HDFS就是超大型仓库负责把货物数据块分门别类存到不同货架DataNode上同时有一本总账NameNode记录每件货物放在哪。YARN是仓储调度中心货来了谁来卸、谁去打包、哪台设备空闲都由它安排。MapReduce是流水线的标准作业流程规定了先分拣、再汇总的处理方式。HBase则是你仓库里那批高周转货品的专用货架支持快速定位单件商品根据RowKey查询不是把所有货物都翻一遍。ZooKeeper像物业负责协调各个部门之间的状态同步谁掉线了、谁上岗了大家都通过它来确认。很多初学者照着教程把Hadoop装好敲了两条命令就跑去看Hive语法了结果底层的整体认知完全是空的。等你真正遇到NameNode到底怎么恢复、RegionServer挂了为什么业务没断这类问题才发现必须回来补架构课。所以我的建议是先花两天把整套生态的角色关系理清楚再动手装集群进度反而更快。1.2 先分清几个容易混淆的概念HDFS、MapReduce、YARN、HBase、Hive这几个词新手经常串。我直接给你一个职责分清的记忆框架HDFS 存储层。只管文件怎么分块、存哪几个节点、坏了一块怎么补。它不关心文件内容是什么。YARN 资源管理层。报告谁有空闲内存、谁有富余核数把计算任务分配合适的容器Container里跑。MapReduce 计算模型。把任务拆成Map并行处理和Reduce汇总归并两个阶段。HBase NoSQL列式数据库。跑在HDFS之上提供随机读写的实时访问能力。HDFS本身只适合顺序读写不适合点查HBase就是用来补这个短板。Hive 数据仓库工具。把SQL翻译成MapReduce或Spark任务本质上是SQL翻译官本身不存数据。一句话概括HDFS管存原始文件HBase管实时点查Hive管离线分析YARN管资源分配ZooKeeper管协调。这个图景清晰了后面的架构拆解就顺理成章。2. 核心系统架构拆解HDFS与HBase2.1 HDFS架构把一份大文件拆到一堆机器上HDFS采用主从架构Master/Slave由NameNode、DataNode和SecondaryNameNode三个角色组成可能还会加一个客户端。NameNode是大脑不存数据只存元数据。它维护着整个文件系统的目录树、文件名到块列表的映射、每个块存储在哪些DataNode上等关键信息。元数据在内存中维护同时通过FsImage和EditLog两份文件持久化到磁盘。NameNode一旦挂了整个集群就变成只读甚至不可用所以它是HDFS里最需要保护的单点。DataNode是手脚真正存数据的节点。文件上传时HDFS会把文件切成固定大小的块块大小默认128MB每个块默认保存3个副本分布在不同的DataNode上。DataNode启动后会向NameNode发送块报告汇报自己手里的块列表让NameNode随时清楚元数据与实际存储是否一致。SecondaryNameNode不是备胎而是辅助管家。很多人误以为它是NameNode的热备其实不是。它的作用是定期拉取NameNode的FsImage和EditLog合并成新的FsImage再返回给NameNode防止EditLog无限膨胀导致NameNode重启时恢复过慢。真正的高可用需要借助JournalNode和ZKFC去实现Active/Standby切换。再深入一层解释几个关键设计这是面试必问为什么块默认设置成128MB这是为了降低寻址开销与元数据压力。HDFS是面向大文件设计的块太大时MapReduce处理单个块的并行度下降块太小NameNode内存要装下的块数量剧增。128MB是吞吐量、并行度、元数据规模三者之间的一个折中值。副本放置策略是什么默认3副本时第一个副本放在客户端所在节点第二个副本放在与第一个不同机架的节点第三个副本放在与第二个相同机架但不同节点的机器上。这样既保证了机架级容灾又兼顾了机架间带宽成本。写流程怎么走客户端先向NameNode发起写请求NameNode检查权限和空间后返回允许写的DataNode列表客户端按块依次把数据推给第一个DataNode再由它接力传给第二个和第三个形成数据管道每写完一个块客户端会收到确认最后把完成状态汇报给NameNode。这条链路你面试时最好能画出来。2.2 HBase架构一张十亿行的表是怎么存的HBase是跑在HDFS上的分布式列式数据库核心目的是提供海量数据的随机实时读写。它同样采用主从架构由HMaster、RegionServer和ZooKeeper组成。HBase的逻辑模型是一张稀疏的大表行按RowKey排序存储列按列族Column Family分组每个单元格存着多个时间版本的数据。这张表在物理上会被水平切分成多个Region每个Region包含一段连续的RowKey区间。Region是HBase负载均衡和数据分布的基本单位Region Server则负责处理这些Region的读写请求。我经常跟新手说逻辑上可以把HBase表想象成一个按字典序排列的大字典RowKey是词条字典总是按字母顺序排好。一个Region就是字典里的一个分册每册负责一段连续的字母区间。查询某条数据时先通过元数据定位它属于哪一册哪个Region再直奔那一册去找不需要从头翻到尾。Region内部到底长什么样这是HBase架构里最值得吃透的部分。每个Region内部包含多个Store一个Store对应一个列族。Store由内存中的MemStore和磁盘上的HFile构成。写入数据时先写MemStore和WAL预写日志达到阈值后刷写成HFile读取数据时先查MemStore再查HFile。HFile底层采用类似LSM-Tree的组织方式有序、不可变、适合顺序写入和批量合并。Region高可用原理值得单独说。HBase依靠ZooKeeper监控所有RegionServer的健康状态。每个RegionServer启动时会与ZooKeeper建立持久会话一旦RegionServer宕机会话超时断开ZooKeeper会立即通知HMaster。HMaster先把宕机节点上的WAL拆分成文件然后把这些文件分配到其他存活RegionServer去重放Replay最后把宕机节点负责的Region重新分配到合适节点。这个过程对客户端是透明的新的RegionServer接管后会继续对外服务。这就是HBase不依赖NameNode那种单点能力也能保障可用性的核心机制也是面试题里Region高可用原理的标准答案。为什么HBase敢说实时随机读写因为它在内存中维护了MemStore写入先落内存读的时候内存能直接命中同时通过RowKey有序存储定位到具体Region后查询目标数据的范围很小不需要全表扫描。对比HDFS它就不适合做这种点查因为HDFS读一个文件至少要经过NameNode取元数据、找块位置、连续读一整块数据的过程。2.3 ZooKeeper在Hadoop生态里扮演什么角色ZooKeeper在Hadoop生态里是一个极易被新手忽略、却又无处不在的组件。尤其在HBase架构中它承担了三个关键职责管理HMaster的选举保证任何时刻集群只有一个Active HMaster。存储HBase的元数据表hbase:meta的RegionServer位置。每个RegionServer启动后会把自己负责的Region信息注册到ZooKeeper客户端读写前先问ZooKeepermeta表在哪再通过meta表定位目标Region。监控RegionServer的心跳。RegionServer宕机时ZooKeeper的会话过期机制会触发HMaster的故障恢复流程。所以在搭建HBase之前先部署一个ZooKeeper集群几乎是标准操作。Hadoop自身的NameNode高可用也会用到ZooKeeper来做Active/Standby的故障切换但那是靠ZKFC进程配合实现比HBase直接用ZooKeeper做会话监控要复杂一些。你把ZooKeeper理解成生态里的通信中枢就好任何需要分布式协调、选主、状态同步的地方都有它的身影。3. 实操从零搭一个可用的Hadoop HBase环境3.1 环境准备版本选型是第一步我不建议直接去网上复制别人的配置文件版本选型不对后面全是坑。这里给出一套经过大量验证、我自己搭过多次的组合操作系统Ubuntu 22.0464位。JDKOpenJDK 8Hadoop 3.x、HBase 2.x官方要求Java 8最优。Hadoop版本3.3.6。3.x和2.x的配置文件、命令都有差异网上很多教程还是基于2.x写的容易踩坑。HBase版本2.4.17对应Hadoop 3.x适配版本。ZooKeeper版本3.7.0作为HBase的协调服务。安装包直接去Apache官网镜像站或者国内高校镜像站下载下载后统一解压到/opt目录并且最好用普通用户操作不要用root。root用户启动HDFS会有安全模型检查报错虽然可以改配置绕过但不建议新手在这个阶段给自己增加复杂度。配置环境变量时在~/.bashrc里加入HADOOP_HOME、HBASE_HOME、ZK_HOME再把对应的bin目录追加到PATH。改完记得source一下用echo $HADOOP_HOME验证变量是否生效。这一步很多人漏掉source导致后面hdfs命令找不到。3.2 Hadoop伪分布式搭建全过程新手阶段不苛求直接拉三台机器搭真分布式先在单机上跑通伪分布式也叫Pseudo-Distributed Mode其实就是用单台机器的多个进程模拟分布式集群。虽然性能和真集群有差距但架构和配置方式完全一致足够理解整个运行机制。伪分布式搭建最核心的就三个配置文件core-site.xmlconfiguration property namefs.defaultFS/name valuehdfs://localhost:9000/value /property /configuration这里指定了默认文件系统地址其实就是告诉HDFS客户端NameNode在哪。localhost主机名解析需要配置否则后面启动时会报UnknownHostException。hdfs-site.xmlconfiguration property namedfs.replication/name value1/value /property property namedfs.namenode.name.dir/name value/opt/hadoop/data/name/value /property property namedfs.datanode.data.dir/name value/opt/hadoop/data/data/value /property /configuration伪分布式集群只有一台机器副本数必须设为1否则第三份副本会因为找不到第二个机架而卡住等待。name dir和data dir是NameNode元数据和DataNode数据块的存储目录记得提前创建好目录并确保拥有写权限。配置本机SSH免密登录虽然伪分布式在同一台机器上跑但HDFS启动脚本默认会通过SSH远程执行命令所以要配置localhost的免密登录ssh-keygen -t rsa -P -f ~/.ssh/id_rsa cat ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys ssh localhost能免密登录成功再继续。这一步是新手最容易卡住的地方我见过好几个人因为authorized_keys权限不对一直卡在输密码循环。格式化NameNodehdfs namenode -format格式化本质是初始化NameNode的元数据目录生成空的FsImage。注意格式化操作会清空元数据如果集群已经在运行不要轻易执行否则会丢数据。很多新手想重启一下集群顺手格式化结果整个数据目录被清空追悔莫及。启动HDFS和YARNstart-dfs.sh start-yarn.sh jpsjps是用来查看Java进程的命令正常情况下应该看到NameNode、DataNode、SecondaryNameNode、ResourceManager、NodeManager这几个进程。然后浏览器访问http://localhost:9870能看到NameNode的Web UI说明HDFS已经起来了。3.3 HDFS常用命令与读写流程HDFS命令行是日常工作最基础的工具新手先记住这一组就够用了命令作用示例hdfs dfs -ls /path查看目录内容hdfs dfs -ls /hdfs dfs -mkdir /path创建目录hdfs dfs -mkdir -p /user/hive/warehousehdfs dfs -put 本地路径 HDFS路径上传文件hdfs dfs -put test.txt /test/hdfs dfs -get HDFS路径 本地路径下载文件hdfs dfs -get /test/result.txt ./hdfs dfs -cat HDFS路径查看文件内容hdfs dfs -cat /test/word.txthdfs dfs -rm HDFS路径删除文件hdfs dfs -rm /test/old.txthdfs dfs -du -h /path查看文件占用空间hdfs dfs -du -h /命令格式里hdfs dfs和hadoop fs两个前缀在很多版本里都能通用建议固定用hdfs dfs因为它在3.x里更规范。写流程再复盘一遍配合实操记忆更强。执行hdfs dfs -put上传文件时客户端先向NameNode发送请创建文件/data/xx.txt的请求NameNode校验无误后返回允许创建的确认和块ID。客户端开始写数据时按128MB切块第一块数据会先推到第一个DataNode第一个DataNode边接收边复制给第二个第二个再复制给第三个形成一个管道。每个块写完管道中每个DataNode都会向客户端返回确认消息ACK客户端收到所有ACK后再请求NameNode分配下一个块的DataNode列表。整个文件传完客户端关闭文件流NameNode把文件标记为已完成。读流程刚好反过来。客户端向NameNode请求我要读/data/xx.txtNameNode返回该文件所有块的位置列表。客户端拿到列表后会根据网络拓扑选一个最近的DataNode去读比如优先本机、其次同机架。读到的块按offset组装回原始文件。这个过程里NameNode只负责告诉客户端块在哪真正的数据流不经过NameNode所以HDFS的读吞吐可以做得非常高。3.4 HBase安装与使用先启动ZooKeeper再启动HBaseHBase的安装比Hadoop本身要省心一些因为它不涉及复杂的格式化流程核心是配置好HBase与HDFS、ZooKeeper的关联。hbase-site.xml里的关键几项configuration property namehbase.rootdir/name valuehdfs://localhost:9000/hbase/value /property property namehbase.cluster.distributed/name valuetrue/value /property property namehbase.zookeeper.quorum/name valuelocalhost/value /property property namehbase.zookeeper.property.clientPort/name value2181/value /property /configurationhbase.rootdir指向HDFS上的/hbase目录表示HBase的数据最终落在HDFS上。hbase.cluster.distributed设为true表示分布式运行模式这个值如果漏配HBase会启动成单机模式HMaster无法实现多节点协调。hbase.zookeeper.quorum填ZooKeeper地址单机调试填localhost即可。启动顺序非常关键强烈建议固定执行start-dfs.sh # 先启动HDFS zkServer.sh start # 再启动ZooKeeper start-hbase.sh # 最后启动HBase jps # 看到HMaster、HRegionServer进程才正常这个顺序背后的逻辑是HBase要往HDFS上写数据所以HDFS必须先行HBase要注册到ZooKeeper并依赖它的会话监控所以ZooKeeper也要先起好。启动成功后执行hbase shell进入交互命令行create student, info put student, 1001, info:name, zhangsan put student, 1001, info:age, 20 get student, 1001 scan student这段操作先建一张student表只有一个列族info然后插入一条RowKey为1001的记录分别写上name和age两个列再通过get按RowKey精确查询用scan扫描全表。get和scan的区别也常被问到get是点查直接定位到一行scan是范围扫描可以指定startRow和stopRow。如果想通过Java API读HBase依赖加上hbase-client之后核心代码其实很短Configuration conf HBaseConfiguration.create(); conf.set(hbase.zookeeper.quorum, localhost); Connection conn ConnectionFactory.createConnection(conf); Table table conn.getTable(TableName.valueOf(student)); Get get new Get(Bytes.toBytes(1001)); Result result table.get(get); System.out.println(Bytes.toString(result.getValue( Bytes.toBytes(info), Bytes.toBytes(name))));这段代码的意图就是连接HBase、按RowKey查一行、取出info:name列。新手跑通这段代码后基本就算跨过只会敲shell的门槛了。4. 高频报错排查与面试硬考点4.1 我踩过的坑典型报错排查实录不管你是自己搭伪分布式还是在服务器上搭集群有些报错几乎是人人都会遇到。我按出现频率整理了几个附上我实际排查的思路。报错1java.io.IOException: previous writer likely failed to write hdfs://centos04:9000/...这个报错我在实验环境里踩过很多次字面意思是你正在写的文件上一次写入者疑似故障了HDFS认为这个文件还被占着。常见触发场景是用同一个路径反复写文件前一次客户端异常退出没有正常close文件流导致租约Lease没有释放。解决思路分三步。第一步先检查有没有残留的Java进程用jps看清楚如果有僵死的客户端进程直接kill掉。第二步用hdfs debug recoverLease -path 文件路径 -retries 3这个命令强制恢复文件租约等几十秒让NameNode完成租约恢复。第三步如果还不行就把这个残留目录删掉重新写hdfs dfs -rm -r /对应目录。这个报错本身不会损坏已有数据但会让你误以为文件写坏了实际上大部分情况下文件已经完整写完只是元数据状态没刷新。报错2NameNode连接不上客户端报Connection refused优先检查NameNode进程是否存活。如果jps看不到NameNode看日志里有没有磁盘空间不足、元数据目录权限不对之类的异常。常见原因是格式化后目录被root身份写过导致普通用户无法读写。解决办法是chown把目录归属改回来。另外检查core-site.xml里的fs.defaultFS端口是否和实际启动的端口一致如果你改了端口但客户端配置没同步也会连不上。报错3HDFS长时间处在安全模式Safe mode安全模式本质是NameNode启动后先统计DataNode汇报的块数如果可用数据块比例不足阈值集群就拒绝写操作。伪分布式副本数设为1时格式化后第一次启动有时会卡安全模式通常是DataNode还没及时汇报。可以先等两分钟或者手动执行hdfs dfsadmin -safemode leave强制退出。如果反复进入安全模式重点检查磁盘是否满了——DataNode写不进数据块比例就达不到要求。报错4HBase启动后HRegionServer进程消失这种情况多半是HRegionServer和ZooKeeper的会话频繁断开时间一长被ZooKeeper认定为宕机然后进程退出。排查方向有两个第一确认服务器时间是否同步时钟漂移过大会导致会话验证失败第二检查hbase-site.xml里zookeeper.session.timeout配置是否过小默认60秒网络有波动时可以适当调大。日志里如果看到大量的ZooKeeper Session Expired基本就是这里的问题。报错5localhost解析失败或SSH互信不生效这类问题多数出在/etc/hosts里没配置localhost到127.0.0.1的映射或者~/.ssh目录权限不对。SSH对权限非常敏感authorized_keys文件权限必须是600.ssh目录权限必须是700多一个组用户的可写权限都会导致免密失效。我见过有人在Windows上编辑过authorized_keys文件格式带了\r回车符这个小问题能让整个集群启动失败。4.2 这些面试题其实都在考底层架构很多同学学了半个月去面试时一被问到底层就不知道怎么答。我梳理几个高频题其实对应的是架构理解HDFS写入时客户端和DataNode之间为什么用管道式复制而不用客户端逐个复制因为管道式复制可以并行传输第一个DataNode接收的同时就把副本传给第二个延迟大大降低同时减轻客户端网络带宽压力。核心考量是吞吐和带宽开销。HBase为什么快答案要落在存储引擎上。写入走WAL和MemStore批量刷盘形成有序的HFile查询优先命中内存其次通过有序文件范围读取。整个过程回避了传统数据库的随机写和随机读问题。面试时能说出LSM-Tree这个关键词并解释清楚顺序写原地更新延迟说明真的理解到位了。Region分裂和合并的原理是什么Region默认达到一定大小由hbase.hregion.max.filesize控制默认10GB会分裂成两个子Region新的Region会由HMaster均衡分配到其他RegionServer。当大量数据被删除、Region明显变小且长期低于阈值时多个Region会合并以减少管理开销。这个过程完全由HBase内部自动管理不需要人工干预。RowKey设计为什么如此重要HBase的表按RowKey字典序存储查询时只能按RowKey做到高效点查和范围查。如果RowKey没有设计好比如用时间戳直接做前缀那么热点数据会集中在某一个RegionServer上读写性能都受影响。实际设计时通常要打散顺序比如在RowKey前加盐或者倒序让数据均匀分布到各Region。面试里常考的热点问题就是从这里引出来的。关于HDFS的副本放置策略、HBase的Region高可用原理前面已经拆过这里不再复述。你只要把这三个点串起来——NameNode管元数据、DataNode管块、RegionServer管Region——整个Hadoop存储体系的主干就基本通了。最后再给新手一个节奏建议先别急着去看源码把环境搭起来、把命令跑通、把读写流程用自己的话讲出来再去啃Region分裂和NameNode HA这些高级话题。我也见过太多人卡在想一次性学完的执念里结果什么都是半桶水。与其追求面面俱到不如把HDFS和HBase这两块最核心的东西扎扎实实吃透后面的Hive、Spark、Flink再上手你会觉得整个数据体系都是相通的。
返回列表