ARTICLE DETAIL

资讯详情

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

腾讯音乐数据工程笔试复盘:Hadoop、SQL与数仓建模核心考点

腾讯音乐数据工程笔试复盘:Hadoop、SQL与数仓建模核心考点 腾讯音乐的数据工程岗笔试我之前完整走了一遍2023年春招第一批当时拿到卷子到交卷的三小时里心理活动可以说是跌宕起伏。这套题不算偏但覆盖面非常“数据工程”和纯后端或纯算法的笔试风格差别挺大。如果你正打算投数据工程方向或者想检验一下自己在大数据基础、SQL、分布式理论这些模块上的底子这篇复盘值得你花几分钟看完。我先把当时笔试的总体感受放在前面这套题的核心不是考你背了多少框架API而是考你在数据链路上遇到实际问题时的处理逻辑包括你写的SQL会不会炸、你的分区策略合不合理、你在数据倾斜面前有没有感觉。整张卷子做下来知识点高度集中在Hadoop生态、Hive/Spark、SQL、Linux命令和数据结构基础这几个板块几乎没有那种“偏难怪”的题但每个板块都有让人纠结的坑。1. 笔试整体格局先看题型再谈备考1.1 题型分布与分值结构2023年腾讯音乐春招数据工程岗的第一批笔试线上限时完成整体题量控制在三小时左右题型大致分成四块选择题、SQL编程题、大数据组件问答题、以及一道综合设计题。选择题大概占了30%左右的分值后面三道SQL题属于实操题考察点非常明确直接看你写出来的查询能不能跑、能不能应对复杂场景。再往后是几道关于Hadoop、Spark、Hive原理的简答最后那道综合设计题围绕真实业务场景展开要求你基于一张用户听歌行为表做数据链路设计这部分是最考验数据工程思维的。从题目风格来看这套笔试并不要求你掌握冷门框架而是反复在考数据工程日常工作中最高频的那几个能力SQL写得好不好对分布式计算模型的底层理解够不够深碰到数据质量问题有没有排查思路。我当时做完之后最大的感受是腾讯音乐这边的数据工程岗位想要招的人不是在培训班里背了一堆名词的人而是真的能埋下头处理数据、能做链路优化的人。1.2 备考核心逻辑这套题在筛选什么样的候选人如果你准备去刷这套题首先要搞清楚数据工程岗和数据分析岗笔试的区别。数据分析岗会更偏业务理解和可视化思维但数据工程岗的考题里明显有更多计算引擎原理、存储格式、调度依赖设计这类底层内容。腾讯音乐的笔试尤其重视三个维度一是SQL的熟练度和严谨度二是对大数据生态各组件的原理性理解三是有没有真正处理过海量数据的工程意识。我认识的一些朋友在准备数据工程笔试时容易陷入一个误区疯狂刷力扣把算法题练得很溜但SQL反而写不溜Hive和Spark只停留在用过的层面一问到底层的Shuffle原理就答不清楚。这种状态在腾讯音乐的笔试里会吃很大的亏因为选择题里好几道都在考机制理解比如Spark作业提交之后Driver和Executor之间怎么协作、Hive SQL底层怎么转换成MapReduce作业这些不是靠“用过”就能答出来的需要真的啃过源码或者看过完整的执行流程解析。2. 核心考点逐一拆解选择题和简答题里的高频知识点2.1 大数据组件原理Hadoop与Hive的关系选择题部分有一道让我印象特别深的题问的是Hive执行引擎的发展路线以及Hive SQL最终通过什么方式在Hadoop集群上执行。这个知识点本身不难但选项里混杂了Tez、Spark、MR三种执行引擎的对比如果你只是熟悉其中一种很容易被干扰项带偏。我当时选答案的思路是这样的Hive最初设计的核心思想是把SQL语句翻译成MapReduce作业让不熟悉Java的开发者也能用SQL方式处理HDFS上的数据。但因为MapReduce的落盘机制导致执行速度偏慢后来才逐渐支持Tez和Spark作为执行引擎。这题的考点是Hive的本质是一个数据仓库工具它的底层仍然依赖Hadoop的存储和计算能力而执行引擎可以替换。所以选项里如果出现“Hive本身就是一个分布式计算框架”这种表述果断排除。这背后其实是数据工程里非常重要的一条认知你在生产环境使用哪个组件要清楚它在整个生态里的位置。Hive负责把SQL语义翻译成分布式任务存储和计算都托管给Hadoop因此它的性能瓶颈、优化手段都要围绕底层引擎来谈。如果你能理解这条链路那么面对“为什么Hive查询慢”“哪些参数能提升执行效率”这类问题就能举一反三了。2.2 Spark Core的执行机制与调优思路还有一道题几乎可以称得上整套选择题的灵魂之题它考察Spark中宽依赖和窄依赖的区别并让你判断哪些算子会产生Shuffle。很多刷过面试题的同学应该都能脱口而出groupByKey、reduceByKey、join这类操作会触发Shuffle而map、filter、union这些操作不会。但这次笔试的选项设计得比较狡猾它没有直接让你判断算子而是给出一段关于Stage划分的描述让你判断哪一个表述是错误的。这里有一个核心原理需要理解Spark会根据RDD之间的依赖关系把作业拆分成多个StageShuffle操作是Stage之间的边界。窄依赖是指父RDD的每个分区最多被子RDD的一个分区使用这样在同一个Stage内可以直接做流水线式计算不需要跨节点传输数据宽依赖则是指父RDD的一个分区被子RDD的多个分区使用这必然会产生数据重组也就是Shuffle。这道题里有一个选项说“宽依赖和窄依赖的划分只影响性能不影响作业的正确性”这显然是错的。理解窄依赖还有一种特殊情况就是当分区数量发生变化时即使依赖关系上是窄依赖也可能引入一定程度的数据移动。我在实际调优Spark作业时也会刻意把多个宽依赖尽量合并减少Stage数量这样能有效降低调度和网络传输开销。备考这个模块建议把Spark执行流程完整走一遍从提交作业、构建DAG到划分Stage、生成Task再到Executor执行任务每一步都要能说清楚。2.3 数据仓库与数据建模理论简答题部分有一道涉及维度建模的问题在设计用户行为分析数仓时你会选择星型模型还是雪花模型这道题和真实业务贴得很紧因为腾讯音乐这种内容平台天然存在用户、歌曲、歌手、专辑、听歌行为等多维度数据。相比之下星型模型更适合快速查询和直接理解雪花模型则把维度表进一步规范化拆分能减少数据冗余但会增加Join的复杂度。笔试题给了一个场景一张用户听歌事实表一张歌曲维度表和一张用户维度表要求判断这种设计属于什么模型。答案显然是星型模型因为歌曲表和用户表都是直接与事实表关联没有多级维度表依赖。这道题背后考察的其实是你在做数仓建模时有没有真正权衡过查询性能、维护成本和业务易用性。在真实项目里星型模型往往是首选只有在维度属性特别复杂或者下游使用频率不高时才会考虑雪花模型这是数据工程岗位日常工作中经常需要做的取舍。3. SQL实战三道题串起数据工程的核心能力3.1 窗口函数应用如何计算用户连续听歌天数SQL编程题的第一道要求从一张听歌记录表中计算每个用户的连续听歌天数。这张表有三个字段user_id、song_id、listen_date一个用户一天内可能听很多首歌但只计算他当天是否有听歌行为最终要输出每个用户最长的连续听歌天数。我当时看到这个题的第一反应是这题的核心是把同一用户的听歌日期去重然后通过日期减去行号的方式构造连续分组的标识。具体做法是先把listen_date按用户去重然后用ROW_NUMBER()按用户分组、按日期排序给每一行生成一个序号再用listen_date减去这个序号得到一个新的日期字段。在同一个用户内如果日期是连续的那么做差得到的日期就是相同的按照这个差值分组就能数出每一段连续听歌的天数了。WITH user_listen_dedup AS ( SELECT DISTINCT user_id, listen_date FROM user_listen_log ), user_listen_seq AS ( SELECT user_id, listen_date, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY listen_date) AS rn FROM user_listen_dedup ), user_listen_group AS ( SELECT user_id, listen_date, DATE_SUB(listen_date, rn) AS grp_date FROM user_listen_seq ) SELECT user_id, DATEDIFF(MAX(listen_date), MIN(listen_date)) 1 AS max_consecutive_days FROM user_listen_group GROUP BY user_id, grp_date HAVING DATEDIFF(MAX(listen_date), MIN(listen_date)) 1 1这道题坑点在于去重之前直接做ROW_NUMBER()会导致同一天听多首歌时产生多个序号连续分组的计算结果会出错。我当时是先做了DISTINCT再用窗口函数最后通过DATE_SUB(listen_date, rn)得到分组标识。如果你对Hive和Spark SQL比较熟会发现这套逻辑在这两个引擎里都能正常跑区别只在于函数命名略有不同。这里补充一句我踩过的坑连续性问题在早期数仓面试里常以“连续登录天数”出现但现在越来越多地包装成业务语言比如“连续收听天数”“连续签到天数”核心解法都是同一个先分组排序生成序号再做差聚合。把这道题的思路吃透比死记硬背几个SQL代码段有用得多。3.2 留存率计算一类表和二类表之间的关联关系第二道SQL题给了一个比较经典的场景已知用户注册表user_register和用户活跃表user_active要求计算每个注册日期后第7天的用户留存率。留存率的口径是第7天活跃用户数 / 注册用户数。这道题表面上是考SQL实际上是在考你能否处理好“先定义口径再写查询”的问题。我的解法是先通过LEFT JOIN把注册表作为主表关联活跃表关联条件是注册用户等于活跃用户且活跃日期等于注册日期加7天。此时如果活跃表没有匹配记录活跃日期字段就是空值。聚合计算时分母是注册用户数分子是活跃日期不为空的用户数。最后按注册日期分组用COUNT统计分母、SUM加总分子相除得到留存率。SELECT r.register_date, COUNT(DISTINCT r.user_id) AS register_users, COUNT(DISTINCT CASE WHEN a.active_date IS NOT NULL THEN r.user_id END) AS retained_users, ROUND( COUNT(DISTINCT CASE WHEN a.active_date IS NOT NULL THEN r.user_id END) / COUNT(DISTINCT r.user_id), 4 ) AS retention_rate FROM user_register r LEFT JOIN user_active a ON r.user_id a.user_id AND a.active_date DATE_ADD(r.register_date, 7) GROUP BY r.register_date这道题想拿满分还要注意一个细节去重逻辑。一个用户在某一天可能有多次活跃记录如果直接用JOIN而不做去重那么分子统计时用COUNT(DISTINCT ...)还能兜底但如果你换成SUM(CASE WHEN ...)就会出问题。我在笔试时习惯在所有可能产生多对一关联的查询里都加上COUNT(DISTINCT)避免活跃表里同一用户重复记录导致计算失真。这道题其实也暗示了数据工程岗位的特征你写一个大范围的任务之前必须先把数据粒度搞清楚不要拿到表就开始JIOIN。3.3 播放量Top N分组排序里的细节陷阱最后一道SQL题是典型的Top N问题在歌曲播放记录表song_play_log中计算每首歌按天的播放量排行并输出每个歌曲播放量排名前三的日期。表结构包含song_id、play_date、play_count三个字段每天每个歌曲可能有多次播放记录需要先按歌曲和日期聚合再排序取前三。这个场景在榜单类业务里太常见了腾讯音乐这种内容型产品几乎天天会算各类榜单。我的思路分两层第一层用GROUP BY song_id, play_date汇总每天的播放量第二层用ROW_NUMBER()按歌曲分组、按播放量降序排序最后取排名小于等于3的记录。WITH daily_play AS ( SELECT song_id, play_date, SUM(play_count) AS total_play FROM song_play_log GROUP BY song_id, play_date ), ranked_play AS ( SELECT song_id, play_date, total_play, ROW_NUMBER() OVER (PARTITION BY song_id ORDER BY total_play DESC) AS rk FROM daily_play ) SELECT song_id, play_date, total_play FROM ranked_play WHERE rk 3这题的核心考点有两个一是你是否知道先聚合再排名二是选窗口函数时用ROW_NUMBER()还是DENSE_RANK()。如果题目要求“排名前三”但同日期的播放量可能有并列情况这时用ROW_NUMBER()会随机分配一个名次而DENSE_RANK()会保留并列名次。我当时在笔试环境里直接用了ROW_NUMBER()因为题目没有明确要求并列处理后面复盘时想到如果实际业务榜单用这个逻辑确实需要和产品对齐口径。这类思考在面试官眼里非常加分因为反映了你有工程经验。4. 综合设计题从一张表到一个完整的数据链路4.1 需求场景与目标拆解这套笔试卷里最重量级的一道题是综合设计题它给了一张模拟的“用户歌曲播放日志表”字段包含user_id、song_id、play_time、duration、listen_date、province等要求你基于这张表设计一个每日用户播放行为分析的数据链路输出维度包括每日活跃用户数、每日播放量Top10歌曲、分省份播放量分布。除了必须给出SQL或者伪代码之外还需要说明你的存储分区方案、调度策略和异常处理思路。这类题目在数据工程岗的笔试中出现频率极高因为它最能反映出你能否从零到一搭建一条数据管线。我当时的解法是先做数据分层ODS层原样接入日志DWD层做清洗和规范化DWS层做汇总ADS层输出报表。这道题没有标准答案但你的思路必须完整闭环从数据接入到最终应用每个环节都要有明确的设计说明。4.2 建模与分区策略如何规划表结构设计的第一步是决定表结构。ODS层我选择保留完整的原始日志数据按照listen_date进行二级分区。为什么用日期分区因为用户播放日志是按天持续产生的每天一个分区查询时可以直接裁剪分区节省大量扫描成本。省份字段可以作为后续多维分析的二级维度但不建议在ODS层就过度拆分保持原样进入仓库即可。DWD层做清洗时我会过滤掉duration为0的记录这类记录大概率是播放异常比如用户点击了播放立即退出或者前后端埋点上报有误。这个步骤非常关键因为如果把脏数据带入汇总层最终的播放量和活跃用户数都会偏大。我在实际项目里见过因为没做过滤导致的线上报表数据大幅跳变最后排查半天才发现是异常播放数据混入。DWS层按业务维度做汇总可以把每日活跃用户数、歌曲维度的总播放时长、歌曲维度的播放次数都在这层完成计算。ADS层则服务具体报表比如Top10歌曲榜单、省份播放量分布。这种分层设计的最大好处是每一层只负责一类职责下游报表需要新指标时尽量从DWS层扩展而不需要重新扫描ODS原始数据在数据量大时能显著节省计算资源。4.3 调度与重跑机制数据链路稳定性的关键调度策略我选择了按天定时触发任务约定了凌晨1点处理昨日全量数据这个时间段T1报表的用户访问压力很小同时凌晨的集群负载相对低。这里还设置了一个依赖检查只有当天ODS分区写入完成且数据量校验通过才触发DWD层任务执行否则任务挂起重试。这个设计能有效避免“上游数据缺了下游还在傻跑”的脏数据问题。关于数据异常的处理我写了三条规则duration为0的记录过滤丢弃单日播放次数超过阈值比如单用户超过500次的标记为异常并单独存储最终表数据量比前一天波动超过50%时发送告警。这三点是数据工程里常见的质量监控手段我在实际项目里都有实践过尤其是数据量波动告警能在问题扩散到报表端之前就提醒我们介入排查。这道综合设计题考察的其实是数据工程最核心的能力闭环从数据接入、清洗、加工到最终产出每一步都需要考虑合理性、效率和稳定性。我见过很多候选人在写这类题时只给了SQL没有分层和调度设计这样就是把自己的位置限定在“SQL Boy”层面距离数据工程师的定位还很远。4. 细节坑点复盘笔试时容易失分的地方4.1 SQL常见陷阱函数的兼容性我在笔试过程中发现腾讯音乐的在线编程系统支持Hive SQL和Spark SQL但不同引擎对一些函数的支持有细微差别比如DATE_SUB和DATE_ADD在Hive里能直接用在部分Spark SQL版本里也没问题但如果你用INTERVAL关键字某些老版本可能不兼容。我当时的做法是尽量使用各引擎都通用的函数写法避免在语法层面浪费时间。另外有个坑是COUNT和SUM的使用在统计用户数时要用COUNT(DISTINCT user_id)避免重复但在统计播放次数时直接SUM(play_count)即可两者语义完全不一样。有同学在写留存率时分子用了COUNT(active_date)如果LEFT JOIN时有重复记录结果会比真实值高很多。4.2 大数据组件选择题细节决定成败选择题里关于HDFS的题目也有几道考的是读写流程和副本机制。比如写入一个文件时客户端先把数据切分成块然后按顺序写入第一个DataNode再由第一个DataNode复制到第二个和第三个DataNode默认副本数为3。问题会问“如果第二个DataNode写入失败会怎样”此时第一个DataNode已经收到部分数据需要重新选择节点继续写同时保持副本数一致。这类题如果只看过博客没有亲手搭建过集群可能会靠猜。但如果你平时习惯了查看HDFS Web UI看文件块在集群上的分布对这些概念会有很直观的认识。我在准备这类考点时推荐大家在自己电脑上用Docker搭一个三节点的Hadoop集群亲手操作文件上传和块分布查看记忆会比背诵强很多。4.3 编程语言基础Python与Shell的实用场景笔试中还出现了一道Python相关的题内容不算复杂要求实现一个函数从一段文本中提取所有手机号。这种题在工作中出现的频率极高尤其是日志解析和数仓清洗阶段。我用正则表达式解决这也是数据工程岗位最常用的Python技能之一。import re def extract_phone_numbers(text): pattern r1[3-9]\d{9} return re.findall(pattern, text)为什么用正则而不是字符串切片因为手机号可能出现在日志文本的任意位置前后可能有各种字符正则更灵活。还有一个容易忽略的点如果日志里可能包含多个手机号需要用findall而非matchmatch只会匹配文本开头的位置很容易漏掉目标数据。Shell相关倒是没有出复杂的脚本编写题但有一道关于crontab的题目问的是如何配置一个每天凌晨2点执行的任务。如果你对Linux的基本定时任务不熟悉这道题会失分。答案很直接0 2 * * * /path/to/script.sh。但要注意分钟位是0而不是*否则任务会在凌晨2点的每一分钟都执行一次。这种题目看着简单但是对生产环境的细节考察非常精准一个配置失误真的会引发调度重复执行。5. 常见问题与排查技巧实录5.1 数据倾斜问题最容易暴露工程经验的话题笔试选择题里没有直接考数据倾斜但综合设计题的描述中我特意提到了这个排查点因为这是数据工程岗面试里的高频题。真实场景中数据倾斜通常表现为某个Reduce任务处理的数据量远大于其他任务导致整个作业卡在最后几个Task上迟迟无法结束。腾讯音乐这种体量的业务倾斜往往发生在热门歌曲、头部用户上比如一个顶流歌手的歌曲播放量是普通歌曲的上百倍如果按歌曲聚合那首歌曲所在的Reduce任务就会成为瓶颈。处理方法通常是加随机前缀键把倾斜的key打散到多个任务或者布隆过滤器提前过滤异常值。这些方案在笔试里不需要展开到代码级别但至少要让面试官感觉到你对这个问题有实际认知。我做笔试复盘时经常提醒自己数据工程不是只会写SQL就好还要知道写出来的SQL在集群上怎么跑、跑得慢怎么调。这个意识是通过EXPLAIN查看执行计划慢慢培养的。5.2 笔试时间分配先把能拿的分拿到这次笔试的时间是三小时题量其实不算大但每道题都值得认真对待。我的时间分配经验是选择题控制在30-40分钟内完成会做的先做不确定的标记跳过不要在一道机制题上死磕。SQL题每道15-20分钟尽量把SQL写到思路清晰、逻辑正确如果有余力在注释里写清楚你的计算口径选择。综合设计题留出30-40分钟因为这个题占分值最高而且主观性较强写得越完整越能体现工程素养。我在笔试时遇到一道选择题关于Kafka的问的是消费者组和分区的关系。这里有一个核心知识点同一个消费者组内每个分区只能被一个消费者实例消费一个消费者可以消费多个分区如果消费者数量大于分区数就会有空闲的消费者无法消费。这道题如果理解不透很容易选错。我当时在纸上画了一个分区和消费者的对应关系图很快就选出了正确答案。这里的经验是不要害羞在草稿纸上写写画画数据结构和分布式系统的问题画图比裸想可靠得多。5.3 笔试后的下一步从笔试看面试准备方向笔试结束之后建议花半小时做一个完整的复盘把每道题考察的知识点写下来对照自己的薄弱项补充学习。我从这次腾讯音乐的笔试题里整理出来的核心考点清单是Hive SQL和Spark SQL的常用函数窗口函数、日期函数、聚合函数的组合使用Hadoop生态各组件的原理性知识尤其是HDFS读写机制和Shuffle过程数仓分层建模思路第一层ODS到DWD的处理逻辑DWS到ADS的汇总方向以及事实表和维度表的组织方式Spark作业执行流程DAG划分、Stage边界、宽窄依赖对性能的影响数据质量监控和异常处理的基本方案比如数据量波动监控、脏数据策略、任务重跑机制这些方向不仅仅是备考清单它们本身就是数据工程日常工作的核心内容。笔试只是把高墙的一面展示给你真正进去之后你会发现这些都是基本功。6. 给后来人的一些实在建议6.1 准备笔试的正确姿势如果你还在准备阶段我建议你用“项目驱动”的方式代替“刷题驱动”。什么意思呢就是找一份真实的脱敏数据自己搭一套简单的数仓链路原始日志落地到HDFS用Hive做清洗和汇总再用Sqoop或DataX同步到关系型数据库最后用可视化工具展示。这个过程中你会自然地碰到Hive语法问题、数据倾斜问题、分区策略问题、调度依赖问题每一个问题都能加深你对笔试考点的理解。我在准备过程中最大的体会是笔试中很多题看起来是“知识题”实际是“经验题”。比如数据倾斜的解决方案如果只是背答案可能知道加随机前缀但如果你真的亲手处理过一个跑了两小时还失败的Spark作业你会对倾斜的定位方式、加盐力度、二次聚合的细节有更深的记忆笔试时你甚至能写出伪代码而不是只写一句“通过加盐解决”。6.2 考试中的自我保护策略笔试现场要做到“稳住心态能调则调”。在线笔试的环境有时候可能会因为网络原因出现延迟SQL编译器也可能因为特殊语法报错。我当时的做法是先在本地用MySQL练熟了标准SQL再切到Hive语法搞清楚哪些函数不兼容这样笔试时即使编译器报错也能迅速判断是语法问题还是逻辑问题。每道题写完代码后我都会在脑子里跑一遍测试用例特别是边界值比如空表、重复数据、极端日期。SQL不出bug的概率很低但能把边界情况考虑清楚的考生很少做完这些检查你的答案就已经比大多数人完整了。6.3 从笔试到Offer的最后一公里笔试通过之后面试大概率还会围绕笔试内容和简历上的项目展开。你可以在笔试结束后的第一时间把每道题重新做一遍做成一个知识点笔记面试时就能直接把这些题目作为“我的实操复盘”来聊。面试官最想看到的不是完美的答案而是候选人是否具备复盘和总结的习惯。我记得笔试复盘笔记里我给自己的综合设计题补了一张数据流向图ODS层原始日志DWD层清洗明细DWS层汇总指标ADS层报表应用每层标注了表的粒度、分区字段和刷新频率。这些内容后来在面试中聊到数仓设计时给了我很大的帮助因为我能够把一个抽象概念落实到具体的执行计划里面试官一眼就能看出我不只是听过这个概念而是真的用过。如果你接下来要参加类似的笔试我的建议是不要只把目标放在“过笔试”上而是把笔试当成一次免费的技能诊断。数据工程岗位的技术栈广且杂笔试能帮你看到自己的盲区在哪里。无论结果如何把这份整理出来的考点清单过一遍不断补全自己在数据链路上的知识图谱你会发现自己越来越能胜任这个岗位。说到底数据工程是一门实践的学问。笔试只是敲门砖真正让自己值钱的是你在日复一日的抽数、清洗、建模、调优里积累出来的直觉和判断力。
返回列表