简介:这份“2023年史上最全的大数据面试题”资料,覆盖Linux&Shell、Hadoop、Zookeeper、Flume、Kafka、Hive、HBase、Sqoop、Scala及Spark十大核心方向,适合大数据开发、运维、云计算、数据治理及架构师岗位的求职者系统备考。内容不限于概念梳理,还包括HDFS读写流程、MapReduce Shuffle、YARN提交流程、Kafka压测与数据一致性、Hive窗口函数与数据倾斜、HBase RowKey设计、Spark宽窄依赖与Shuffle优化等高频考点,并配有参数调优与项目经验总结。资源内附1个docx文档,压缩包共491KB,目录按技术栈逐章组织,便于按需查阅。已有879人浏览学习,适合作为面试前查漏补缺、快速回顾知识框架的实用手册。
1. 大数据面试题到底在考什么:别背题,背这五条主线
2023年这套大数据面试题,网上叫“史上最全”,可你真照着背会发现根本背不完。我把题目按岗位拆开看,发现考官翻来覆去只问三件事:你做过什么、怎么做、出了问题怎么解决。大数据开发、运维、云计算、数据治理、架构师五个方向看似跨度大,实际共用一套底层逻辑:数据从哪来、怎么算得对、宕机了怎么办、表乱了怎么管、架构能不能扩。这篇文章不罗列题号,而是把五条主线的正确打开方式和踩坑细节讲清楚。适合正在准备面试的人,也适合想借这套题反推自己项目缺口的从业者。
2. 大数据开发方向:动手做一遍离线数仓比背一百道题更管用
大数据开发的面试题,最密集的板块是批处理和实时计算。背八股文只能过第一轮,第二轮会让你现场写SQL、写算子、说参数。我见过不少候选人把分区、分桶背得滚瓜烂熟,却解释不清一个简单的groupBy为什么发生shuffle。所以这一章我挑两个被问得最多的点:数据倾斜和拉链表。这两个点几乎隔一场面试就会出现一次,而且都有明确的可执行解法,值得你当场写一遍,而不是只背结论。
2.1 必问的MapReduce与Spark核心:从数据倾斜到两段式聚合
数据倾斜的完整问法一般是:“你的MapReduce任务或Spark任务跑得很慢,有一个任务卡了很长时间,其他任务早就结束了,你怎么定位和解决?”这不是单纯的知识题,而是排查题。先回答定位:打开Spark Web UI,看某个Stage里的task输入记录数,如果某个task读取的数据量是其他task的上百倍,或者Duration明显异常,基本就是数据倾斜。常见原因就三类:key分布不均、业务热点key过度集中、join操作的一侧数据膨胀。定位到原因后,最常见的解决手段是两段式聚合,也叫加盐聚合。
// Spark Scala:两段式聚合处理数据倾斜 import org.apache.spark.sql.functions._ import org.apache.spark.sql.{SparkSession, DataFrame} def fixSkew(df: DataFrame, keyCol: String, aggCol: String): DataFrame = { val saltedDf = df.withColumn("salted_key", concat(col(keyCol), lit("_"), (rand() * 10).cast("int"))) val partial = saltedDf.groupBy("salted_key") .agg(sum(aggCol).as("partial_sum")) val restored = partial.withColumn("origin_key", split(col("salted_key"), "_").getItem(0)) restored.groupBy("origin_key") .agg(sum("partial_sum").as("total_sum")) }这段代码的逻辑是:先把原始key拼上一个随机数后缀,让原本挤在同一个key里的数据分散到10个不同的虚拟key上,各自做一次局部聚合;再把盐去掉,按真实key做第二次聚合。参数上最有讲究的就是rand() * 10里的10,也就是盐粒数量。热点key规模大、倾斜严重时,这个值可以调到100甚至更大;如果倾斜不严重,建议不要加盐,因为加盐会新增一次shuffle,CPU和网络开销并不小。很多面试官会接着问“盐粒数怎么定”,你只要能说出“按热点key的数据量估算,保证每个虚拟key的数据量和其他普通key基本相当”就算过关。
除了代码实现,Hive/MapReduce场景还有两个参数要背熟:set hive.map.aggr=true和set hive.groupby.skewindata=true。前者是开启map端聚合,在map端先合并一部分数据,减少shuffle数据量;后者是让Hive自动把倾斜的key拆分,用两段式聚合完成。两个参数一起用,适合那种不想改SQL、只能靠配置救场的场景。不过要注意,这两个参数不是银弹,它们的本质是“洗数据”,如果业务上对精确度要求极高,不能随便启用,因为部分聚合可能丢失原始分布信息。
另一个高频追问是“如果倾斜发生在join上怎么办”。思路完全不同:不能只靠加盐,而是先看小表能不能广播。Spark里用spark.sql.autoBroadcastJoinThreshold控制广播阈值,默认10MB,如果小表小于阈值就能避免shuffle join。超过阈值的话,可以考虑把热点key拆出来单独join,或者把大表侧的热点key加盐、小表侧同步膨胀再关联。这个追问只要你能说出“先广播、再拆分、最后还原”三步,基本就能让面试官满意。
2.2 高频率SQL题:手写拉链表,把有效期讲清楚
数仓开发岗位的SQL题,拉链表是常客。面试官通常给一个订单维度表,要求你维护历史状态,同时支持按时间回溯。直接覆盖更新会丢失历史,每天存全量快照又太浪费存储,于是就有了拉链表:用开始时间和结束时间来表示一条记录的有效期,结束时间是9999-12-31就表示当前生效。第一步是建表结构:订单ID、状态、开始日期、结束日期。第二步是每天的增量更新逻辑,这也是手写SQL的重点。
-- Hive SQL:订单维度拉链表新增与变更 INSERT OVERWRITE TABLE dim_order_latest SELECT a.order_id, a.status, a.start_date, CASE WHEN b.order_id IS NULL THEN a.end_date ELSE '${bizdate}' END AS end_date FROM dim_order_latest a LEFT JOIN ( SELECT order_id, status FROM ods_order_di WHERE dt = '${bizdate}' ) b ON a.order_id = b.order_id AND a.status = b.status WHERE a.end_date = '9999-12-31' UNION ALL SELECT c.order_id, c.status, c.dt AS start_date, '9999-12-31' AS end_date FROM ( SELECT order_id, status, dt, ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY dt DESC) AS rn FROM ods_order_di WHERE dt = '${bizdate}' ) c WHERE rn = 1;这个SQL的逻辑分两段。第一段拿当前拉链表里还处于生效状态的数据去关联当天增量表,如果当天同一张订单出现了新状态,就把旧记录的结束日期改成当天;如果没关联上,说明状态没变,保留原来的结束日期。第二段把当天增量数据里的最新状态插进去,作为新的生效记录,开始日期是当天,结束日期是9999-12-31。${bizdate}是任务调度日期,每天跑一次时自动替换成当天。
这里有三个细节值得单独说。第一,9999-12-31在业务上也可以换成2100-01-01,但全公司最好统一,否则跨系统比较日期时容易出问题。第二,daily增量里同一订单可能出现多条变更记录,所以必须用ROW_NUMBER按dt倒序取一条,不然会把中间过程错误地当成最新状态。第三,面试官特别喜欢追问“第二天再看这条数据怎么办”,答案是这个更新SQL必须做成幂等,重复跑同一天的结果不能变。做法是在INSERT前先删除当天已经写入的增量区间,或者用事务表保证原子性。
3. 大数据运维与云计算:集群调优和容器化的高频问答
运维和云计算的面试题,和开发完全是两个路子。开发问你“怎么算”,运维问你“怎么扛”。考官通常会扔一个故障现场:某天凌晨任务全挂,NameNode进入安全模式,磁盘报警,你怎么办。你要能说出排查顺序和调整参数,而不是只答“重启一下”。云计算岗还会追到容器资源、弹性伸缩,说明你已经把大数据组件跑在了容器编排平台上。这一章我把两个方向最高频的考点整理出来,每个都给出能落地的命令和配置。
3.1 NameNode和YARN的必答套路:磁盘、堆内存与任务排队
NameNode进入安全模式,是运维面试里出现频率最高的故障。套路是先问原因,再给排查命令,最后说恢复。安全模式的本质是NameNode认为元数据不够安全,拒绝写入。常见原因有三类:磁盘空间不足、元数据加载失败、堆内存异常。排查顺序应该是先看磁盘,再看元数据目录,最后看日志。下面这组命令能覆盖大部分场景:
# 查看数据节点和NameNode健康状态 hdfs dfsadmin -report # 查看NameNode元数据目录磁盘占用 df -h /data/hadoop/name # 查看是否有块缺失 hdfs fsck / -files -blocks -locations | grep 'MISSING'三条命令的执行顺序很重要。dfsadmin -report看的是集群整体概览,能快速确认是否有DataNode宕机;df -h看的是本地磁盘,NameNode元数据目录所在磁盘如果超过90%,就会持续告警;fsck检查的是块完整性,如果输出里有MISSING,说明副本数不足,这时候直接退出安全模式只会让数据风险继续扩大。很多人一看到安全模式就执行hdfs dfsadmin -safemode leave,结果没过几分钟又退回去,就是因为没找到根因。正确做法是:先扩容或清理文件,再修复缺失块,最后才考虑手动退出安全模式。
YARN侧的必问题也集中在一类:任务排队或者资源不够。面试官会给你一个场景:集群有空余CPU,但任务全部卡在ACCEPTED状态。这个现象大概率是内存不足,不是CPU不足。YARN调度器以内存为主要维度,你要会调yarn-site.xml里的三个核心参数:
<property> <name>yarn.nodemanager.resource.memory-mb</name> <value>8192</value> <description>每个NodeManager可分配的总内存,需要预留系统与HDFS余量</description> </property> <property> <name>yarn.scheduler.minimum-allocation-mb</name> <value>1024</value> <description>单个容器最小内存,调大可以减少容器数量,调小可以提升利用率</description> </property> <property> <name>yarn.scheduler.maximum-allocation-mb</name> <value>4096</value> <description>单个容器最大内存,不要超过NodeManager总内存的一半</description> </property>这三个参数是一个组合拳。yarn.nodemanager.resource.memory-mb是物理边界,一般取机器内存的70%到80%,剩下留给操作系统和HDFS缓存;minimum-allocation-mb决定了每个任务容器最少拿多少内存,调小了任务粒度更细、调度更灵活,但集群task数量爆炸时会增加调度开销;maximum-allocation-mb是防止某个任务申请超大内存,导致其他任务全部排队。面试官追问“为什么设置了最大4096MB还有任务占8GB”时,你要能答出:这个最大限制只对调度器分配生效,如果任务自身通过其他参数指定了更大内存,可能绕过限制,需要同时检查提交命令里的资源配置。
运维岗还经常考“怎么判断是数据倾斜还是集群资源不足”。这也是一道典型的区分题:集群资源不足时所有任务都很慢,数据倾斜时只有一个或少数几个任务慢。对应到日志,前者看yarn application -list里大量任务等待,后者看Spark/Flink Web UI里某个task的输入量异常。会看这两个地方,基本就能把问题归位。
3.2 云计算岗位的容器化与弹性扩缩容:从资源配置到自动伸缩
云计算方向的大数据面试题,通常默认你已经把Spark或Flink跑在容器编排平台上了。高频问题有两个:容器资源怎么配、流量波动时怎么自动扩缩容。容器资源配错会直接导致任务OOM或被驱逐,常见做法是给每个角色设置独立的内存与CPU上限。以流计算任务为例,任务管理器侧的资源不能只算数据量,还要算状态后端、网络缓冲、反压消耗。下面这段YAML可以当作模板来记:
spec: jobManager: resource: memory: "2048m" cpu: 1.0 taskManager: resource: memory: "4096m" cpu: 2.0 parallelism: default: 4这段配置里,JobManager主要承载作业协调和Checkpoint管理,内存不用给太大,但必须有稳定CPU;TaskManager是真正干活的角色,内存要按每个并行实例独立计算。4096MB的TaskManager如果跑4个并行度,每个并行实例大约分到1GB内存,这对有状态计算而言可能不够。所以实际经验是:内存给足,CPU量先按保守值设,等反压指标稳定后再逐步调低。面试官问“怎么判断TaskManager内存够不够”,你只要说看taskmanager.memory.process.size和GC日志,Full GC频繁就说明堆太小,内存溢出说明整体进程内存不够,两个方向完全不同。
弹性扩缩容是云计算岗位的加分题。Kubernetes里最直接的是HorizontalPodAutoscaler,按CPU利用率扩缩容。但大数据任务不能只看CPU,还要看事件队列的堆积量。一个可行的方案是自定义指标,把积压消息数作为扩缩容依据。基础版本先理解下面这个HPA:
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: flink-taskmanager-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: flink-taskmanager minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 60这个配置的含义是:任务管理器实例数维持在2到10之间,当平均CPU利用率超过60%时扩容,低于60%时缩容。实际操作中要注意两个坑:一是流计算任务的CPU利用率本来就是波动的,直接把60%作为阈值会导致频繁扩缩;二是在Kubernetes上扩缩容不等于立即生效,需要等待实例启动和状态恢复,所以阈值要留缓冲,通常建议45%到55%之间。更好的做法是给扩容增加冷却时间,但标准HPA的冷却配置不够细,这时可以结合专用的事件驱动型自动扩缩组件,把制品队列长度变成指标,不过那是进阶内容,面试时能讲出“用事件堆积量代替CPU利用率”的思路已经足够。
4. 数据治理与架构师:从元数据到数据质量,考察的是判断力
数据治理和架构师岗位,刷题的人最少,但恰恰最容易拉开差距。数据治理容易被理解成“写规范文档”,架构师容易被理解成“画技术架构图”,实际上考官真正想听的是你怎么做取舍。治理的取舍是质量和成本的平衡,架构的取舍是延迟、一致性和成本的平衡。这一章给两个高频场景的处理框架,不给你背不动的概念,只给能直接复用的流程和参数。
4.1 数据治理面试题不是背概念,是讲流程
数据治理岗位的面试题,十有八九从“你做过哪些数据治理工作”开始。如果你回答“元数据管理、数据质量、数据血缘”这种词列表,基本就进入被动状态了。面试官真正想听的是:面对一份没人敢信的报表,你怎么一步步把它治好。所以答案要从一个具体场景切入,比如“某公司订单报表每天和财务对不上”。第一步拉元数据,确认这张表由哪条链路产出;第二步定义质量规则,检查字段的空值、唯一性和值域;第三步落地监控规则,跑出问题后通知业务方;第四步反推链路,找到数据链路里哪个环节出了问题。
面试时能把这四步讲出来,比背十本规范文件都有用。质量规则是最容易具体化的点,下面这张表可以当作记忆模板,也可以当作你项目里的规则清单来用:
| 规则类型 | 检查方式 | 失败处理 |
|---|---|---|
| 非空率 | sum(case when col is null then 1 else 0 end) / count(1) | 大于阈值告警,阻塞发布 |
| 唯一性 | count(1) != count(distinct col) | 告警并定位重复来源 |
| 值域范围 | min(col)、max(col)对照业务阈值 | 超范围自动拦截 |
| 数据波动 | 今日量对比近7日均值,偏差超过20% | 告警并进入人工确认 |
| 实时延迟 | 数据产生到落库时间差 | 超过阈值触发重跑或降级 |
这张表的价值在于,每条规则都对应一个可计算的SQL表达式和一个明确的失败动作。面试官追“你怎么发现质量问题”时,你直接把表里的检查方式说出来,他就能判断你确实做过。再追“然后呢”,你就讲失败动作和通知机制,比如通过告警把问题推到某平台,同时阻断下游报表发布。这个闭环说完,数据治理面试题基本过线。
还有一个高频追问是“元数据怎么采集”。常见做法是每天定时扫描Hive的元数据库,把表名、字段名、分区、所有者、更新时间抽出来,同时根据SQL解析出表与表之间的血缘关系。注意血缘分析不要一上来就做解析级,先做表级血缘,也就是从执行日志里抽“哪些表被哪张表读写了”,这个简单且不容易出错,字段级血缘等成熟了再加。能说清楚这个层级划分,面试官会觉得你有工程经验,而不是只懂理论。
4.2 架构师题:怎么设计一个实时数仓并自圆其说
架构师面试题通常是开放题:“如果业务要做实时大屏和秒级告警,数据源是数据库变更数据和日志,你会怎么设计?”很多人一上来就画一堆组件,结果被一句“你的数据可能丢”问住。正确的答题顺序是先问约束,再给设计。约束包括:每秒多少条数据、允许的延迟是多少、数据能不能容忍丢失、要不要回溯历史。
拿到约束后,再给一个分层设计。实时数仓没必要照搬离线数仓的五层架构,通常三层就够:接入层、计算层、服务层。接入层用消息队列,主要解决高并发写入和削峰问题;计算层用流计算引擎,做窗口聚合、维表关联和事件时间处理;服务层用支持高并发点查的OLAP引擎,承接大屏和告警查询。下表是我在设计这类方案时习惯用的选型逻辑,你也可以把它当作面试答案骨架:
| 分层 | 组件类型 | 选型理由 | 翻车点 |
|---|---|---|---|
| 接入层 | 消息队列 | 高吞吐、可重放 | 分区数跟不上消费并行度 |
| 计算层 | 流计算引擎 | 秒级窗口、状态管理 | Checkpoint太久造成延迟 |
| 服务层 | 列式OLAP引擎 | 高并发聚合查询 | 实时写入造成小文件 |
| 调度层 | 容器编排平台 | 弹性扩缩容 | CPU指标不能反映真实负载 |
每说一个组件,都要补一句取舍,这才是架构师题的核心。比如消息队列选型为什么不用普通队列,因为需要数据可以重放;流计算层为什么要求支持状态,因为去重和窗口累计都需要持久化状态;服务层为什么不选事务型数据库,因为大屏查询是读多写少、聚合多更新少。面试官最在意的是你不要无脑堆组件,所以每个选择后面都跟上“如果数据量到一半以下,完全可以用单机方案替代”这种边界感。
架构设计题还有一条必追线:延迟和一致性。实时数仓最常见的坑是“实时链路算出来的数据和离线链路对不上”。原因往往是两条链路的计算窗口口径不一致,或者实时链路过早提交了不完整数据。解决思路是:核心大屏指标允许秒级延迟但必须最终一致,做法是用离线任务每天修正一次实时结果;次要指标可以容忍小范围偏差,但要在页面上标注为“实时估算”。能把这个口径问题提前说出来,比任何技术选型都加分。
5. 面试题避坑:五个容易翻车的问题现场
我把近几年身边候选人面试大数据岗位时的常见翻车点整理了一遍,挑出五个最典型的。每一条都按“现象、原因、解决”拆开看,你会发现这些问题不是知识不够,而是答题姿势不对。避开这些坑,面试难度至少降低三成。
现象一:背了一百道题,却被一句“你项目里遇到过OOM吗”问穿。候选人能把MapReduce原理倒背如流,但一问到自己的业务场景就支支吾吾,说“项目里好像没遇到过”。原因很简单,刷题时只看了“为什么发生OOM”的概念题,没有准备“我当时怎么排查”的实战题。解决方法是每个岗位准备两个属于自己的项目案例:一个偏故障处理,比如从日志里发现某个executor内存溢出,通过调大spark.executor.memory和降低并行度解决;一个偏业务优化,比如某张宽表查询从五分钟压到十秒。案例不追求高大上,但必须能一句话说出背景、动作、结果。
现象二:窗口函数背得滚瓜烂熟,手写SQL时却在“去重后取最近一条”上卡住。会写ROW_NUMBER的人很多,但一结合去重就会出错。原因是平时只刷单知识点,没有把排名、去重、时间条件组合在一起练。解决方法是每天手写三道组合SQL,比如“按用户分组取最近一次订单金额,并且只保留金额大于100的记录”,写完再去和同事或网上的答案对逻辑。面试时如果逻辑不清,先大声说“我先用ROW_NUMBER按时间倒序编号,再过滤rn=1”,考官就能看出你的思路,即使代码有瑕疵也有机会补救。
现象三:数据治理题只答“元数据、数据质量、血缘”,被追问“然后呢”就断掉。这几乎是数据治理岗位的通病。原因是把概念当作答案,没有把概念串成流程。解决方法是把每个概念都挂在一个业务场景上,比如“血缘”就讲“报表数据异常时,我根据血缘关系从下游表反查到上游表,最后定位到某个字段没有做空值过滤”。讲流程时至少要覆盖:问题出现、如何定位、如何修复、如何防止再发生。一个故事能讲两分钟,比十个名词都有效。
现象四:架构题只画技术栈,被问“这个方案一个月要多少资源”立刻沉默。面试官问成本,不是真的让你报价,而是在考察你有没有估算过资源。原因是很多候选人只看架构图,从不看监控面板。解决方法是养成记数字的习惯:你的任务处理峰值每秒多少条、每个并行度消耗多少内存、集群有几个节点、高峰时段CPU使用率多少。面试时即使数字是估算的,也要给出计算过程:“每个taskManager给我4G内存,我开了8个并行度,单机最多跑2个,按最高流量预留1.5倍。”说出这个推导过程,比给出精确预算更让面试官认可。
现象五:运维题只会重启大法,被问“重启前先看什么”就卡住。大数据组件的重启代价很大,直接重启会把现场证据全冲掉。原因是缺少真实的故障排查经验。解决方法是在本地起一个单机HDFS,故意制造磁盘满、副本数不足这类问题,然后跑一遍“先看日志、再看指标、最后动服务”的流程。面试时至少要说出一句“我会先保存NameNode和DataNode的日志,再做故障快照,最后才考虑重启”,这句话能把你和其他只会重启的候选人区分开。
6. 用一周时间把面试题跑成项目经验:一个可复现的练习清单
如果你准备时间有一周,与其继续翻面试题合集,不如按下面的清单把题目改成练习。核心方法是每道题都要落到一个命令、一段SQL或一份配置上,而不是落在“背过”这个状态上。
周一练HDFS和YARN:用Docker起一个单机Hadoop环境,执行hdfs dfs -mkdir、hdfs dfsadmin -report、yarn application -list,再停掉一个DataNode,观察SafeMode现象。这半天能让你把运维面试题里的“安全模式”真正理解。周二练Spark:准备一份TPC-H或等价业务数据,写出groupBy、join、窗口函数三类算子,故意制造一个重key,观察Spark UI里task分布,再用2.1节的两段式聚合修复。周三练Flink:写一个基于事件时间窗口的WordCount或订单统计,把并行度调成2和8各跑一遍,对比Checkpoint耗时,记录延迟变化。周四练SQL:把2.2节的拉链表和“近7日留存用户明细”这种窗口函数题各手写两遍,重点练ROW_NUMBER、LAG、LEAD的组合用法。周五练数据治理:给自己常用的表写一份数据质量规则,包含非空、唯一性、值域、波动四类,然后用SQL手工执行一遍,记录哪些规则能防住真实脏数据。周六把这一周数据和命令整理成一份问答笔记,每条笔记结尾写“这个问题背后考的到底是配置、原理还是排查能力”。周日模拟一次完整面试:随机抽五道题,每道题逼自己按“背景、动作、结果”讲三分钟。
这个清单的价值在于,你做完之后会自然形成项目经验,而不是只有面试话术。比如你说“我调过Spark并行度”,没有练习过的人只会背参数,你却能说出“默认值跑出来的task记录数差距有20倍,我把spark.sql.shuffle.partitions从200调到800后,单个task输入从2.1G降到270M”。这就是考官愿意听见的答案。我当年最吃亏的一件事,就是花了一个月刷题,却没打开过一次真实集群,面试时被一句“你排查过最慢的SQL是什么”问得哑口无言。后来改成用一周把题跑成命令,效果立刻不一样。希望这个习惯能帮到也在准备面试的你。
本文还有配套的精品资源,点击获取