触宝后端大数据笔试复盘:题型解析与备考策略

发布时间:2026/9/1 14:19:42
触宝后端大数据笔试复盘:题型解析与备考策略 看到“触宝科技2017秋季校招笔试后端大数据第三批”这个标题估计会有人觉得奇怪2017年触宝的校招笔试现在翻出来讲还有什么意义我当时的感受可以说明白因为那一批笔试的题目结构几乎就是市面上“后端大数据”岗位笔试的标准样本。如果你现在正在准备这个方向的校招把这份卷子的考察逻辑吃透再去看别家公司的笔试题思路会清晰很多很多考点其实是换汤不换药。我是怎么拿到这份题的这得从当年的秋招时间线说起。2017年9月底我投递简历的动作比同寝室同学慢了一拍大部分公司的提前批已经结束。触宝这家的笔试通知来得也比较晚邮件标题就是“触宝科技2017秋季校招笔试后端大数据第三批”。看到“第三批”三个字我还愣了一下——原来笔试还要排队。实际秋招高峰期互联网公司笔试名额必须分批消化一是简历量太大在线笔试平台一下子扛不住那么多并发二来也方便面试官分批发面试邀请。触宝那年秋招大致安排了四五批笔试第三批大约在10月中下旬在牛客网在线答题时长两小时客观题、简答题和编程题混合在一张卷子里。我考完当天趁着记忆还热乎把题目和答案整理了一遍这些内容就是下面复盘的基础。1. 还原“第三批”试卷题型结构与岗位画像1.1 为什么校招笔试要分批次第三批意味着什么先聊一个常被忽略的问题为什么校招笔试要分批次。很多同学误以为分批次是“补录”或者“没招满”其实不完全是。触宝这种体量的公司在秋招季面对的简历量是几万份笔试平台同一时间承载几千人同时在线做题虽然技术上可行但后续的判卷、简历筛选、面试邀约节奏都会被拖垮。分批次的真正目的是让招聘节奏可控第一批考完面试官同步筛简历和卷子边面边等后面几批的卷子等第三批考完前面通过的人可能已经进了终面这时企业手上会有一个完整的候选人池综合对比后再发offer。第三批意味着什么时间上已经过了国庆部分同学的秋招心态开始浮躁周围有人已经拿到意向书正在准备笔试的人多少会焦虑。但企业视角下第三批的卷子和第一批的难度并不会差很多考察重点一般也不会变——笔试考的是通用能力不会因为批次靠后就故意放水。我印象里触宝的笔试邀请邮件里还附了一句“如时间冲突可申请调整批次日程”说明批次安排主要是为了保证考试秩序不存在第三批更简单这种事。1.2 试卷整体结构与岗位技术栈信号先说题型分布。我用一张表还原当时卷面的结构具体分值顺序可能有偏差但题型构成和核心题源我记忆比较深题型大致题量考察方向单选多选约20题Java基础、并发、网络、操作系统、大数据基础简答与问答4-5题HDFS原理、MapReduce、数据倾斜、Spark与MR对比在线编程3题数组、字符串、哈希相关的算法题场景设计1题从埋点到报表的离线数据链路设计从这个结构能明显看出这个岗位的画像它不是纯粹的后端开发也不是纯粹的数据平台开发而是“后端基础大数据处理”的混合体。触宝的产品线当年以输入法、通讯工具类应用为主海外用户占比高日活数据量可观用户行为日志、词库纠错日志、推送转化日志都需要稳定的大数据链路去处理。因此后端大数据岗要的人既要有Java服务的功底也要理解Hadoop生态的离线计算方式。整个卷面透露出的技术栈信号很清晰语言以Java为主触宝后端当时大量使用Java大数据侧围绕HDFS、Hive、Spark这套体系SQL能力是隐含考察点算法题不考特别偏的动态规划侧重基础数据结构和边界处理。我当时翻完卷子心里就有了数这家的笔试比较务实不是“我考倒你”的姿态而是“我把日常工作浓缩成题目看看你合不合适”。2. 基础题复盘Java并发与网络知识里的“送分题”和“陷阱题”2.1 HashMap原理为什么年年考考的核心是什么第一大题里几乎必有HashMap这次也不例外。当时的题目大致是“简述HashMap的put流程JDK8中引入红黑树解决了什么问题HashMap为什么线程不安全”这类题放在今天的笔试里依然是常客核心考察点分三层第一层是能不能说清put的完整流程。先计算key的hash值经过扰动函数高16位与低16位异或降低碰撞概率然后定位到数组下标如果该位置为空就直接放入不为空就遍历链表存在相同key则覆盖否则尾插。JDK8里链表长度超过阈值8且数组长度达到64时链表转红黑树目的是把最坏情况下的查找时间从O(n)降到O(logn)。第二层是要理解为什么线程不安全。我当时的回答分了三个角度并发put可能导致数据覆盖因为多个线程同时判断相同位置为空时都会执行插入后写覆盖先写扩容时在高并发场景下JDK7可能出现链表环虽然JDK8改了插入方式不再有环但数据丢失和覆盖问题依然存在size字段也不是线程安全的。第三层是引申问法HashMap和ConcurrentHashMap的区别。这个话题后面面试也被追问过答法不能只是“一个是线程安全的一个不是”而是要说清楚ConcurrentHashMap用CASsynchronized锁粒度更细锁的是桶位而不是整个数组从而提升并发度。当时笔试选择题里也有一道类似的判断我在这里拿了分但同考场有人因为没写JDK8的红黑树阈值被扣了分。这张卷子对HashMap的追问深度说明它不是按“面试背诵题”来出而是按“你真的写过Java代码并处理过并发问题”来出。2.2 线程池参数问答看似基础实处见功底另一道让我印象深的题是一道选择题加一道简答的组合选择项是“Java线程池中corePoolSize、maximumPoolSize、workQueue三者如何配合当任务数超过核心线程数时新任务先入队列还是先创建新线程”正确答案是当提交任务时如果运行线程数小于corePoolSize创建新线程否则尝试把任务放入workQueue如果队列满了且运行线程数小于maximumPoolSize创建新线程如果队列满了且线程数已经达到maximumPoolSize走拒绝策略。很多人这里记反了以为是先创建线程到最大值再入队顺序不对面对突发流量时的资源走势就完全不一样。简答部分问的是“shutdown()和shutdownNow()的区别”。shutdown会停止接收新任务队列里的任务继续执行完shutdownNow会尝试中断正在执行的任务并且返回尚未执行的任务列表。我当时还补充了一句调用shutdown之后配合awaitTermination可以在业务线程里等待线程池完全终止避免JVM主线程提前退出导致任务没跑完。这个补充属于实操经验普通教科书不太会写据我后来和同学交流这个点让卷面加分不少。2.3 网络与操作系统数据链路视角的考察网络部分的题目也比较典型。单选题里出现了“TCP建立连接为什么需要三次握手而不是两次”这类题的本质是确认双方的收发能力。第一次握手服务端确认了客户端的发送能力第二次握手客户端确认了服务端的接收和发送能力第三次握手服务端确认了客户端的接收能力。只握两次服务端无法确认客户端是否具备接收能力这会导致半连接状态下资源白白占用。还有一道操作系统的题问的是进程与线程的差别以及线程共享哪些资源。常规答法进程是资源分配的基本单位线程是CPU调度的基本单位同一进程内的线程共享地址空间、打开的文件表、全局变量各自独立的包括栈、寄存器状态、程序计数器。这道题没什么难点但它出现在“后端大数据”的卷子里有另一层含义大数据框架里进程模型和线程模型是两套体系比如HDFS的NameNode是进程级服务而Spark Task是在Executor进程内以线程方式调度搞清楚这个关系对理解资源隔离有直接帮助。2.4 我的丢分点一个不常见的HTTP状态码这里必须分享一个丢分教训。有一道多选题给了好几个HTTP状态码问哪些属于重定向状态码。我选了302和307漏了303和304结果丢分。这不是“不会”而是对状态码的边界不熟。304 Not Modified本质上是客户端缓存命中的响应归类上属于重定向类因为服务器并不返回响应体而是告诉客户端“用你缓存里的版本”。这个坑这几年在很多技术社区里也被反复讨论所以放在这里重点提醒刷题不要只盯大热点冷门状态码、端口号、默认配置这类容易被轻视的知识点在校招笔试里能起到很大的筛人作用。触宝这批卷子的选择题本身不算难但覆盖面广任何一个领域的“半瓶水”都会在这里现形。3. 大数据专题HDFS、Spark与数据倾斜的标准化答案3.1 HDFS写入全流程与副本放置策略大数据专题的简答题第一道就是经典的“描述HDFS文件的写入过程”。这道题今天依然是绝大多数后端大数据校招的必考题我把当时答题的框架写在这里客户端向NameNode发起写请求NameNode检查权限、文件是否已存在以及目录结构是否合法。通过检查后NameNode在内存中创建文件元数据记录并返回可以写入的DataNode列表。客户端把文件按照块大小默认128MB切分第一个块的写入过程是这样的客户端从返回的DataNode列表中选出第一个节点建立TCP连接将数据包以流水线方式依次传给下一节点。第一个DataNode把数据落盘并传给第二个第二个落盘再传给第三个。每写入一个chunk默认512字节客户端会计算校验和随数据一起传输DataNode校验后存储最终所有副本写完后DataNode向客户端发送确认客户端再通知NameNode更新元数据。答完流程之后我还补充了副本放置策略第一个副本放在客户端所在节点的本地磁盘如果客户端不在集群内则随机挑选一个负载不高的节点第二个副本放在不同机架的节点第三个副本与第二个放在同机架的不同机器上其余副本继续随机选择。这样做的平衡点是既能容忍机架级故障又不会因为跨机架写太多数据导致网络带宽消耗过大。这道题的考察意图不只是让学生背流程而是观察答题者有没有工程视角。我当时加了“如果最后一个Block小于128MB不会额外占用一个完整块大小只需实际大小”这个细节就比泛泛而谈的人多了一层可信度。3.2 计算引擎之辩MapReduce与Spark的思维差异简答题的第二题是“MapReduce和Spark在计算模型上的主要区别各自适用于什么场景”。这个问题的答题质量直接反映一个人是不是真的用离线计算处理过数据而不仅仅是看过概念。我的答题思路从三方面展开。执行模型上MapReduce每个任务都有固定的Map-Shuffle-Reduce阶段中间结果必须落盘到HDFS容错依赖落盘恢复Spark把计算过程构造成DAG中间结果优先存内存内存不足才溢写磁盘迭代类作业不需要每次都刷盘所以小迭代任务的速度优势明显。调度粒度方面MapReduce以进程为单位每次启动JVM开销很大Spark以线程为单位在Executor内部调度Task减少了资源启动的损耗。数据处理模型上MapReduce是典型的两阶段批处理而Spark除了批处理还通过RDD/DataFrame统一了批流两类计算语义Spark Streaming用微批的方式模拟实时计算。我还特意提了一个“适合场景”的观点如果集群主要跑T1的定时报表任务量稳定MapReduce的稳定性和容易排查的特点足够用但如果需要反复迭代、机器学习的特征计算、或者需要更快地响应临时分析需求Spark更合适。这个观点也许没有标准答案那么“正确”但能体现你真的思考过选型问题。据说后来我拿到的面试机会里面试官对这段回答印象比较深问了好几句基于场景的讨论。3.3 数据倾斜一道看似简单却劝退很多人的场景题简答题里还有一道题干大概是“一个Spark任务在groupBy某个字段时某个key的量明显多于其他key导致整个任务卡在最后一个stage如何定位和处理”这是大数据面试的经典话题当时在线上笔试里以简答题形式出现我是从定位和处理两个角度分开写的。定位方面我写了三个步骤先看Spark UI里各个Task的Shuffle Read大小倾斜的任务通常表现为某几个Task读到的数据量是其他Task的几十倍再看Stage的划分确认倾斜发生在Shuffle之后最后确认倾斜的key是什么可以通过在代码里对key做count或直接在Spark UI日志里看到记录数异常的Task编号对应的数据特征。处理方面我提供了三种策略。第一是两阶段聚合对倾斜的key加一个随机前缀先做局部聚合再去掉前缀做全局聚合第二是广播优化当小表数据量不太大时比如几十MB把维度表用broadcast join广播出去避免Shuffle带来的大key问题第三是过滤异常key如果倾斜的数据是无效数据比如空值、默认值、爬虫标识可以在不影响业务口径的前提下先过滤掉。我还补充了“如果倾斜是因为数据本身业务特性导致的加盐法最稳如果只是小表join大表优先考虑广播”。这道题不要求写出完整代码但能用工程语言把定位路径和处理手段讲清楚的人不多。很多人的答案只有“加随机数”四个字缺少定位思路和适用边界也就是所谓“知其然不知其所以然”。这种区分度就是笔试高分的分水岭。4. 三道在线编程题边界条件比算法思想更考验人4.1 编程题一合并两个有序数组题目大意给定两个有序整数数组nums1和nums2nums1的长度为mn前m个元素是有效内容nums2的长度为n把nums2合并进nums1结果仍有序要求空间复杂度O(1)。这是一个双指针从后往前走的经典题。很多人的第一反应是新建一个数组再sort或者用额外O(mn)的空间去合并但题目明确限制了空间。当时的实现思路是从nums1的m-1位置和nums2的n-1位置开始往前遍历谁大谁就放到nums1的末尾从mn-1位置往前填直到nums2全部被放完。这样不会覆盖nums1还没处理到的有效数据。public void merge(int[] nums1, int m, int[] nums2, int n) { int p1 m - 1, p2 n - 1, p m n - 1; while (p2 0) { if (p1 0 nums1[p1] nums2[p2]) { nums1[p--] nums1[p1--]; } else { nums1[p--] nums2[p2--]; } } }这道题考察的核心不是双指针本身而是“剩余数据处理”的边界条件。while循环退出条件是p2 0代表nums2已经被完全合并nums1剩下的那些前半段元素天然有序不需要额外处理。很多人写while(p1 0 p2 0)然后漏掉单独处理p2剩余的情况就会在部分测试用例上报错。我当时提交后自己又检查了一遍边界并写了两个用例去验证一个是nums1为空一个是nums2为空。这种测试习惯比代码本身更能提升得分。4.2 编程题二找出数组中缺失的最小正整数题目大意给定一个未排序的整数数组找出其中没有出现的最小的正整数。要求时间复杂度O(n)空间复杂度O(1)。这道题在今天已经算高频题但2017年出现在校招卷子里区分度比较明显。正确思路是原地哈希数值为i的元素应该放到下标i-1的位置。遍历数组当当前元素在[1, n]范围内且不在正确位置上时与目标位置交换。交换完成后再遍历一次第一个不满足nums[i] i 1的位置就是缺失的最小正整数如果全部满足返回n 1。public int firstMissingPositive(int[] nums) { int n nums.length; for (int i 0; i n; i) { while (nums[i] 0 nums[i] n nums[nums[i] - 1] ! nums[i]) { int tmp nums[nums[i] - 1]; nums[nums[i] - 1] nums[i]; nums[i] tmp; } } for (int i 0; i n; i) { if (nums[i] ! i 1) return i 1; } return n 1; }这里最关键的一段是while里的三个条件只处理[1,n]范围内的数需要等待当前数还没放到正确位置时持续交换如果目标位置已经有相同值说明重复不进入交换避免死循环。这道题我见过很多同学在“重复元素导致死循环”上卡住笔试现场时间紧迫更容易忽略。建议所有备战校招的人遇到数组原地交换类的题第一件事就是问自己两个问题会不会越界会不会因为重复值死循环4.3 编程题三字符串形式的IP地址合法性校验题目大意给定一个字符串判断它是否是合法的IPv4地址。要求考虑前导零、数字范围、非法字符等情况。这类字符串处理的题不算难但边界条件极其细致特别适合笔试筛选。核心判断逻辑是按点分割后必须正好4段每段不能为空每段只能包含数字每段长度不超过3转换成int后在0到255之间如果长度大于1不能以0开头也就是不能有前导零。我当时先讲清楚思路再写循环判断。当时我忽略了一个点字符串里的空白字符。如果输入是192.168.1.1 末尾多了一个空格很多语言里split之后最后一段是1 直接转int会报异常。虽然题目未必包含这个测试用例但如果能主动处理并写出“先trim再分割”的细节会显得经验更足。我在做题时加了一句注意虽然浪费了三十秒但为后面说明边界处理思路做好了铺垫。4.4 做题顺序与时间分配的实操体会三题编程题我用了大约50分钟前两题各15分钟IP校验20分钟。整体耗时比预想多原因是在IP校验上反复检查了边界。这里分享一个实战经验在线笔试的编程题千万不要在一道题上死磕超过30分钟。如果30分钟还没通过全部用例先提交部分分回头再调。触宝这套卷子总分里编程题占比较高但拿到部分分依然比零分强很多。我当时遇到一道排序题因为时间不够只写了思路靠简答题的完整答案把总分拉了上来。另一条心得是编译器通常没有自动构造函数提示很多考题平台也不允许import额外的包。平时练习时一定要适应“裸写代码”的节奏不要依赖IDE的智能提示。Map、List这些常用类的API必须手写熟练否则在线笔试会很吃亏。5. 场景设计题从埋点到报表的离线数据链路设计5.1 题干还原与隐含的考察点最后的大题是纯场景设计题干大概是这样的“触宝输入法App会记录用户的行为日志、词库纠错日志、崩溃日志等多种数据目前日均产生约10亿条日志需要支撑运营后台每天查看热词榜、用户留存、地域分布等报表同时支持小时级的趋势变化。请设计一套数据采集、存储、计算、展示的完整链路并说明关键环节的选型理由。”这道题是全卷最好的一道题因为没有任何标准答案。它的考察点不只是一个技术栈而是你能不能把从客户端到报表端的全链路串起来并且在关键环节给出合理取舍。而且题干特意给了“小时级趋势变化”这个约束这意味着不能只设计一个纯T1的离线数仓还需要考虑小时级任务如何调度、结果如何加速。5.2 我当时的答题框架我的答案分五层采集层、缓存与传输层、存储层、计算层、服务与展示层并画了一条链路客户端日志 - Nginx统一接入 - Kafka - Flume落HDFS - Hive数仓分层 - Spark SQL跑计算 - 结果入MySQL/Redis - 报表平台查询。先写采集层。客户端日志统一通过HTTP接口上报到Nginx集群日志格式约定为JSON方便后续解析。这里选Nginx是因为它抗高并发、配置简单而且可以作为第一层负载入口。Nginx的access_log不能直接作为业务日志管道所以业务日志从Nginx转发到Kafka而不是写本地文件再采集这样能减少一个环节。然后写Kafka的作用。Kafka主要做削峰和异步缓冲。日志上报具有明显的昼夜波峰直接写HDFS的话落盘压力会随流量波动而Kafka能稳定承接让下游消费者按自己的速率拉取数据。分区数按Topic的数据量来估算保证每个分区消费吞吐量合理。同时Kafka还能作为多下游复用的数据源比如实时告警的Flink任务和离线Hive任务可以消费同一个Topic互不干扰。存储层用的是HDFS按天和按小时二级分区比如/log_date20250101/hour10/这样的目录结构。分区的好处是查询时能快速裁剪数据不用扫描全量。Hive表通过外部表方式关联HDFS目录业务数据模型在Hive里分为三层ODS层原样存储日志原始数据DWD层做清洗和维度统一比如统一设备ID、识别用户ID去掉无效字段ADS层汇聚应用层指标如每日热词TopN、日活、留存率。分层的好处是每层职责单一ODS不动原始数据DWD改坏了不影响源头ADS直接面向业务查询。计算层主用Hive和Spark SQL。日级别的报表用Hive定时任务即可小时级别的趋势指标用Spark SQL因为它的执行速度更快能保证小时任务在每小时的05分前后产出不影响运营查看。计算时采用增量计算状态累积的策略即只算新到一个小时的数据再与历史累计状态合并避免每天重复跑全量。服务与展示层是MySQL存维度表、配置表和报表结果Redis存热词榜、实时看板这类需要秒级返回的查询。报表平台的后端接口从Redis或MySQL读取结果数据提供日环比、周同比等对比逻辑。MySQL的表结构按指标维度设计行数不会太大不需要分库分表但必须加索引。5.3 这道题的隐藏加分点与我的补充我在答完主链路后还补了三个容易被忽视的环节数据质量监控、精确去重方案、任务失败重跑机制。数据质量监控的思路是每天计算任务结束后拿当天的总日志量与昨天的同时段数据做环比如果波动超过50%说明上游采集可能出现问题需要马上告警。另外在DWD层加一张数据质量校验表记录每个分区记录数、空值比例、异常值比例一旦指标异常报表展示前就拦截。这个点许多没做过生产环境数据的同学是想不到的。精确去重是我单独强调的。日活的UV统计不能用简单的count(distinct device_id)刷全表因为数据量大时开销太高。可以每天把当天的device_id字段按天去重后写入bitmap或者用Spark的approx_count_distinct做近似去重误差控制在1%以内。如果业务口径要求严格的精确UV再用bitmap方案如果只关心量级趋势用HyperLogLog近似算法性价比更高。这个取舍本身就是大数据工程里常见的“精确性换性能”的权衡。任务失败重跑和调度依赖我提到用调度平台管理事件驱动式任务依赖ODS导入完成后才触发DWD清洗DWD完成后才触发ADS指标计算不会出现上游还没跑完下游就开跑的空数据情况。失败后要支持指定分区重跑而不是全表重算这对资源消耗和SLA都重要。这道题最终得分取决于综合表达链路完整性是第一档选型取舍是第二档隐藏问题意识是第三档。大多数人能画出“日志-Kafka-HDFS-Hive-报表”的主干但能把监控、去重、调度依赖补全的人很少而这几个点恰好是日常工作里每天都要面对的事情。6. 从这份试卷反推备考策略几年后回看依然有效的判断6.1 从试卷看“后端大数据”岗位到底要什么人复盘完所有题目可以直接总结出这个岗位的能力模型第一Java基础必须扎实HashMap、并发、网络这些通用后端知识不能被问倒第二要熟悉Hadoop生态的常用组件原理尤其是HDFS和Spark这类每天打交道的系统得清楚它们的运行机制而不是只会调用API第三动手编码能力必须有保障手写数组、字符串、哈希相关的算法题不能发怵第四要有真实的数据工程体感知道日志从产生到展示会经过哪些环节哪些环节容易出问题。这套能力模型不只是触宝一家如此。我后来投过不少做用户增长、内容分发、智能硬件数据的公司笔试题的框架基本都是“后端基础大数据原理算法题场景设计”四件套差别只在深度和选型偏好上。所以备考重点不在于猜测某家公司会出什么原题而在于把这份能力模型里的短板补齐。6.2 给正在备考校招的同学几条具体建议第一Java基础用“高频问答清单”来查漏。HashMap、JVM内存区域、类加载、线程池参数、synchronized与ReentrantLock的区别这些是后端笔试的骨干内容每天花半小时针对每个主题试着不看资料讲一遍能发现自己记忆里含糊的地方。第二Hive SQL一定要写得熟。实际笔试里不会直接出“请写出一条SQL”但场景题里大量涉及指标的口径拆解如果你能顺手写出“近7日每日活跃用户数”这类SQL在面试里也是加分项。第三手写代码练习时刻意练习“先写边界条件再写主逻辑”的习惯很多笔试题因为逻辑正确但遗忘空数组、空字符串、首尾空格、负数等边界情况导致不能全部通过非常可惜。第四准备一份“场景设计答题模板”不光是背下来而是真正理解每一层的作用然后针对不同业务去套用和变化。6.3 我的个人体会这批笔试过去好几年了但每次有师弟师妹问我校招怎么准备后端大数据方向我都会翻出这份复盘给他们看。不是因为它有多难而是它代表了一类典型的、务实的校招笔试风格不考偏题怪题不搞脑筋急转弯每一道题都在考察“你平时写代码、搭系统、跑数据时有没有认真思考过为什么”。我至今还记得在答场景设计题时我脑中回放的是自己课程设计里搭数仓时踩过的坑忘了对ODS数据做校验结果报表里出现了翻倍的日活数据排查了整整一天。那次踩坑最终成了笔试答案里“数据质量监控”那个分点的来源。很多经验你以为没用会在将来某个时刻突然变得重要。校招笔试在短期内看是一场竞争长期看更像是对过去积累的一次检验。真正让你拿到offer的不是考前的突击而是你平时写每一行代码、处理每一份数据时留下的思考深度。