资讯动态

HCIA-Big Data备考笔记:存储、计算与调度三条主线串讲

发布时间:2026/10/27 20:18:16 来源:尧图企业网站定制
2月10号那天我把HCIA - Big Data相关的笔记从头到尾重排了一遍。起因很直接前一周做模拟题时HDFS的写入流程我能背下来但一问到“客户端写失败之后NameNode怎么处理租约”“YARN的Container申请和分配到底谁跟谁对话”我就开始含糊。这种“能复述、不能推演”的状态在HCIA - Big Data这类偏概念与原理的认证里是最危险的因为题目不会照着教材原句问它总要在某个环节拐个弯。所以我干脆把零散的知识点全部拆开按“这份认证到底想确认你懂什么”重新拼了一遍。这篇笔记写给两类人一是正在准备HCIA - Big Data、手里有一堆课件但串不成线的人二是已经在大数据岗位上干活、但底层组件原理一直靠“印象”撑着的人。我不会把官方大纲复述一遍那东西你手上就有。我想讲的是这套知识体系里哪些点是真正的主干、哪些是出题人爱挖的坑、哪些东西你背下来了但一到实验环境就露馅。中间会穿插我自己搭环境、跑作业时踩到的具体问题以及几个我认为值得反复琢磨的参数和机制。1. 先弄清这套认证在考什么三条主线而不是一堆组件很多人翻开目录的第一反应是“组件好多”HDFS、MapReduce、YARN、Hive、HBase、Spark、Flink、Kafka、ZooKeeper、Flume、Sqoop……于是一路背下去背到后面忘了前面。我在第一轮复习时就掉进这个坑结果是每个组件都能说两句但被问到“一个日志采集需求该用哪几个组件串起来”时脑子是空的。后来我换了个思路这套知识体系的骨架其实只有三条主线存储、计算、资源调度其余组件都是这三条主线的延伸或者补充。1.1 存储主线数据放在哪怎么放才可靠存储主线的核心是HDFS外挂一个HBase解决随机读写再往下延伸出Hive的元数据和表结构。你只要抓住一个问题一份数据在集群里存三份怎么保证这三份不出错、不丢、读得快。HDFS的所有机制设计本质上都在回答这个问题。副本机制解决“丢了怎么办”默认3副本机架感知决定副本放在哪几个机架上。块Block机制解决“大文件怎么切”默认128MB一块切完才能分布式存。元数据机制解决“怎么找到块”NameNode内存里存的是文件到块的映射不是数据本身。心跳与租约解决“谁还活着、谁还在写”DataNode定期上报客户端写文件时持租约。把这四条摆开HDFS那一章就不再是零散的配置项而是一条有因果链的设计。考试里问“SecondaryNameNode的作用”答“帮助NameNode合并editlog和fsimage不能做热备”这种标准答案当然要会但更关键的是你能说清为什么它不能做热备——因为它不实时同步元数据的变更。这个“为什么”才是把知识点钉死的钉子。1.2 计算主线任务怎么切、怎么并行、怎么汇总计算主线的核心是MapReduce往上延伸出Hive把SQL翻译成计算任务、Spark把计算放到内存里跑、Flink把计算做成流式。这条主线你要抓的问题是一个大任务怎么拆成很多小任务并行跑跑完怎么拼回去。MapReduce的五个阶段——Input、Map、Shuffle、Reduce、Output——每一个阶段的边界条件都得清楚。尤其是Shuffle它是最容易出问题也最爱考的地方分区Partitioner决定数据去哪个Reduce排序Sort决定Reduce端看到的顺序合并Combiner在Map端做一次局部归约以减少网络传输。这三个动作在同一个阶段里发生但不是同一件事很多人笔记里把它们糊成一团。Hive那一章看起来是讲SQL其实讲的是“SQL怎么落到MapReduce/Tez/Spark上执行”。你需要知道Hive自己不算数据它只是一个把HQL翻译成分布式作业的编译器元数据存在MetaStore里通常落在关系型数据库真实数据在HDFS上。这个认知一旦建立Hive的很多行为就顺理成章了为什么内部表删表会删数据、外部表不会因为数据归属权不同。为什么分区字段不能随便选高基数的列因为每个分区对应一个目录分区太多会导致NameNode元数据膨胀。1.3 调度主线资源怎么分、任务怎么排队资源调度这条线最容易被轻视但它恰恰是把存储和计算串起来的那根绳。YARN的核心角色是ResourceManager全局资源调度、NodeManager单节点资源管理、ApplicationMaster单个作业的管家、Container资源的抽象单位。这四个角色的对话关系是这一章的全部重点。我整理笔记时画过一张最简对话图虽然这里不能画图但你可以自己在纸上画客户端提交作业 → RM分配第一个Container启动AM → AM向RM申请后续Container → RM让NM去启动 → NM拉起任务进程 → 任务向AM汇报进度 → 全部完成AM注销。这条链路你只要能口述出来YARN那一章基本就通了。调度器这块FIFO、Capacity、Fair三种的差别要能说清适用场景。FIFO简单但会饿死小作业Capacity把队列容量预分配适合多团队共享Fair让资源动态均衡适合任务量波动大的场景。考试喜欢考“某场景下选哪种”你光背特性不够得理解每种调度器在解决什么矛盾。主线核心组件必须回答的问题存储HDFS、HBase数据分块、副本、元数据、随机读写计算MapReduce、Hive、Spark、Flink任务切分、Shuffle、SQL翻译、内存计算调度YARN、ZooKeeper资源分配、队列、协调选举把这张表贴在笔记第一页后面每学一个组件先问它属于哪条线、解决什么问题再去看细节。这个顺序反过来你会背得很痛苦。2. HDFS的写入链路从客户端到DataNode的每一步都可能被问HDFS是这套认证里分量最重的组件之一而写入流程是重灾区。我见过太多人能把“客户端向NameNode请求、NameNode返回DataNode列表、客户端写Pipeline”这段话背下来但一旦题目改成“Pipeline中某个DataNode挂了会怎样”就答不上来。2.1 一次完整写入的六个动作我把写入拆成六个动作每个动作对应一个可能被追问的点客户端调用create向NameNode发起创建文件请求。NameNode做检查确认路径不存在、权限够、配额没超然后返回一个可写的DataNode列表按机架感知排序通常第一个副本放在客户端所在节点或最近的机架。客户端建立Pipeline把数据块切成Packet依次发给第一个DataNode第一个转发给第二个第二个转发给第三个形成一条链。三级确认反向上报最后一个DataNode写完向上一级发ACK逐级回传到客户端。块写满或关闭时做finalizeDataNode把临时块转正向NameNode汇报块信息。客户端closeNameNode做持久化文件变为可用状态。这六步里第3、4步是Pipeline机制的核心。为什么用Pipeline而不是客户端同时写三个DataNode因为要避免客户端成为带宽瓶颈同时保证三个副本写入顺序一致。这个“为什么”在面试和考试里都常被问。2.2 Pipeline中途挂了一个节点怎么办这是我最喜欢的一个考点因为它能区分“背过”和“懂了”。假设三个DataNode组成Pipeline写到一半第二个挂了会发生什么客户端会收到ACK超时或错误。客户端通知NameNodeNameNode把出问题的节点从Pipeline里移除。剩下的两个DataNode重新组成Pipeline客户端继续往新Pipeline里写。已写入的数据不会丢因为第一个和第三个节点上的数据是完整的。后续这个块会按副本策略补足到三副本。关键结论写入过程是“尽力而为事后补齐”不是事务性的原子操作。这个认知很重要因为它解释了为什么HDFS适合一次写入多次读取而不适合频繁修改。2.3 SecondaryNameNode的定位别再搞混这个组件名字起得太有误导性很多人第一反应是“备用的NameNode”。不是。它的作用是定期把NameNode的editlog和fsimage合并减少NameNode重启时的加载时间。它不做实时同步所以NameNode挂了它顶不上。真正解决NameNode单点问题的是HA架构两个NameNodeActive和Standby靠JournalNode共享editlog靠ZooKeeper做选举和故障切换ZKFC进程监控。这套架构里Standby会实时读取JournalNode上的editlog所以切换时元数据基本不丢只可能有极短的延迟。我在实验环境里配过一次HA踩的坑是格式化NameNode的顺序搞反了导致两个节点元数据不一致启动后一直处于standby状态无法切换。后来才明白HA模式下要先格式化JournalNode再分别格式化两个NameNode且第二个要用-clusterid参数对齐。这类实操细节课件上通常一句话带过但你不动手就永远记不住。提示考试里如果问“SecondaryNameNode能否实现高可用”答案是不能如果问“HA架构中谁负责故障切换”答案是ZooKeeper配合ZKFC别只写ZooKeeper。2.4 块大小为什么是128MB这个数字不是拍脑袋定的。块太小元数据条目多NameNode内存压力大块太大单个节点的磁盘IO成为瓶颈且任务并行度上不去。128MB是在当时的硬件条件下寻址时间约10ms与传输时间约100MB/s下1秒多之间的一个平衡点。你可以记一个粗略的换算希望传输时间远大于寻址时间通常是100倍左右所以块大小≈100×10ms×100MB/s≈100MB取整到128MB。这个推导过程考试不考但它能帮你在被问到“块大小能不能改、改了有什么影响”时给出有依据的回答而不是干巴巴一句“默认128MB”。3. Hive不是数据库搞清楚它到底翻译了什么Hive这一章最容易被误解成“学SQL”。SQL那部分你本来就会真正要学的是Hive如何把你写的HQL变成分布式作业。这个视角一换分区、分桶、内部表外部表、数据倾斜这些概念就都有了归属。3.1 元数据、数据、计算三者的分离Hive的架构可以概括成三句话元数据在MetaStore背后通常是MySQL这类关系库数据在HDFS计算交给MapReduce/Tez/Spark。Hive自己只做一件事——解析、优化、生成执行计划。这个分离带来一个很实际的后果你删了Hive表数据可能还在。内部表Managed Table删表时会把HDFS上的数据目录一起删掉外部表External Table删表只删元数据数据目录原封不动。生产环境里几乎都用外部表因为数据往往由上游采集程序写入不能被一个误操作带走。我在早期做练习时用内部表存了一份跑了两小时的清洗结果后来手滑drop了一下数据直接没了只能重跑。那次之后我养成习惯除了临时中间表一律建外部表并且建表时就显式指定location。3.2 分区和分桶解决的不是同一个问题这两个概念经常被放在一起讲但它们的目的完全不同。**分区Partition**解决的是“减少扫描量”。按日期、地区这类低基数字段分区查询时带上分区条件Hive只扫对应目录。**分桶Bucket**解决的是“数据均匀打散”。按某个字段的哈希值取模分到固定数量的文件里主要用于抽样和Map端Join。分区字段是目录结构/table/dt2024-02-10/分桶是文件层面的切分。分区数量过多会让NameNode压力变大因为每个分区都是一个目录分桶数量一旦建表时定下后期改动很麻烦。一个常见的错误是拿高基数字段做分区比如用用户ID分区结果产生几百万个目录NameNode直接扛不住。这种字段适合做分桶。3.3 数据倾斜Hive调优绕不开的那道坎数据倾斜的本质是某个key对应的数据量远超其他key导致一个Reduce任务拖慢整个作业。典型场景是Join时某个热门商品ID、某个默认值null或空串占了绝大部分记录。处理手段我在笔记里总结了四条按使用频率排序过滤异常key如果倾斜来自null或空值Join前先过滤掉或者在Join条件里给null赋一个随机值。Map端Join小表足够小默认25MB以内时把它广播到每个Map任务直接避免Shuffle。加盐打散给倾斜key拼接随机前缀让它分散到多个Reduce之后再聚合回来。这个方法会多一次作业但能救命。调参数hive.exec.reducers.bytes.per.reducer调整每个Reduce处理的数据量hive.groupby.skewindata开启倾斜时的负载均衡会生成两个MR作业。这里有个经验不要一上来就调参数。先看执行计划确认倾斜发生在哪个Stage、是Join倾斜还是GroupBy倾斜再对症下药。参数是兜底手段不是第一选择。倾斜类型表现首选方案Join倾斜某个Reduce耗时远超其他Map Join或加盐GroupBy倾斜某个key聚合量巨大两阶段聚合空值倾斜null占比高过滤或随机化3.4 HQL到作业的翻译过程值得手动跟一遍我建议你至少手动跑一次explain看一条简单SQL是怎么被拆成多个Stage的。比如一个带Join和GroupBy的查询通常会生成两到三个MapReduce作业第一个做Join前的数据准备第二个做Join第三个做聚合。理解了Stage的划分你才能明白为什么有些SQL写起来简单、跑起来很慢。比如select count(distinct uid) from t很多人以为是一个作业实际上distinct会被翻译成“先GroupBy去重再count”中间可能产生额外的Shuffle。想优化成select count(1) from (select uid from t group by uid) tmp因为后者可以用更少的阶段完成同样的去重。这类改写技巧在数据量大时差别非常明显。4. HBase的读写路径RowKey设计决定一切HBase是这套认证里最“反直觉”的组件。关系库你按行存、按索引查HBase你只有RowKey这一个索引其他字段想查只能全表扫。这个限制逼着你在设计阶段就把查询模式想清楚。4.1 LSM树与写入路径HBase的写入不是直接落盘而是先写WAL预写日志保证不丢再写MemStore内存MemStore满了刷成StoreFileHFile落盘。这个结构叫LSM树特点是写快读慢——写入都是顺序追加读取要合并多个文件。这个设计决定了HBase的适用场景写多读少、按RowKey随机读写。如果你需要复杂的多条件查询HBase不是好选择Hive或者搜索引擎更合适。读取时HBase会先查MemStore再查BlockCache最后查StoreFile。为了加速“某个RowKey在不在这个文件里”的判断可以用布隆过滤器BloomFilter代价是额外内存。这个开关在列族级别配置考试里偶尔会问。4.2 RowKey设计的三条铁律RowKey设计是HBase里唯一真正需要“设计”的部分我总结成三条长度要短RowKey会冗余存储在每个单元格里太长会显著增加存储开销。一般建议不超过16字节。散列要均匀避免热点。常见做法是加盐前缀随机数、哈希对RowKey取md5、反转把时间戳倒序。排序要符合查询HBase按RowKey字典序排列所以你要把“最常用的查询前缀”放在最前面。比如查询“某用户某时间段的数据”RowKey应该是userId timestamp而不是反过来。一个真实的反例有人用时间戳做RowKey前缀记录日志结果所有写入都集中在一台RegionServer上因为时间戳是单调递增的永远落在最后一个Region。这就是典型的“写入热点”解决办法是加盐或反转。4.3 Region分裂与预分区HBase的表按RowKey范围切分成多个Region每个Region由一个RegionServer管理。表刚建时只有一个Region随着数据增长会分裂。分裂本身没问题但分裂瞬间会有短暂的不可用而且自动分裂的边界不可控。生产环境通常用预分区建表时就根据RowKey的分布范围预先切好多个Region。比如按用户ID哈希取模预先建16个Region。这样写入从一开始就是分散的不会出现“先热后分裂”的抖动。预分区的split key怎么定简单办法是按业务已知的取值范围均分复杂一点先用抽样数据算出分位数。这个细节考试不会深究但你在实验里建表时如果忘了预分区后面导入数据会明显感觉到前期写入集中在一个节点上。5. Spark、Flink、Kafka三条技术路线的边界在哪到了这一层知识点开始交叉也最容易混。我的处理办法是不背组件特性而是背“什么场景该选谁”。选型的判断依据比组件参数更有价值。5.1 Spark的RDD与宽窄依赖Spark的核心抽象是RDD一个不可变、可分区、可并行操作的数据集合。RDD之间的依赖分两种窄依赖一个父分区只对应一个子分区比如map、filter和宽依赖一个父分区对应多个子分区比如groupByKey、join。宽依赖会触发ShuffleShuffle是Spark作业里最贵的操作。所以Spark优化的核心思路就是能不用Shuffle就不用非用不可就尽量减少数据量。reduceByKey优于groupByKey因为前者在Map端先做局部聚合。大表Join小表时用广播变量Broadcast Join把Shuffle变成Map端操作。多次复用的RDD要cache()或persist()但要选对存储级别内存不够时用MEMORY_AND_DISK。Stage的划分就是以宽依赖为界遇到一个宽依赖就切一个新Stage。这个规则你要能自己画出来因为考试里给一段代码问“有几个Stage”是很常见的题型。5.2 Flink的流批一体与时间语义Flink和Spark最大的理念差别是Spark以批为第一公民流是微批模拟Flink以流为第一公民批是流的有界特例。这个差别体现在编程模型上就是Flink的DataStream API可以处理无界流DataStream也可以处理有界数据。Flink的时间语义是重点Event Time事件发生时间、Ingestion Time进入系统时间、Processing Time处理时间。生产上几乎都用Event Time因为Processing Time受网络延迟和系统负载影响结果不可重现。但用Event Time就必然面对乱序问题于是有了Watermark一个表示“这个时间点之前的数据应该都到齐了”的标记。Watermark的生成策略有两种周期性和标点式。窗口触发条件就是Watermark越过窗口结束时间。这块逻辑如果不理解题一变形就懵。5.3 Kafka的角色不是消息队列那么简单Kafka经常被放在大数据组件列表的最后容易被当成“顺带一提”。实际上它在实时链路里是枢纽上游采集写进来下游Spark/Flink消费出去起到削峰和解耦的作用。核心概念Topic逻辑分类、Partition物理分片决定并行度、Replica副本决定可靠性、Offset消费位点、Consumer Group消费组组内每个分区只被一个消费者消费。考试常考的点生产者ack机制acks0不等确认最快但可能丢acks1等Leader确认折中acksall等所有ISR确认最安全但最慢。ISRIn-Sync Replicas与Leader保持同步的副本集合Leader挂了从ISR里选新Leader。如果ISR缩到只剩Leaderacksall就退化成acks1。消费者位移提交自动提交简单但可能重复消费或丢消息手动提交可控但代码要写对。组件一句话定位典型场景Spark内存计算引擎批处理强项离线ETL、机器学习Flink原生流处理引擎实时风控、实时大屏Kafka分布式消息中间件日志缓冲、实时链路解耦我个人的判断习惯是先看数据有没有界。有界且要求吞吐选Spark无界且要求低延迟选Flink。两者不是替代关系很多架构里是并存的。6. 实验环境和备考节奏纸面知识和能跑起来是两回事理论背得再熟集群起不来一样白搭。HCIA - Big Data虽然偏概念但实验部分能帮你把知识点从“记忆”转成“理解”。我用的是一台16G内存的机器开了三个虚拟机伪分布式跑HDFS和YARN单机跑Hive和HBase。6.1 搭环境时最容易翻车的四个地方主机名和hosts三台机器的主机名必须能互相解析否则DataNode注册不上。我图省事用过IP结果Hive的MetaStore连接串写IP没问题但HBase的RegionServer注册用的是主机名直接报错。免密登录启动脚本依赖SSH没配好免密会卡在输密码。生成密钥后用ssh-copy-id分发别忘了本机也要能免密登录自己。时间同步集群节点时间差超过阈值会导致认证失败和任务异常。用时间同步服务把三台机器对齐这个小细节坑过我不止一次。内存分配YARN的yarn.nodemanager.resource.memory-mb默认值往往偏大虚拟机内存小的时候容器起不来日志里只报“Container exited”看不到根因。调小这个值同时调小mapreduce.map.memory.mb。格式化NameNode这一步也有讲究只在第一次搭建时执行重复格式化会导致clusterID不一致DataNode拒绝启动。真遇到了要么清空数据目录重来要么手动对齐clusterID。6.2 参数不要死记记住它在调什么考试里出现参数题很多人靠死背。我更建议记住“这个参数影响什么维度”。dfs.replication副本数影响可靠性和存储开销。dfs.blocksize块大小影响并行度和元数据量。mapreduce.job.reducesReduce个数影响输出文件数和单任务数据量。hive.exec.dynamic.partition.mode动态分区模式默认strict要求至少一个静态分区改成nonstrict才能全动态。spark.sql.shuffle.partitionsShuffle后分区数默认200小数据量下这个值太大会产生大量小文件。记住“影响什么”题目换个说法你也能对上。死记数字题干一变就废。6.3 复习节奏三轮而不是一遍到底我的安排是三轮每轮目标不同第一轮约两周过一遍全部知识点不求记住只求建立索引。看完一章就在笔记上写三行这章解决什么问题、核心组件是谁、最容易错的地方在哪。第二轮约一周按三条主线横向串。比如把HDFS、HBase、Hive的存储相关部分放一起对比把MapReduce、Spark、Flink的计算模型放一起对比。横向对比最能暴露理解漏洞。第三轮约三到五天刷题加回看错题。错题不要只看正确答案要写下“我为什么选错”是概念不清还是审题问题。这一步的收益比再刷一百道新题都高。刷题时我有个习惯凡是做错的题回到笔记里找到对应章节用一句话把这个知识点重新表述一遍。如果表述不出来说明那一章得重看。这个方法很土但确实能把“似懂非懂”揪出来。还有一点做题时注意题干里的限定词。“默认情况下”“最优方案”“最直接的原因”这些词决定了答案的方向。同一个知识点问“是什么”和问“为什么”答案完全不同。我在模拟题里栽过好几次明明知道原理但因为没看清问的是“根本原因”而选了表面现象。最后分享一个小技巧把这套知识体系里的组件按“数据流向”串成一条线从采集Flume/Sqoop到存储HDFS/HBase到计算MapReduce/Hive/Spark/Flink到消息Kafka到协调ZooKeeper在纸上画一遍。画得出来说明你脑子里有的是一张网而不是一堆散点。画不出来的地方就是下一轮该重点看的地方。我自己画到第三遍时才真正把YARN的调度和Spark的资源申请对上号——原来Spark on YARN模式下Spark的Executor就是跑在YARN的Container里的Driver可能跑在客户端也可能跑在集群里这个对应关系一清楚两章的知识就合并成一章了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑