
触宝科技2017秋季校招笔试复盘后端大数据方向第三批全解析2017年秋季校招那会儿触宝科技的笔试通知下来的时候我正在刷一堆大数据面试题琢磨着后端和大数据这两个方向到底怎么在一套卷子里结合。那时候移动互联网的校招竞争已经相当激烈触宝这家做输入法和海外通讯产品的公司后端大数据岗位笔试的考察范围特别值得总结——它几乎囊括了当时互联网公司对于“后端大数据”方向候选人的全部核心期待数据结构与算法、JVM与并发、大数据生态组件原理、系统设计场景以及海量数据处理的实战思路。这篇文章我结合当时第三批笔试的题目内容和后续面试聊到的反馈把整套笔试的考察逻辑、核心细节和判断标准拆开讲讲。如果你正准备这类既要写算法又要聊大数据的笔试无论是不是当年的批次这套题型的准备思路到今天依然有很强的参考价值。1. 完整考察框架这套笔试卷子到底想测什么1.1 从岗位定位反推考察模块先看岗位本身。后端大数据岗位在触宝内部负责的是用户行为数据采集、存储、清洗、分析和挖掘链路的建设同时要支撑推荐系统、广告系统这些对实时性要求高的业务场景。所以笔试不可能只考算法也不可能只考大数据组件背概念而是要把“后端工程师的编码能力”和“大数据工程师的架构思维”糅合在一起考。从第三批笔试的卷面结构来复盘主要分成四个模块考察模块占比核心能力指向数据结构与算法手写题30%基础编码功底、边界条件把握Java/Scala与并发基础20%后端语言掌握程度、并发场景意识大数据组件原理与使用30%HDFS/Spark/Kafka等原理理解系统设计与场景题20%海量数据处理的工程判断力这个比例不是随便定的。算法占比高是因为后端开发第一天就要写代码代码能力是底线大数据组件占比更高是这个岗位区别于普通后端的关键系统设计题则是筛选那些只会背概念、不会落地的候选人。1.2 第三批意味着什么校招笔试分批次很多人担心第三批会不会题目更难或者机会更少。实际上从招聘方的角度看分批考试主要是为了缓解服务器压力和组织面试官资源卷面难度和批次数没有必然联系。但有一点要注意到了第三批前两批的通过情况会直接影响本批的通过率基准。如果前两批已经招到了足够多合适的人第三批的筛选标准会更严格容错率更低。我当时做这套卷子的时候有一个直观感受它不像很多大厂笔试那样全是变态难的算法题而是更务实很多题目直接对应日常工作场景。比如考Kafka的offset管理、考Spark的宽窄依赖、考HDFS的小文件问题这些在真实的日志采集和离线分析任务里天天都要面对。所以说穿了很多公司的笔试其实都在回答一个问题你来了能不能直接干活。2. 算法与数据结构手写代码环节的踩坑与加分项2.1 Top K问题的两种解法层次笔试里有一道很经典的大数据算法题给定一个包含上亿条日志的文件每行是一条访问记录要求统计访问次数最多的前100个IP。这题从算法本身看是典型的Top K问题但放在大数据背景下考的不只是堆排序而是海量数据下的内存意识。第一层解法是把文件读进内存用HashMap统计频率再用大小为K的最小堆维护Top100。这个方案在数据量几千万条的时候够用但到了上亿条甚至数十亿条的时候HashMap会耗尽内存直接就OutOfMemoryError了。所以我在考卷上是这样处理的第一步对文件做哈希分片按IP的hash值取模N把大文件拆成N个小文件保证同一IP只会落在一个文件中 第二步对每个小文件分别用HashMap统计频次再用大小为100的最小堆取Top100 第三步对N个文件的Top100做归并得到全局Top100。这种分治思路其实就是一个简化版的MapReduce——Map阶段做分片和局部统计Reduce阶段做全局合并。我在试卷上把这一步写出来之后明显感觉到阅卷视角会不一样因为它证明你不是只会调API而是理解分布式计算的根本思想。2.2 LRU缓存设计考察工程细节的算法题另一道算法题是手写LRU缓存。这题本身不难但有一个关键点使用LinkedHashMap实现是一种写法手动实现双向链表加HashMap是另一种写法。很多人在笔试里选择了LinkedHashMap代码量少正确性容易保证。但我在当时选的是双向链表加HashMap的手写方式原因有两个第一面试官后续追问“为什么LRU要用双向链表而不是单链表”的时候手写过的人能答得上来删除一个节点的时候需要同时知道它的前驱节点单链表需要从头遍历才能找到前驱时间复杂度就退化成O(n)。双向链表能保证get和put都是O(1)。第二LinkedHashMap的accessOrder模式虽然也能实现LRU但面试官容易追加一个问题“如果让你在并发场景下用这个LRU你会怎么改”这时候如果你只写过LinkedHashMap版本思路明显会卡住。我当时的回答是加锁或者用ConcurrentHashMap配合锁分段虽然不算最优解但至少体现了我考虑过并发问题。2.3 算法题的时间分配策略三批笔试的算法题量一般在两到三道手写题时间分配上我给一个参考第一道简单题控制在15分钟以内中等难度的控制在25分钟以内最后一道难题至少留40分钟。算法题宁可少做一道也要保证已做题目通过尽可能多的测试用例因为面试官看的是解题质量和代码风格而不是AC数量。另外有一个我后来反复强调的细节笔试里写代码一定要有注释习惯。哪怕是在线笔试也要在关键逻辑边上写一行注释面试官看代码的时候注释能帮他快速理解你的思路。这一点在校招笔试里是被严重低估的加分项。3. 大数据组件专项笔试里出场率最高的几个知识块3.1 Kafka面试题的作答重点不只是背概念第三批笔试里关于Kafka的题目我记得很清楚问的是“Kafka如何保证消息的有序性以及Consumer的offset存在哪里”。这题在当年是Kafka系列的高频题现在依然是。但多数人的回答都停留在“partition内有序跨partition不保证”这个层面很难拿高分。我当时的作答思路分了三个层次。先解释Kafka的partition机制生产者指定消息在同一partition内追加写入所以有序性只存在于partition级别如果业务强依赖全局有序只能通过指定key哈希到单一partition来实现代价是吞吐量下降。这一步先把原理讲透。再讲offset的存储位置旧版本的offset存在Zookeeper里但Zookeeper不适合高频读写所以新版本把offset作为内部主题__consumer_offsets存到Kafka自己集群里消费者通过提交offset记录消费位点这样才能实现断点续传。这里能点明“新版为什么用Kafka存而不是Zookeeper”就比背答案的人高一层。第三层是加分项我当时主动写了“如果Consumer在提交offset前崩溃会导致重复消费如果提交了没处理完会导致消息丢失。所以生产环境一般做‘先处理业务逻辑再提交offset’的处理并接受至少一次语义”。这一层实际上是在向后端大数据岗位的核心要求靠拢——你要有处理分布式系统不一致问题的工程判断。3.2 Spark宽窄依赖与血统机制的必考逻辑Spark相关题目里我最推荐大家仔细准备的考点是宽依赖和窄依赖的区别、Stage如何划分、血统机制如何实现容错。这套题几乎是所有大数据笔试的钉子户。窄依赖是指父RDD的每个分区最多被子RDD的一个分区使用比如map、filter宽依赖是指父RDD的每个分区可能被子RDD的多个分区使用典型的是groupByKey、reduceByKey这个过程会产生shuffle。Stage划分的原则是从后往前推遇到宽依赖就切断所以宽依赖是Stage的边界。我当时在试卷上补充了一个容易被忽略的点reduceByKey和groupByKey虽然都产生shuffle但reduceByKey会在map端先做一次本地聚合相当于把shuffle的数据量缩小了所以在做分组聚合时优先用reduceByKey而不是groupByKey。这个细节在笔试里不一定占很多分但在面试聊项目的时候几乎是必问的。关于血统机制核心是讲清楚为什么Spark不需要像Hadoop那样每次把中间结果落盘每个RDD都记录了它的父RDD和计算函数当一个分区丢失时可以通过血缘关系重新计算避免了数据副本的多份存储。但Shuffle过程本身是不可靠的所以shuffle的数据需要落盘这也是为什么宽依赖比窄依赖代价大得多。3.3 HDFS数据写入流程与副本策略大数据方向笔试不会绕过HDFS。第三批考了一道关于“HDFS写文件流程”的题要求描述从客户端发起写入到数据落盘的全过程并说明副本放置策略。这个问题要答得有条理可分五步步骤操作说明1客户端向NameNode发起上传请求检查权限和目标路径2NameNode返回可用的DataNode列表按网络拓扑选择节点3客户端将数据分块写入第一个DataNode默认128MB一个Block4DataNode之间流水线复制副本节点间直接传输不经过客户端5所有副本写入完成后客户端确认关闭流NameNode更新元数据副本放置策略要讲清楚机架感知默认3副本的话第一个副本放在客户端所在节点第二个副本放在同一机架的另一个节点第三个副本放在不同机架的一个节点。这样设计的核心思想是同一机架内的副本保证写入性能和带宽跨机架的副本保证数据容灾能力。这个知识点的价值在于它能够串联起一系列后续问题为什么不能只放一份副本、为什么块大小是128MB而不是更小、NameNode单点故障怎么解决。笔试经常只考一个点但回答的时候要有意识地把整个链路串起来。3.4 数据倾斜问题的排查思路大数据方向笔试还有一个非常务实的题通常以“实际生产任务运行缓慢怎么排查”的形式出现。第三批笔试里有一道问“Spark作业某个Task执行时间远超其他Task可能是什么原因怎么解决”这题我直接按数据倾斜来答了。生产环境里Task长尾90%以上都是数据倾斜引起的。我的排查思路是先看Spark UI里头每个Stage的Task耗时分布如果某个Task处理的数据量是其他Task的数倍基本可以确定是key分布不均导致某些分区的数据量过大。然后是处理手段优先推荐salting加盐法给倾斜的key加上随机前缀把它们打散到多个分区做完局部聚合再去除前缀做全局聚合。这个方法能解决大部分场景。我在试卷上多说了一句还可以在业务层面做过滤比如对无效的key空值、默认值在join前先过滤掉。这个点往往被忽略但实际效果经常比技术手段更直接。4. 系统设计题日志收集系统的完整设计思路4.1 从题目要求读出的真实业务场景第三批笔试题里有一道系统设计题场景是“设计一个支撑日增数十亿条用户行为日志的实时收集系统要求数据延迟在分钟级并且支持离线分析和实时计算两条链路”。这道题目的场景还原了触宝海外产品后台的真实需求客户端埋点数据量巨大同时要喂给实时推荐和离线报表。这类题在笔试里容易难住人是因为很多人没有做过完整的数据管道设计不知道从哪入手。实际上它考的不是你能不能像架构师一样设计出一套完美的系统而是你有没有基本的组件选型和数据流意识。4.2 一个可落地的参考架构我当时给出的设计方案核心链路是客户端SDK埋点 - Nginx/LVS负载均衡 - Flume日志采集 - Kafka消息队列 - Storm/Spark Streaming实时处理 - HDFS存储 - Hive离线分析这个链路每一步都有明确的选型理由。客户端埋点数据首先经过负载均衡进入采集层选择Flume是因为它能灵活对接各种数据源并且自带channel缓冲区可以防止后端瞬时压力过大造成数据丢失。Kafka是整个链路的峰值缓冲层它的高吞吐能力把采集层和计算层解耦采集端不用关心下游处理速度计算端可以按需消费。实时计算层我选择Spark Streaming而不是Storm因为当时Spark Streaming的秒级延迟已经能满足多数业务需求且能和Spark离线任务共享同一套代码逻辑和生态。实时结果输出到Redis或者Kafka供业务方读取同时原始数据落地到HDFS供每天的Hive离线任务做全量分析和报表生成。4.3 面试官在答案里挖掘的隐藏考察点这道题要拿高分关键在于写出两个容易被忽视的细节。第一个是数据丢失的兜底方案Kafka的offset记录了消费位点如果实时任务挂了重启后可以从最近提交的offset继续消费数据不会丢也不会重复。这个能力是整套系统的容错基石。第二个是链路监控和报警设计里要提到对Kafka集群的积压量、消费者Lag、HDFS写入成功率这些指标做监控阈值触发时通过邮件或短信报警。这个细节不加设计就只是纸上谈兵加了面试官就知道你考虑过线上运维的事情。还有一个小技巧系统设计题最好画一个简单的箭头链路图哪怕在线笔试环境里用文字画也可以它能让阅卷人一眼看到你的思路结构省去阅读文字的负担。我自己在笔试时一直用文字画箭头指向这个小习惯帮我节省了很多描述架构的时间。5. 备战策略与笔试过程中的实用技巧5.1 时间分配与答题顺序在校招笔试里时间管理几乎和知识储备同等重要。以触宝这套卷子为例总分150分钟我建议的分配是内容建议耗时策略选择题/判断题30分钟不要犹豫不确定的先标记最后再回看算法手写题60分钟优先做有把握过的题留足调试时间大数据问答题35分钟按原理、场景、优化的结构组织答案系统设计题25分钟画链路图列组件选型理由写兜底方案选择题部分不要浪费太多时间因为分值占比通常不高。但要注意选择题的答案可能在后面的问答题里被再次使用比如选择题里问“Spark的默认并行度由什么决定”后面问答题可能让写一个Spark提交命令并设置并行度前后呼应。这时候前面选错后面也会受影响所以做选择题时也要尽量回忆原理别纯蒙。5.2 知识点储备清单结合这套卷子的考察范围我整理了一份当年备战用的清单对现在的校招同样适用。语言与算法部分需要准备Java集合类源码级别的实现原理HashMap的put流程、扩容机制、ConcurrentHashMap的分段锁、线程池的核心参数与拒绝策略、以及TopK、LRU、有序链表合并这类高频手写题。大数据组件部分是重头戏每一个组件都要能回答“是什么、解决了什么问题、核心原理、实际使用时有什么坑”。HDFS要掌握读写流程、副本策略、NameNode元数据管理MapReduce要掌握shuffle全流程、combiner的作用、数据倾斜处理Spark要掌握RDD、DAG、宽窄依赖、Stage划分、算子调优、内存管理Kafka要掌握存储结构、副本机制、消费组、offset管理、消息不丢失的三种语义。这些内容表面上是背概念实际上每一条都能和某个实际故障场景关联上背的时候尽量带着场景去理解。5.3 笔试过程中容易忽略的细节回看那次笔试说实话踩了不少坑。第一是环境问题在线笔试系统用的是Coding.net当时我在本地IDE里写的代码没问题因为用的Java版本有细微差异粘贴到在线编辑器后编译报错浪费了五分钟。建议笔试前先去系统的模拟环境里试一次编译确认JDK版本和类库支持情况。第二是审题不仔细。有一道大数据题问的是“如何提高HDFS读取吞吐量”我看成“写入吞吐量”答偏了。这类错误在时间紧张时特别容易发生我的办法是读题后先把题目里的关键词圈出来或者抄到草稿纸上比如“读取”“写入”“倾斜”“实时”这些限定词明确以后再动笔。第三是对不确定的题目不要空着。笔试过程里系统设计题没有标准答案只要逻辑完整、组件选型理由站得住脚就算方案不是最优也能拿大部分分数。我当时有一道关于数据去重的问题方案不是最高效的但思路完整后来面试官反馈说那道题答得“有工程可行性”这给我在面试阶段争取了不少印象分。6. 事后复盘从笔试题目反推公司技术栈与团队水平6.1 题目暴露出的团队业务方向笔试内容从来不是随便出的每道题都对应着公司业务线的真实技术需求。从触宝这套第三批笔试题看日志采集与实时计算比重很高说明公司内部对用户行为数据的实时分析有强烈诉求。当时触宝的产品矩阵以输入法和海外应用为主这类产品的推荐系统对用户点击、输入、下载行为的时效性要求很高所以日志收集、实时特征计算、消息队列这些技术成了考察重点。另一个明显的信号是整个笔试和Spark紧密相关答案里如果只写Hadoop/MapReduce而不提Spark在系统设计题里会显得技术选型过时。这也是我前面强调Spark原理的原因——笔试出题人把业务的技术栈偏好藏在了题目里有心的考生应该敏锐地捕捉到这一点。6.2 笔试与面试的衔接关系校招的笔试成绩不只是决定你能否进入面试更会影响面试的深度。通常笔试答得好的同学面试官会默认基础扎实因此面试时会直接问项目细节和深入原理如果笔试成绩一般面试官会更谨慎先补问基础再聊项目。换言之你在笔试里展示的能力决定了面试的难度起点。我那次笔试里写到一个数据倾斜的解决案例面试时被追问得很细包括盐值怎么生成、加盐之后做预聚合的代码怎么写、为什么不直接用双聚合。这些问题本质上都是围绕笔试答案展开的所以笔试里涉及的所有内容面试前都要准备到可以口头复述的程度。6.3 给后来者的一句话建议回头复盘这套笔试我最想分享的一条经验是笔试本身不是一个筛选工具它更像一面镜子照出你技术体系和思维方式的短板。你可以不会某一道题但你不能不知道自己为什么不会。每一道错题背后都有对应的知识模块和思维方式需要补强这才是笔试真正的价值所在。