浩鲸科技数据开发笔试C卷解析:从Java基础到大数据组件
笔试这关说到底考的不只是知识点更是你对数据开发这门工作的理解方式。这两年经常有人问我“浩鲸科技这种公司的数据开发笔试到底考什么”尤其是2020届那套C卷被传得挺神的说难吧也没到竞赛级别说简单吧裸考的人基本都挂了。我后来把题目和我自己带新人时的面试题库对照了一下发现这类笔试其实有一套非常固定的出题逻辑。今天就把这套逻辑拆开结合C卷的题型设置聊聊数据开发笔试到底在筛选什么样的人以及你该怎么准备才不踩坑。1. 数据开发笔试到底在考什么1.1 从笔试结构看岗位定位先看大框架。浩鲸科技的数据开发岗核心业务围绕电信行业的数据平台、数据仓库、经营分析系统展开所以笔试不会像互联网大厂那样纯考算法而是更偏工程落地和技术深度并重。C卷给我的整体感觉是基础题占四成SQL和数据处理题占三成大数据组件原理占两成剩下的一成是开放性的场景设计题。这种结构本身就说明了一个问题这家公司要的不是只会写SQL的“取数工具人”也不是只会背八股文的“理论王者”而是能把数据链路跑通、出了问题能排查、业务方提需求能听懂的人。所以考试范围看着很杂其实核心就两条线一条是计算机基础功一条是数据生态的技术栈。我见过不少同学备考时拼命刷LeetCode结果到了笔试现场发现算法题只有一两道反而是Java集合类的多选题和SQL窗口函数的编写题占了大量篇幅瞬间就慌了。这就是典型的没搞清楚岗位定位用错复习方向。1.2 出题逻辑为什么笔试会这么设计理解出题逻辑比背答案重要得多。C卷的题目顺序是有讲究的前面是基础知识选择题中间是SQL编写后面是大数据原理简答最后是综合设计。这个顺序其实模拟了一个数据开发工程师从“看懂代码”到“写数”再到“搭架构”的能力进阶路径。还有一个容易被忽略的细节这套卷子的Java题目偏向集合框架和并发而不是SSM框架或者SpringBoot。原因很直接数据开发日常大量工作是写MapReduce、Spark任务、Flink作业这些框架底层全是Java集合和并发编程。你如果连HashMap在并发环境下为什么会丢数据都说不清楚那写出来的Spark算子是经不起推敲的。另外SQL题占比这么高是因为数据开发的核心产出物就是SQL。不管是数仓ETL、报表开发、数据接口最终都会落到一段段SQL上。C卷里的SQL题不是简单的单表查询而是多表关联、窗口函数、去重取最新这类实战场景这其实就是电信行业里最常见的“用户套餐变更记录取最新状态”“话单数据按天汇总”的业务抽象。2. 计算机基础与Java核心考点拆解2.1 Java基础集合框架和并发是绝对重点C卷Java部分我印象最深的是几道关于HashMap的题目。比如问HashMap在JDK1.7和1.8之间有什么区别扩容时是头插法还是尾插法为什么1.7在并发扩容时会形成环形链表。这种题看起来是考源码其实是在考你有没有真正跑过并发任务。我记得自己当年复习的时候把这些源码看了三遍才彻底想明白JDK1.7的扩容是transfer方法里把旧数组的元素重新hash到新数组用的是头插法并发下两个线程同时扩容时A线程刚把节点B移到新位置B线程又把链表顺序翻转最后就形成了环。到了JDK1.8改成尾插法加上红黑树优化环的问题就解决了。笔试如果考到这个点你不能只答“1.8优化了”要把为什么优化、怎么优化的说透。再就是ConcurrentHashMap这题几乎是必考的。C卷里问的是它怎么保证线程安全分段锁和CASsynchronized的区别是什么。这个知识点在数据开发里的映射就是你在写Spark的mapPartitions或者Flink的keyBy之后的聚合操作时如果有外部共享变量就涉及到并发安全的问题。笔试考ConcurrentHashMap本质上是在考你有没有并发编程的意识和基本功。还有一块容易翻车的是JVM内存模型特别是堆内存的分代和GC机制。C卷虽然没有出特别深的JVM调优题但有一道选择题问的是“哪些情况会触发Full GC”这其实对应的是你写的数据任务在跑批量作业时如果内存设置不合理频繁Full GC导致作业变慢的场景。我建议复习这块的时候别看那种三个小时的源码解析视频就看清楚Eden区和Survivor区的对象流转过程、Minor GC和Full GC的触发条件就够了。2.2 数据结构与算法题量不大但区分度高C卷的算法题不多我记得好像是两个编程题一个是数组相关的简单题一个是带一点动态规划思想的题。难度比LeetCode中等题要低但有个坑是环境是白板编码没法用IDE调试平时依赖编译器提醒的同学会很不适应。第一个编程题大概是找数组里出现次数超过一半的数字也就是“多数元素”问题。这题有几种解法排序取中间值、HashMap计数、摩尔投票。笔试现场最好写的是HashMap计数简洁不容易出错但如果你能写出摩尔投票会是一个加分项。我当时是这么写的public int majorityElement(int[] nums) { int count 0; int candidate 0; for (int num : nums) { if (count 0) { candidate num; } count (num candidate) ? 1 : -1; } return candidate; }第二题我记得是爬楼梯或者类似的斐波那契变体。这题考的不是你会不会递归而是你会不会优化递归。如果你写了朴素的递归面试官会觉得你只会背书如果你能写出迭代版本的动态规划甚至能提到用滚动数组把空间复杂度降到O(1)那才是他们想看到的水平。说实话算法这块在数据开发笔试里的比重没有想象中那么大但它是区分“会写业务代码”和“有扎实计算机功底”的关键。如果你时间有限优先把数组、链表、栈、队列、哈希表这几类基础数据结构搞定动态规划掌握最常见的几种模型就够了。3. SQL与Hive/SQL实战要点3.1 SQL基础题型窗口函数是拿分关键C卷的SQL部分如果让我用一句话总结那就是“没有窗口函数你根本答不完”。我记得有一道题是“统计每个部门薪资排名前3的员工”这种题用group by硬写会非常痛苦但用row_number()或者rank()就很简单。窗口函数在数据开发笔试中的地位就像炒菜时的盐几乎道道题都用得上。特别是row_number()、rank()、dense_rank()三兄弟的区别几乎是必考。C卷里有一道选择题专门考这三者的使用场景还涉及到了partition by和order by的执行顺序。这块如果搞不清楚建议画个简单的表格自己推演一遍别光背结论。要注意的是row_number()在遇到相同值时会随机排rank()会留下空位dense_rank()不会这个差异在报表去重场景下特别容易踩坑。再就是经典的“取分组最新一条记录”的题目。C卷里给了一个用户登录日志表字段是user_id、login_time、login_ip要求取每个用户最新的登录记录。这道题标准的写法是SELECT user_id, login_time, login_ip FROM ( SELECT user_id, login_time, login_ip, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_time DESC) AS rn FROM user_login_log ) t WHERE t.rn 1;这种题目在笔试里考的是基本功但在实际工作中同样是高频场景。我见过太多人一上来就group by user_id然后max(login_time)结果登录IP对不上。这个时候你就能理解为什么笔试反复考窗口函数了——它就是数据开发吃饭的家伙。SQL题里还有一类是连续问题比如“统计连续3天登录的用户”。C卷的最后一道SQL大题就是这个。这题的标准解法是先用lag或lead函数算出日期偏移再通过日期减去偏移量得到分组标志。我写一下核心思路WITH t1 AS ( 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 WHERE login_date IS NOT NULL ) SELECT user_id, COUNT(DISTINCT login_date) AS cnt FROM t1 GROUP BY user_id, grp HAVING cnt 3;这里有个技巧先用窗口函数按用户分组对日期排序然后用日期减掉排名序号如果日期是连续的差值会相同。这个概念不复杂但没见过的话现场很难临场想出来。3.2 Hive进阶数据倾斜和UDF是必问题C卷的Hive部分有一道简答题问的是“Hive常见的数据倾斜情况以及解决方法”这道题基本上是数据开发面试的“保留曲目”。数据倾斜这个话题我建议准备的时候不要只背解决方案要搞清楚倾斜到底是怎么产生的。简单说当某个key的值特别多比如用户表里“未知”这个取值占了80%join的时候这个key就变成了一根独木桥所有人都卡在这。C卷给了一个典型的group by倾斜场景让考生说明解决方案。标准回答分几步一是开启map端聚合也就是set hive.map.aggrtrue先把部分聚合放在map端减少shuffle数据量二是如果倾斜key是空值可以考虑加随机前缀打散三是用两个阶段聚合先加随机数做局部聚合再去掉随机数做全局聚合。我建议你在卷子上把第二种方式的SQL写出来这样比光写文字更有说服力。-- 先给倾斜key加随机前缀 SELECT flag, COUNT(1) AS cnt FROM ( SELECT CASE WHEN user_id unknown THEN CONCAT(unknown_, FLOOR(RAND() * 10)) ELSE user_id END AS flag FROM user_log ) t GROUP BY flag;如果你能把“一阶段加盐、二阶段去盐”的SQL写出来这道题的分数基本就稳了。还有一道题是问“Hive和关系型数据库有什么区别”。这道题看起来简单但很多人答不到点子上。关键差异不在于语法而在于执行模型和设计理念Hive是批量处理延迟高吞吐大适合离线分析MySQL是实时事务处理适合在线业务。Hive的元数据存储在MySQL里但数据存在HDFS上这个架构特点也值得提一下。我建议复习Hive的时候重点关注这几个点内部表和外部表的区别、分区和分桶的作用、order by和sort by的区别、UDF编写流程。这些都是笔试和面试高频中的高频比追新特性划算得多。4. 大数据组件原理与场景题4.1 Hadoop与MapReduce不只要会调API很多人在准备大数据笔试时有个误区觉得MapReduce已经不流行了就不看了。实际上C卷里明确考了MapReduce的shuffle过程还考了Map端和Reduce端并行度的设置。原因很简单虽然现在多数任务是Spark或者Flink来跑但这些框架底层的设计思想大量借鉴了MapReduce不懂shuffle就很难真正理解Spark的shuffle。C卷里那题关于shuffle我建议这样答map端把结果写入环形缓冲区缓冲区默认100MB达到80%阈值时溢写本地磁盘溢写过程中会进行分区、排序、combiner合并然后reduce端拉取属于自己的分区数据在内存中归并排序最后逐组调用reduce函数。整个过程可以概括为“分区、排序、溢写、归并”八个字这八个字理解了MapReduce题基本不会失分。曾经有一个同学问我为什么MapReduce的环形缓冲区要设计成80%才溢写不等到满了再写这个问题的答案其实涉及性能考量如果等到100%才溢写那么整个map任务会阻塞等待磁盘写完成而80%的时候开始溢写还有20%的空间可以继续写入新数据这样map任务和溢写线程可以并行工作。这种设计思想不只在MapReduce里在Kafka、Netty里都能看到类似的“低水位线”思路。如果你在笔试中能把这类底层设计逻辑说清楚分数会明显不一样。还有一个易错点是HDFS的读写流程。C卷考了一道判断题说“客户端写入数据时数据先写入DataNode再写入NameNode”这明显是错的。HDFS写数据时客户端先跟NameNode通信拿元数据信息然后跟DataNode建立管道流式写入。NameNode只负责元数据管理不经过数据本身。很多同学复习时容易记混建议画一张简化的时序图帮助记忆。4.2 Spark和Kafka实时场景绕不开的话题C卷对Spark的考察不算深主要是RDD和DataFrame的区别、宽窄依赖的判断、以及Spark任务怎么优化。这里有个考点是“reduceByKey和groupByKey有什么区别”非常基础但非常经典。你可以从两个角度回答一是reduceByKey会在map端先做一次combiner聚合然后才shuffle而groupByKey是把所有原始数据直接shuffle到下游不做预聚合二是如果数据量很大groupByKey会导致shuffle数据量巨大性能远差于reduceByKey。我把两道题的对比整理成了一张表复习时可以参考对比项reduceByKeygroupByKeymap端聚合有combiner无shuffle数据量小大适用场景聚合、求和、计数需要访问全部分组数据性能表现高低关于宽窄依赖C卷的选择题问的是“coalesce操作对应窄依赖还是宽依赖”答案是窄依赖。因为coalesce只是合并分区不会发生shuffle父RDD的每个分区最多被一个子分区使用。但如果不传shuffle参数且分区数变多那就是错的用法coalesce只能减少分区不能增加分区。这些细节知识点笔试里考的就是判断你有没有真正理解。Kafka在C卷里也出现了不过考的是消费模型和offset管理。有一道题问“Kafka消费者宕机后重启怎么续传之前没消费完的数据”这对应的就是offset提交机制。Kafka通过消费者组协调消费者重启后会根据上次提交的offset继续消费但如果你用了自动提交并且没处理完就提交了就会丢数据。反过来如果你手动提交但没等处理完就提交也会丢。这个坑在实际生产环境里非常常见笔试考的是你有没有踩过。我建议你在复习Kafka时重点关注分区和副本机制、生产者和消费者的ack机制、offset提交方式、消费者组rebalance的触发条件。这几个点搞明白不只是应付笔试后面做实时数仓项目也够用了。4.3 调度与数据治理容易被忽略的送分题C卷中还有一小部分是关于任务调度的问的是“数仓任务调度失败后应该怎么处理”。这种题看似没有标准答案其实考的是你对数据任务生产环境的理解。答题思路可以是先看失败原因是资源不足还是数据问题再决定是重跑依赖的上游任务还是修改SQL最后要建立任务失败告警和补偿机制。另外还有一道关于数据质量的题问“如何保证数据准确性”。这道题我印象很深因为很多人答不到点上只会说“多测试几遍”。实际上数据质量在数据开发里是一整套体系至少包括完整性、准确性、一致性、及时性几个维度。笔试中你不需要面面俱到但至少要提到数据校验和监控告警两个点比如在数仓的ODS层做行数校验、主键重复校验在DWS层做指标波动告警。这些偏数据治理的内容看着不起眼但在实际工作里反而是最花时间的部分。C卷把它放进去也说明了浩鲸这类做B端项目的公司对数据规范性的重视程度比纯互联网业务要高很多。5. 数据开发场景题与项目复盘思路5.1 场景题怎么答才能拿高分C卷最后一道是开放题大概是“某电信运营商需要搭建一个用户流失预警数仓你如何设计主题和指标”。这种题没有标准答案但特别能拉开差距。我观察下来答得好的同学普遍会遵循一个套路先明确业务目标再确定分析维度然后设计数仓分层和指标体系最后讲技术选型和调度方案。我当时提供了一个思路框架你可以参考首先确定核心指标是“用户流失率”和“预警用户数”维度上拆出用户属性、套餐类型、消费行为、客服交互记录数仓分层上ODS层存源系统原始数据DWD层做清洗去重DWS层按天聚合出用户维度的特征宽表ADS层输出预警名单。最后在调度上每天凌晨跑批生成当天预警名单推送给运营人员。这道题其实不是考你设计得多完美而是考你有没有一套完整的数据处理思维。从原始数据到最终应用中间的每一层是怎么流转的你要能说清楚。我建议平时准备项目描述时也按照这个逻辑来组织不要一上来就讲你用了什么技术栈先讲业务背景和数据流。5.2 从笔试看项目经验怎么把“做过”变成“会做”很多同学简历上写了“参与搭建了XX数仓”但笔试做场景题时还是写不出东西原因在于简历项目的细节没有沉淀成方法论。我建议你在准备时把自己做过的项目重新过一遍重点提炼三个方面一是数据量级每天处理多少条数据、二是链路复杂度涉及多少个数据源、多少层加工、三是性能优化效果任务从多久优化到多久。举个例子如果你在项目里写过一条从业务库同步数据到Hive的流程你应该能把Sqoop或者DataX的同步原理讲清楚而不是只会填JDBC连接串。如果你用SparkSQL做过报表开发你应该能分析出哪条SQL跑得慢、为什么慢、用什么手段优化了。只有把这些细节消化成自己的理解笔试里的场景题和项目问答题才能答出真实感。C卷里还有一道问“你在过去项目中遇到过最大的数据问题是什么是怎么解决的”这道题其实比技术题更关键。我见过很多人的回答是“遇到过数据倾斜”就结束了具体怎么发现、怎么定位、怎么解决一个细节都没有。这种答案在笔试中会被认为是没有真正做过项目的。建议在准备时写一个完整案例问题现象是报错还是运行缓慢排查思路是从日志还是从监控发现最终方案是什么优化后效果如何。这部分内容做不了假也能真正区分一个人的实战水平。5.3 数据开发笔试的复习节奏建议说完了题型和考点如果你正准备投数据开发岗位我给你一套复习节奏做参考。如果你有1个月以上的准备时间前两周主攻Java基础和SQL窗口函数每天至少手写两到三道Hive SQL把行转列、列转行、累计计算、分组TopN这些经典题型练熟第三周系统看一遍Hadoop、Hive、Spark的架构原理结合网上常见的面试题自己讲一遍最后一周找几套数据开发的真题模拟笔试环境严格卡时间。如果你只有一周时间那就集中火力攻SQL和Hive数据倾斜这两个考点。别贪多把最核心的拿下性价比最高。另外我还想特别提醒一点笔试答题时字迹要清楚思路要写出来。尤其是简答题和场景题不能只写结论要把分析过程写出来。阅卷的人想看到的是你的推理链条而不是一个跟标准答案差不多的结论。很多时候答案不完美但思路清晰的人比分点列得很死板的“背书机器”分数更高。数据开发这条路的笔试说到底是把课本知识和工程实践衔接起来的一道门槛。一个懂得从数据中发现规律、从问题中定位原因、从架构上思考方案的工程师才是这类岗位真正想找的人。备考的过程看起来很枯燥但这些基本功扎实了后面无论做数仓还是实时计算都会走得更稳。