ARTICLE DETAIL

资讯详情

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

唯品会数据开发岗面试复盘:Hive、Spark、Kafka高频考点与数仓实战

唯品会数据开发岗面试复盘:Hive、Spark、Kafka高频考点与数仓实战 1. 项目背后的岗位真相唯品会数据开发岗面试到底在选什么人2019年秋招那阵子我前后投了十几家互联网公司的数据开发岗唯品会这条线算是我准备得最认真的一家。一方面是因为电商场景下的数据开发天然比纯平台型公司更有业务感另一方面唯品会的面试流程在当时的秋招大潮里属于比较典型的“基础项目场景”三段式。把这个岗位的面试经历拆开来看其实能映射出当时乃至现在数据开发岗面试的大部分套路。先把这个岗位的基本盘说清楚。唯品会的数据开发岗日常工作基本围绕数据仓库建设、ETL调度开发、数据质量保障、以及面向业务方的数据服务交付。听起来挺宽泛但落到面试题上考察的点非常集中Hive/Spark的底层原理、SQL功底、数仓建模思想、离线与实时链路的基本认知、以及异常排查的实战能力。我当时看完JD职位描述之后的第一反应是这家公司要的不是“会用工具”的人而是“能理解数据加工全链路”的人。这一点在后来的面试里得到了充分验证。比如Hive的题目从来不问“left join和inner join的区别”这种初中题而是直接给你一个数据倾斜的场景让你现场分析原因、给出解决方案还要求你说清楚为什么这个方案能生效。所以这篇文章的核心定位很明确如果你正在准备数据开发、大数据开发相关的岗位面试或者你已经在做数据开发但想系统梳理一下自己的知识体系那么这份复盘值得你认真看一遍。我会把当时遇到的真题、我踩过的坑、以及后来作为面试官视角反推出来的考察逻辑全部摊开来讲。2. 考察逻辑深度拆解从笔试到三轮面试每个环节都在验证什么2.1 笔试环节SQL是门槛但拉开差距的是场景题唯品会数据开发岗的笔试是线上完成的题量不算特别大但时间很紧。题型分布大概是选择题涵盖Hadoop生态基础、JVM基础、Linux操作、SQL编写题大概三到四道、以及一两道开放性的场景设计题。选择题里给我印象最深的是一道关于Hive的题目Hive的执行引擎有哪些选项里混了MapReduce、Tez、Spark。这题本身不难但如果只背过“Hive是基于MapReduce的”这种旧概念就很容易漏选Tez和Spark。这其实是一个信号唯品会当时已经在大量使用Spark加速Hive作业所以面试官默认你应该知道Hive on Spark已经是很成熟的方案。SQL题部分最典型的一道是“计算每个用户的连续登录天数”。这道题现在已经是烂大街的经典题了但放在2019年秋招考察的就是你有没有掌握窗口函数。解法也很清晰先用row_number给每个用户的登录日期排序然后用登录日期减去序号得到一个日期字段最后按用户和这个差值字段分组计数就能得到连续登录段。核心代码如下select user_id, count(1) as continuous_days from ( select user_id, login_date, date_sub(login_date, row_number() over (partition by user_id order by login_date)) as grp from user_login_log ) t group by user_id, grp;笔试里还有个让我印象深刻的场景题大致是假设订单表每天有上亿条数据需要按小时统计各品类的GMV成交总额并输出到报表系统你会怎么设计这条链路这题没有标准答案考察的是你对整个数据链路的理解。我当时的回答思路是源数据通过Sqoop或Canal同步到Hive数仓的ODS层然后按小时粒度做一次轻量汇总到DWD/DWS层最后通过Sqoop或DataX同步到MySQL供报表系统查询。后来回头看这道题其实暗含了对“为什么要分层”的考察——如果不分层所有计算都直接压在线上的业务库上不仅慢而且会影响业务系统的稳定性。2.2 一面技术面MapReduce原理和Spark作业调优是分水岭一面是电话面试全程大概四十分钟。上来没让做自我介绍直接问“你讲一下MapReduce的shuffle过程。”这个问题的杀伤力在于背过书的人能说出“分区、排序、溢写、合并”几个关键词但真正理解的人能把整个流程串起来讲清楚。我当时是按这个顺序讲的map端先做分区默认按key的hash值模上reduce数量然后进入内存缓冲区默认100MB达到80%阈值后开始溢写溢写前会做一次排序如果配置了combiner还会先做一次本地聚合溢写出来的多个文件最后会被merge成一个文件reduce端会拉取属于自己分区的数据拉取完后在内存里做归并排序最后输入给reduce函数。讲完之后面试官追问了一个点“combiner和reducer的区别是什么”这个追问很关键因为很多人会把combiner理解成reducer的简单替换但实际上combiner是在map端本地执行的它的输入输出类型必须和reducer保持一致而且不能指望它对所有场景都适用——比如求平均值就不适合用combiner因为局部平均再全局平均不等价于全局平均。Spark的题目问得更实操。面试官给了一个场景你的Spark作业跑得很慢你会从哪些角度去排查这个问题其实是在考察你有没有真实的排障经验。我当时的回答分了几层先看是不是数据倾斜通过Spark UI观察各task处理数据量是否严重不均再看是不是shuffle参数配置不合理比如reduce端缓冲区太小导致频繁spill然后看是不是资源分配不足executor数量、executor内存、并行度设置最后看是不是代码本身有低效写法比如多次扫描同一份数据源。接着面试官问了一道我当时觉得很有水平的题“如果两张表join的时候其中一张表特别小你会怎么做”这题明显是在引导你说Broadcast Join。原理很简单把小表广播到每个executor的内存里避免shuffle从而大幅提升join性能。在Spark SQL里实现也简单早期版本用spark.sql.autoBroadcastJoinThreshold来控制默认10MB后来可以手动hint。但面试官马上追问“如果小表有2GB你还会广播吗”这个问题我当时卡了一下。后来才反应过来广播不是免费的——driver要把数据序列化后发给每个executor如果executor数量很多网络传输和内存开销都会很大。所以广播阈值不是越大越好要结合集群规模和小表实际大小来判断。2.3 二面技术面数仓建模和业务指标是重头戏二面是现场面面试官是数据团队的负责人。这一面的风格明显不一样题目开始从“工具”转向“业务”。一上来就问了一个开放性问题“如果你来设计一个电商数仓你会怎么分层”这个问题我很熟因为数仓分层本来就是我自己项目里最常做的事。我按标准答案来答ODS层放原始数据保持和源系统一致DWD层做清洗、脱敏、维度退化统一数据类型DWS层按业务过程做轻度汇总比如按用户、商品、店铺聚合ADS层面向具体应用比如报表、取数。每一层的加工逻辑都讲清楚后面试官追问了一个让我印象比较深的问题“ODS层是不是必须和源系统保持一致如果不能保持一致呢”这个问题实际上在考察你对数据质量的理解。我当时回答不能100%保证一致原因是线上业务库的数据本身可能就有脏数据而且binlog同步和增量抽取都存在延迟ODS层能保证的是“在某个时间快照下尽可能接近源系统”。面试官对这个回答应该是认可的因为他接着就让我讲了一个我在项目中做数据质量校验的案例。指标口径的问题也很经典“用户的复购率你怎么定义如果按订单算和按用户算有什么区别”这种题没有标准答案关键在于你能不能看出不同口径对最终结果的影响。按订单算复购率分子是“下单次数大于1的订单数”分母是“总订单数”这种算法受单个用户多次下单的影响很大按用户算复购率分子是“购买次数大于1的用户数”分母是“总购买用户数”这种算法更符合业务上对“用户忠诚度”的理解。我当时把两种口径的差异说清楚后面试官说了一句很到位的话“不谈论口径就是耍流氓。”2.4 三面HR面稳定性、业务理解、薪资预期三面是HR面看起来轻松其实暗藏杀机。HR面刷人的案例我听过不少核心原因基本都出在“稳定性”和“薪资预期”上。当时HR问了我几类问题为什么选择唯品会、对加班怎么看、未来的职业规划是什么。这类问题的回答策略其实很明确一是表达对电商业务的兴趣二是展现自己的抗压能力三是让对方觉得你至少打算在这里干两三年。我当时的回答是“电商数据场景复杂度高从流量到转化到履约链路长、数据多样性强对数据开发来说是很好的成长环境。”这个回答看起来像是在表忠心但实际上是让HR放心你不是来过渡一下就走的人。薪资方面HR问期望薪资的时候我给了个范围而不是具体的数因为范围会让谈判有些余地。这个技巧在秋招里很重要——如果你只说一个数高于对方的预算就没得聊了给范围反而能留出折中空间。3. 高频考点逐项拆解Hive、Spark、Kafka一个都不能少3.1 Hive的考点不只是SQL底层原理才是分水岭Hive作为离线数仓的核心组件在数据开发面试里是绝对的高频考点。但很多人准备Hive面试的时候只刷SQL题看到一个“连续登录”题就以为准备到位了其实差得远。我从那次秋招面试里总结出来的Hive高频考点主要有这么几块第一Hive的架构和组件包括MetaStore、HiveServer2、执行引擎等第二Hive和关系型数据库的区别尤其是“Hive说不支持事务、不支持行级更新”这种历史结论在什么时候已经被打破了比如Hive的ACID表、Hive LLAP第三表的类型内部表、外部表、临时表和管理方式差异第四分区和分桶的区别和应用场景第五Hive SQL的优化手段。分区和分桶这道题面试官问得特别细。我当时的回答是分区是按目录来组织的比如按日期分区每个分区对应一个目录目的是减少扫描的数据量分桶是按文件的hash来组织的一个分区内可以再划分成多个桶文件目的是让抽样查询和bucket join更高效。面试官接着问了一个进阶问题“分区字段和分桶字段能是同一个字段吗”这题我当时有点犹豫后来想明白了——可以但一般没人这么做因为如果既分区又分桶物理上会形成一个两级目录结构分桶的意义就不大了反而增加复杂度。Hive优化里我当时被问到的一个具体场景是一个Hive SQL跑了好几个小时怎么排查和优化这个问题的答题框架和Spark问题很像但细节不同。第一步先看是不是有数据倾斜尤其关注group by和join的key是不是有明显的热点第二步看是不是有大量小文件如果上游产出了成千上万个小于128MB的文件会严重拖慢后续读取第三步看SQL本身能不能改写比如用子查询代替多次join、用union all代替union、过滤条件下推等。这里有个我在项目里踩过的坑Hive的count(distinct)在大数据量下性能极差因为它只能用一个reduce去重正确做法是先group by去重再count。3.2 Spark除了RDD和DataFrame更要讲清楚作业执行流程唯品会的技术面里Spark的问法已经从“Spark和Hadoop有什么区别”升级到了“一个Spark作业从提交到执行经历了哪些阶段”。这个问题的标准回答是先用spark-submit提交作业SparkSession会创建SparkContextDriver端将代码转换成DAG有向无环图DAGScheduler根据宽窄依赖将DAG划分成多个Stage每个Stage包含一组可以并行执行的TaskTaskScheduler把Task分发到Executor上执行Executor执行完后将结果返回给Driver。面试官常见的追问有两个。第一个是“宽依赖和窄依赖的区别是什么为什么要这样划分”窄依赖指的是父RDD的每个分区最多被子RDD的一个分区使用比如map、filter宽依赖指的是父RDD的多个分区被子RDD的多个分区使用比如groupByKey、join。划分的意义在于窄依赖可以在同一个Executor上做流水线计算不需要shuffle宽依赖会产生shuffleshuffle是Spark作业里最耗时的环节。第二个追问是“为什么要用DataFrame代替RDD”这个问题的核心答案在于性能优化。DataFrame有schema信息Catalyst优化器能基于schema做谓词下推、列裁剪、常量折叠等优化而RDD没有schemaSpark没办法做这些基于逻辑执行计划的优化。此外DataFrame还支持Tungsten的二进制内存管理和code generation可以大幅提升计算效率。我当时还补了一句“功能层面RDD能做的DataFrame基本都能做但有的时候处理非结构化数据RDD会更灵活。”这个补充让面试官觉得我有真实的场景判断力而不是纯粹背书。3.3 Kafka不止是消息队列更是数据链路里最重要的一环在电商数据开发岗的面试里Kafka的重要性远超很多人的预期。因为电商的数据链路几乎必然经过Kafka业务日志、订单变更、用户行为事件都是先打进Kafka然后再由Flink或Spark Streaming消费进数仓。Kafka的高频考点很固定一是消息模型点对点和发布订阅的区别二是分区机制为什么分区能提升吞吐分区内消息是有序的三是副本机制Leader和Follower的同步策略四是怎么保证消息不丢失producer端acksallbroker端min.insync.replicas2consumer端关闭自动提交五是怎么保证消息不重复消费幂等Producer、消费者端去重。面试官当时问了一个让我印象很深的问题“如果Kafka的consumer消费速度跟不上producer的生产速度你会怎么处理”这个问题难就难在它没有单一的正确答案。可以从几个层面回答consumer端可以增加分区数和消费者数量、调整fetch大小和max.poll.records参数、优化消息处理逻辑producer端可以降低生产速率、做批量发送架构层面可以做消息分流把不同类型的消息放到不同的Topic里避免一个消费者组扛所有流量。我当时选择了分流和调参两个方向面试官点头表示认可。4. 实战复盘笔试、面试、谈薪的完整时间线与经验教训4.1 简历投递和笔试准备的时间安排2019年秋招互联网公司的节奏其实拉得比很多人想象中更长。唯品会的校招通道是八月初开的笔试安排在九月中旬面试在九月下旬到十月上旬整体节奏属于典型的中场选手——不像腾讯阿里那么早也不像一些传统行业那么晚。我在笔试前大概有两周的准备时间。那两周我是怎么安排的每天雷打不动刷三道SQL题其中至少一道是窗口函数相关的每天看一个Hive或Spark的源码级知识点比如shuffle的过程、分区机制、执行引擎的区别周末找一套往年的大数据面试题按正式笔试的时间限制完整做一遍。这里有个想提醒后来人的点SQL题一定要动手写不要只看题解。数据开发面试的SQL题难度通常比你日常工作中写的报表SQL高不少光看不练很快就会露馅。4.2 面试现场的时间分布和氛围一面电话面大概四十分钟前半段是基础原理题后半段是场景题。二面现场面大约一个半小时前半段是数仓设计和业务指标后半段是让我在白板上画一条数据链路或者写一段SQL。三面HR面大约半小时聊的更多是意愿和稳定性。现场面有一个细节让我记忆犹新面试官让我在白板上写SQL用来统计每个品类下销售额Top10的商品。这道题的核心是窗口函数row_number()的用法加where过滤select category_id, product_id, sales_amt from ( select category_id, product_id, sales_amt, row_number() over (partition by category_id order by sales_amt desc) as rn from product_sales_daily where dt 2019-09-15 ) t where rn 10;写完之后面试官追问了一句“如果同一个商品有多个品类标签怎么处理”这个追问实际上在考察维度建模里的“多对多关系”处理方式我当时说可以通过桥接表来解决或者在DWD层做去重时指定一个主品类。面试官看起来对这个回答比较满意。4.3 谈薪环节预期管理和Offer对比唯品会数据开发岗的薪资在2019年秋招里属于行业中等偏上的水平但和同期阿里腾讯的SPSpecial Offer相比还是要低一档。我当时也拿到了两只独角兽公司的Offer但最终选择唯品会的原因很简单电商数据场景的链路足够完整从埋点到数仓到BI到算法特征你能在同一个公司里一次性看到数据的全生命周期。如果说有什么教训要分享那就是薪资谈判不能只看base要综合看股票/期权、年终奖基数、补贴和公积金比例。唯品会的年终奖基数是比较可观的存在这点在最终对比Offer价值的时候是占优势的。5. 高频面试题型汇总数据开发岗必刷的六类题目5.1 连续类问题连续登录、连续购买、连续活跃这类型题目在数据开发面试里出现频率极高核心解法基本就是窗口函数加差值分组。除了前面提到的连续登录天数还会考连续购买3个月以上的用户、连续7天活跃的用户等变体。解法思路完全一样先用row_number()排序再用日期减序号得到分组字段最后按用户和分组字段计数。要特别注意的一个坑是如果数据存在重复记录比如用户当天登录多次日志里有多条记录必须先按用户和日期去重再做后续处理。如果不先做去重连续登录天数会被错误地放大。我在笔试时遇到过类似问题后来养成了写SQL之前先确认数据粒度的习惯。5.2 TopN问题分组取前N名用窗口函数一网打尽分组取TopN是数据开发日常工作中最常写的SQL类型之一。无论是统计每个类目下销售额Top10的商品还是每个店铺下销量Top5的SKU都可以用row_number()或rank()配合partition by实现。要注意rank()和dense_rank()的区别rank()在有并列时会跳过后续排名比如两个并列第一下一个是第三名dense_rank()不会跳过两个并列第一下一个是第二名。如果业务上要求“不管并列必须取前10条”用row_number()如果要求“并列都算”用dense_rank()。5.3 留存问题次日留存、7日留存的SQL怎么写留存问题是数据分析面试里的常客数据开发岗也经常会考。核心逻辑是找到某个时间窗口内的新增用户集合然后判断这些用户在之后第N天是否有活跃记录。写SQL的手法通常是先求出每个用户的激活日期再关联活跃日志用datediff算出日期差最后统计各日期的留存率。这类题的难点在于数据量大的时候关联查询写不好就会跑很久。优化的思路是先把活跃用户去重成一个小的集合再进行关联减少join的数据量。5.4 漏斗问题曝光到点击到加购到下单每一步转化怎么算漏斗分析在电商场景里极度常见面试官的问法通常是“给你曝光表、点击表、加购表、下单表怎么统计每一步的转化率”最直观的做法是分别统计各个阶段的人数然后相除。但面试官真正想听的是你如何识别漏斗中的用户范围比如是否限定同一用户、同一会话。进阶一点的回答是使用窗口函数做多表关联把每个用户的行为事件按时间排序找出它是否在曝光之后的一段时间内发生了点击。这样算出来的漏斗才是时间上有先后逻辑的漏斗而不是简单的集合交集。5.5 数据倾斜问题从表象到底层原理的完整回答模板数据倾斜几乎是大数据面试的必考题。面试官不会问“什么是数据倾斜”而是会直接给你一个场景一张订单表其中某个商家的订单量占比30%你用它和其他表做join发现reduce阶段某个task跑了很久怎么解决完整的回答应该包括几个层面。第一确认倾斜现象查看Spark UI或Hive日志判断是否有某个task处理的数据量远超其他task。第二分析倾斜原因可能是key本身有热点比如某个商家的订单量特别大也可能是join时两张表的key分布不均。第三给出解决方案如果是大key和小表join可以用广播如果是大表join大表可以对热点key加随机前缀做两次join如果是group by倾斜可以先加随机key打散再聚合一次。一定要把原理讲清楚而不是只报解决方案的名字。5.6 数仓设计题怎么把一套数仓从零搭起来数仓设计题是数据开发岗和数仓岗面试的重头戏。问到这类题时面试官想考察你的不只是“会分层”这个结论而是你对每一层做什么、怎么做、为什么要这样做的深层理解。我建议的回答框架是先给出完整的分层设计ODS、DWD、DWS、ADS四层然后结合一个具体业务过程举例说明每个层次的表结构和加工逻辑最后补充数据质量、数据治理、元数据管理这几个加分项。如果能顺手说一下数仓规范比如表命名规范、字段命名规范、生命周期管理会让面试官觉得你确实在真实环境里打磨过这套东西。6. 项目经验怎么讲才能让面试官觉得你有实战能力6.1 项目描述的黄金公式背景、动作、结果面试里被问最多的问题其实不是八股题而是“你讲讲你的项目”。很多人项目经验很丰富但讲的时候东一句西一句面试官听完完全抓不住重点。我后来总结了一个非常有效的项目描述框架背景-动作-结果。背景部分用一两句话说清楚项目要解决什么问题比如“当前报表平台凌晨计算任务经常延迟到早上七点才跑完”。动作部分说清楚你具体参与了什么注意是“你参与”而不是“你们的项目”重点强调你用到的技术栈和方案选型逻辑。结果部分要量化比如“将任务耗时从4小时缩短到1.5小时资源占用降低40%”。如果项目结果没法量化可以退而求其次说“平台上线后业务方零投诉”。6.2 项目真实性的鉴别与准备面试官会往深里挖面试官在听完项目介绍后一定会往深里挖细节。我遇到过的最典型的追问是“你刚才说你们用Spark重写了Hive作业具体是怎么重写的Hive和Spark的SQL兼容性怎么处理”这类问题如果你只是“用过”而没有真正的踩坑经历很容易卡住。我当时的项目经历里确实有一个Hive迁移Spark的案例所以我能够讲出具体的细节把Hive SQL迁移到Spark SQL时很多Hive的UDF需要做适配因为有些Hive内置函数在Spark SQL里不存在还有一些隐式类型转换的差异比如Hive里11是true但Spark SQL里会报错。这种细节是编不出来的只有真正做过的人才能脱口而出。6.3 没有大厂项目经验怎么办用业余项目和数据竞赛补位很多准备秋招的同学最头疼的事情是简历上没东西可写。这类同学我给的建议只有一条没有真实的生产项目就自己造一个。用公开数据集做一套简单的数仓设计比如用电商公开数据做一份用户购买行为分析把从数据采集、清洗、建模、ETL、报表展示的整个流程完整做下来写成文档配上截图这就足够证明你具备数据开发的基本链路能力。除了项目Kaggle、天池、DataFountain上有很多数据竞赛做完之后把代码整理到GitHub上把解题思路写成一篇技术博客。面试官看到的不只是你的技术水平还有你的主动学习能力这在秋招里非常加分。7. 高频面试题速查表与我的个人体会考察方向典型问题回答要点易错点HiveHive的内外部表有什么区别内表删表连带删数据外表只删元数据只说“外表安全”但没讲底层存储逻辑Hive分区和分桶的区别分区按目录、分桶按文件hash混淆两者的物理组织方式SparkSpark作业执行流程DAG划分Stage、Task调度、Executor执行忽略DAGScheduler的职责Spark数据倾斜怎么解决热点key加随机前缀、广播、两阶段聚合只说方案名字不讲原理Kafka怎么保证消息不丢失Producer、Broker、Consumer三端配置只提acksall忽略消费端提交机制数仓数仓怎么分层ODS、DWD、DWS、ADS各层职责只说层名不说每层的加工逻辑业务复购率怎么算口径不同结果不同不区分“按用户”和“按订单”笔试、面试、谈薪这一套流程走下来我最大的体会是数据开发岗的面试本质上是对“数据全链路理解力”的测试光会写SQL是远远不够的。面试官真正想找的人不是那些能背出最多API的人而是面对一个具体的业务问题能快速判断出“数据的坑在哪里、应该用什么手段绕过这个坑、这个手段的代价是什么”的人。你在项目里踩过的每一个坑面试时都会成为你最扎实的底气。准备数据开发面试时不妨把心态放平——你不是在和面试官博弈你是在向他展示你过去几年积累下来的数据直觉这种直觉装不出来也背不出来。
返回列表