去哪儿研发笔试题解析:高并发与缓存核心考点全梳理

发布时间:2026/8/30 6:06:52
去哪儿研发笔试题解析:高并发与缓存核心考点全梳理 这套题我当年还真认真刷过几遍最近又翻出来看了看发现虽然时间过去很久但里面考察的核心东西一点没过时。尤其是去哪儿这种做旅游搜索起家的公司研发笔试题跟纯互联网公司还不完全一样它更看重你对高并发、分布式、缓存这类和业务强相关的基础功底。今天就把这套题掰开揉碎聊一聊不光讲题更多讲讲每道题背后到底想考什么以及你怎么准备才能不吃亏。1. 笔试全景去哪儿2015研发笔试题到底在考什么1.1 从业务反推考点为什么考这些很多人刷题有个误区就是只看题不看公司。实际上去哪儿这套题如果脱离业务背景去看会觉得很散一会儿考链表一会儿考SQL一会儿又冒出个并发题。但你结合它当时的主营业务——机票、酒店的搜索和预订就会发现所有题目都在围绕同一个核心怎么在一个高访问量、高数据量、强一致性和高可用要求并存的环境下写出稳定高效的代码。机票搜索的特点是读多写少、峰值明显比如节假日抢票、春运抢票瞬间流量能冲得很高。这种业务场景决定了研发必须吃透三样东西第一是数据结构与算法因为搜索引擎底层大量依赖排序、索引、字符串匹配第二是Java并发与JVM因为服务器要同时扛住几十万连接第三是数据库与缓存因为查询量大但数据不能丢性能还得快。所以你在看这套题的时候别把它当成孤立的八股文而是要意识到它其实是把一个真实业务系统的技术难点拆成了一个个可以在两个小时里答完的小问题。理解了这一点你复习的时候就能分清主次知道哪些考点是必抓的哪些可以战略性放弃。1.2 试卷结构与知识点分布2015年的这套笔试题整体结构其实比较传统主要由选择题、简答题和编程题三大部分组成。选择题大概占总分的三到四成覆盖面很广从Java基础语法到网络协议、操作系统都有涉及简答题偏向原理阐述比如让你解释某个机制或对比两个概念的异同编程题则是重头戏基本是两道左右的手写算法题有时候会加一道数据库SQL题。我当时整理过一份知识点分布表后来发现不管是2015年还是现在大厂的笔试题都逃不出这个框架分享给你参考考察方向常见题型占比预估难度数据结构与算法手写代码、算法设计30%-40%高Java基础与并发选择题、简答15%-20%中操作系统选择题、简答10%中计算机网络选择题、简答10%低中数据库SQL编写、索引优化10%-15%中系统设计简答、设计题10%高这个分布不是随机的它反映的是一个研发工程师日常工作的真实构成。你每天写业务代码用的就是Java基础和数据结构你上线服务就要懂Linux和网络你排查慢查询就得会SQL优化。所以这套题的本质不是为难你而是在模拟你入职之后会不会干活。1.3 十年前的老题今天还有参考价值吗这也是很多人会问的问题。我的答案是单看题目本身有些技术细节确实过时了比如当时Java 8刚出没多久Lambda表达式还算新东西并发包里的很多类大家也用得不熟现在这些都成基本功了。但题目背后的考察逻辑没有变甚至因为现在竞争更激烈考得更深了。比如当年考HashMap原理很多人背一背数组加链表就能过关现在面试官会追问红黑树什么时候退化、为什么加载因子是0.75、并发下会发生什么。再比如当年考进程和线程的区别现在会延伸问你协程、虚拟线程。所以拿这套老题来做训练的价值在于它帮你把计算机基础的主干梳理了一遍你在这个主干上再去补充新知识会比直接刷一堆新题要有条理得多。2. 算法与数据结构笔试题里的硬骨头2.1 链表与指针操作手写代码的基本盘去哪儿这套题里链表题是出现频率很高的。原因很简单链表能综合考察你对引用、指针、边界条件的理解而且代码量适中很适合笔试环境。常见的有反转链表、判断链表是否有环、找链表中间节点、合并两个有序链表这些。拿反转链表来说别看它基础真到笔试现场能一次写对的人并不多。很多人不是不会思路而是栽在边界处理上。标准写法是迭代法用三个指针pre、cur、next轮流推进public ListNode reverseList(ListNode head) { ListNode prev null; ListNode cur head; while (cur ! null) { ListNode next cur.next; cur.next prev; prev cur; cur next; } return prev; }这段代码的核心就一句话在断链之前先保存后继节点。很多人第一次写会把cur.next指向prev之后发现后面的节点找不到了就是因为忘了先用next指针保存。另外要注意反转完之后原来的头节点变成了尾节点它的next要指向null否则会形成环这也是个很容易被忽略的细节。链表题其实没什么玄学就是多练肌肉记忆。我建议你把常见那七八道链表题全部手写三遍以上写到不需要思考就能默写的程度考场上就能腾出脑力去处理更复杂的题。2.2 排序与查找的边界问题排序和查找也是笔试必考的但去哪儿这套题不太会直接让你写个快排或者二分而是喜欢出变体。比如在一个有序数组里查找目标值第一次出现的位置或者旋转数组里查找最小值这些都是在二分查找基础上加了一点花样。二分查找最核心的坑是边界条件。区间到底是左闭右闭还是左闭右开直接决定了while循环条件和mid的更新方式。我自己的习惯是统一用左闭右闭区间也就是while (left right)这样可以少记一套规则public int binarySearch(int[] nums, int target) { int left 0, right nums.length - 1; while (left right) { int mid left (right - left) / 2; if (nums[mid] target) return mid; else if (nums[mid] target) left mid 1; else right mid - 1; } return -1; }这里有个小技巧就是计算mid的时候用left (right - left) / 2而不是(left right) / 2。原因很简单当left和right都很大的时候两者相加可能溢出整数范围虽然笔试环境一般不考这个但面试官看到你能写出这种细节印象分会明显不一样。排序方面快排的Partition操作要能默写因为很多题表面上不是排序题但核心思想就是Partition。比如求数组中第K大的元素最优解就是用Partition做快速选择平均时间复杂度O(n)比先排序再取值的O(n log n)要快一个档次。2.3 动态规划与字符串拉开差距的地方动态规划是笔试题里区分度的分水岭。简单题大家都会写暴力解但优化到DP就不是每个人都能做到了。去哪儿这套题里比较典型的是最长公共子序列、最长递增子序列、编辑距离这类经典DP题。拿最长公共子序列来说状态转移方程是要背熟的dp[i][j] dp[i-1][j-1] 1 (s1[i] s2[j]) dp[i][j] max(dp[i-1][j], dp[i][j-1]) (s1[i] ! s2[j])dp[i][j]的含义是字符串s1的前i个字符和s2的前j个字符的最长公共子序列长度。为什么相等的时候是左上角加一因为这两个字符既然相等就可以接在它们各自前一个字符的最优子序列后面。为什么不相等的时候取左边和上边的最大值因为当前位置至少能继承之前某个方向的结果取其中更优的一个。字符串相关的题除了DP还有KMP这类经典算法。不过说句实在话笔试场上让你手写KMP的概率不高但你要能讲清楚next数组是干什么用的以及为什么KMP能在线性时间内完成匹配。如果你连这个都说不明白那说明你还没真正理解字符串匹配的痛点在哪里。2.4 时间复杂度的敏感度训练编程题之外笔试的选择题里经常考时间复杂度计算比如某个嵌套循环是O(n^2)还是O(n log n)递归的时间复杂度怎么用主定理分析。这些题不难但要求你脑子里有一个复杂度雷达看到一个算法能快速估算它的量级。我见过不少候选人代码能写出来但问复杂度的时候支支吾吾。这在笔试里会比较吃亏因为编程题往往要求你写完代码后说明时间和空间复杂度评卷人会根据这个来辅助判断你的代码是不是最优解。建议平时刷题的时候每做完一道题就顺手记一下复杂度形成条件反射。3. 操作系统与计算机网络选择题里的送分题与陷阱题3.1 进程线程与死锁基础概念别丢分去哪儿这套题的操作系统部分难度不算大基本覆盖了进程与线程的区别、死锁产生的四个必要条件、进程调度算法、内存管理这几块。这些概念属于那种你看了就会不看就懵的内容所以我建议考前集中看一遍性价比很高。死锁这块有个高频陷阱题就是让你判断某个场景会不会死锁或者给一组资源分配情况问是否安全。这就要用到银行家算法的思路。虽然是经典题目但很多人只在书本上看过从来没用过。我教你一个快速判断方法先看还有多少可用资源然后找到一个能跑完的进程把它占用的资源还回去再看能不能继续满足别的进程如果能依次推进到全部完成就是安全状态否则就是不安全状态。进程和线程的区别也是个老生常谈但要注意答题时的层次。很多人只会说进程是资源分配的最小单位线程是CPU调度的最小单位这种答案太单薄。你要补上进程有独立的地址空间线程共享进程的地址空间所以线程间通信更高效但同步更复杂进程切换开销大线程切换开销小。这样一层层递进才能拿高分。3.2 内存管理虚拟内存与页面置换内存管理这块常考的是虚拟内存的作用、缺页中断、页面置换算法。我记得当年有题问LRU和FIFO的区别以及为什么LRU更优但实现成本更高。这块我建议结合Redis的淘汰策略一起理解因为它们道理是相通的。LRU的核心思想是最近被访问过的数据将来也可能被访问所以淘汰的时候选择最久没被访问的那个。FIFO则是先来的先淘汰完全不考虑访问频率容易出现Belady异常——也就是分配的物理页框数变多缺页率反而升高。这个知识点用在Redis面试题里也是加分项。3.3 TCP三次握手与HTTP状态码背也要背得明白网络部分的考点比较固定TCP三次握手和四次挥手是绝对重点HTTP状态码、GET和POST的区别、Cookie和Session的区别也经常出现。这些题不难但容易答得不够深入。比如三次握手很多人能背出SYN、SYNACK、ACK三个步骤但你要能回答两个为什么。第一为什么不是两次握手因为要防止旧连接的请求突然到达服务器两次握手会直接建立连接导致服务器白白分配资源。第二为什么不是四次因为四次有点冗余三次已经能让双方都确认自己和对方的收发能力都没问题。HTTP状态码也会结合场景考比如输入一个网址回车后发生了什么中间会返回哪些状态码。这是典型的HTTP综合题你要能把DNS解析、TCP连接、发送HTTP请求、服务器返回响应、浏览器渲染这一整条链路串起来。实际上这道题在面试中出现频率比笔试还高值得你多花一点功夫。3.4 网络题背后的业务场景说到这儿我想强调一下去哪儿这套网络题不会只考纯理论它更希望看到你联系业务的能力。比如它问你TCP的TIME_WAIT状态如果你能联系到高并发服务器上大量短连接导致的TIME_WAIT堆积问题以及怎么通过调整内核参数来优化那这个答案的含金量就完全不一样了。我当年复习的时候养成了一个习惯每学一个网络协议知识点就问自己一句这个知识点在真实业务里会以什么形式出问题。带着这个问题去学你会发现TCP、HTTP这些协议不再是抽象的概念而是你排查线上故障时手里的一把把工具。4. Java基础与并发编程从源码到底层原理4.1 集合框架HashMap直接决定你的基本功Java基础是去哪儿这类以Java为主要开发语言的公司考察的重头。集合框架里HashMap是绝对的重点几乎每年必考。考察方式也从最初的说下HashMap的结构逐渐升级到了HashMap在并发下会有什么问题、为什么加载因子是0.75这类源码级问题。HashMap在Java 8之后的结构是数组加链表加红黑树。数组是主体链表用来解决哈希冲突当链表长度超过8且数组长度大于等于64时链表会转成红黑树来降低查询时间复杂度。加载因子0.75是个空间和时间的折中调大一点比如1.0空间利用率高了但冲突变多查询变慢调小一点比如0.5冲突少了但浪费空间。并发下HashMap会出问题是因为多个线程同时put时可能触发扩容而扩容过程中链表的头插法在Java 7会导致循环链表CPU直接飙到100%。Java 8改成了尾插法不会再有循环链表问题但数据丢失和size不准确的问题依然存在。所以并发场景要用ConcurrentHashMap。如果你能在答案里把这些演进脉络说清楚面试官基本就能判定你是真的读过源码而不是背了八股。4.2 JVM内存区域与GC线上调优的基础JVM这块考得也很多主要是内存区域划分、对象创建过程、垃圾回收算法和常见收集器。这部分要是只背概念会特别枯燥但你要是能结合一次真实的线上OOM排查经历来讲那效果就完全不一样了。比如题目问堆内存里有哪些区域你要能回答新生代、老年代以及新生代里的Eden区和两个Survivor区还能画出对象从创建到进入老年代的完整流程新对象一般在Eden区分配Minor GC后存活的对象进入Survivor区每次Minor GC年龄加一默认到15岁进入老年代大对象直接进老年代动态年龄判断也可能触发提前晋升。GC算法这块标记-复制适合新生代因为存活对象少复制成本低标记-清除适合老年代因为不需要移动对象但会产生碎片标记-整理则是在清除的基础上解决了碎片问题但移动对象成本高。理解了这些你就能明白为什么HotSpot虚拟机的新生代用复制算法、老年代用标记-整理或标记-清除。4.3 synchronized与volatile并发编程的两个基石并发编程是Java笔试里最容易出错的板块因为它考察的不只是语法还有内存模型和锁机制的理解。synchronized和volatile这两个关键字基本是必问的。volatile有两个核心作用一是保证可见性二是禁止指令重排序但它不保证原子性。很多人不理解为什么不保证原子性我举个例子i这个操作表面上是一行代码实际上是三步——读取i、i加1、写回i。volatile只能保证每一步操作对别的线程可见但三步之间可能被其他线程穿插执行所以最终i的值不会等于期望值。synchronized在Java 6之后经历了锁升级过程从无锁到偏向锁到轻量级锁再到重量级锁。这个升级过程很多人背得下来但不懂其实它是在做一个权衡大部分时候锁竞争并不激烈用CAS这类无阻塞手段就能搞定只有竞争真正激烈时才升级为内核态的互斥锁。你要是能把这个演变逻辑讲明白比单纯背状态名要强得多。5. 数据库与系统设计真正拉开差距的拉分题5.1 一条SQL的优化过程数据库这块去哪儿重点关注的是索引和SQL优化。因为它的核心业务是机票酒店搜索页面上的每个筛选条件背后都是一条或多条SQLSQL写得好不好直接决定了接口响应快不快。经典的考察方式是给出一张订单表让你优化一条慢查询。比如SELECT * FROM orders WHERE user_id 12345 AND status paid ORDER BY create_time DESC LIMIT 20;这条SQL的问题在于如果user_id和status分别建了索引MySQL一般会选择其中一个作为驱动条件然后回表去过滤另一个条件最后还要排序。优化思路是建一个联合索引(user_id, status, create_time)这样可以根据user_id定位到该用户的数据再用status过滤最后索引天生有序create_time直接就能用避免了filesort。这个例子我想说明的是SQL优化不是背几个规则就行的关键是要理解B树的索引结构理解最左前缀原则理解回表和覆盖索引。笔试不会让你现场调优线上SQL但会用题目来检验你有没有这个思维。5.2 缓存穿透、击穿、雪崩缓存三兄弟必须说透去哪儿做搜索业务缓存是绕不开的话题。笔试简答题里如果出现如何设计一个缓存方案或者Redis挂了怎么办本质上就是在考缓存三兄弟穿透、击穿、雪崩。缓存穿透是指查询一个不存在的数据请求直接打到数据库。解决方案有两个一个是布隆过滤器把所有可能存在的数据哈希到一个很长的位数组里查询前先过一遍过滤器如果位数组显示不存在就直接返回另一个是缓存空值即使查不到也把空结果缓存起来但要设置较短的过期时间。缓存击穿是指某个热点key过期瞬间大量请求打到数据库。这个用互斥锁就能解决只有一个请求去数据库加载数据其他请求等待或快速失败。缓存雪崩是指大量key同时过期或者Redis节点宕机导致整体流量打到数据库。解决思路是过期时间加随机值打散以及做高可用集群。这三个概念经常混在一起考答题时一定要先准确说清各自定义再讲解决方案不然容易让评卷人觉得你概念模糊。5.3 手写一个简单的系统设计抢票接口的理想回答有些研发岗的笔试会加一道系统设计题去哪儿这类业务型公司尤其喜欢出。比如让你设计一个抢票接口或者设计一个搜索接口的架构。这种题没有标准答案但有标准的分析路径。我建议你按照以下层次来回答第一层是接口层设计RESTful接口明确入参出参和鉴权方式。第二层是缓存层把热点数据放到Redis里比如航班余票、酒店房态先查缓存再查数据库。要注意设置合理的过期时间和缓存更新策略。第三层是服务层用线程池异步处理非核心流程比如下单后的通知、积分累计通过消息队列削峰填谷。第四层是数据层分库分表应对大数据量订单表按用户ID取模分表历史数据归档到冷存储。第五层是容灾层降级、限流、熔断防止单点故障拖垮整个系统。如果你能在答案里体现出优先保证核心链路可用非核心功能可以降级这种架构思维评卷人就会知道你不只是在背题而是真的思考过系统设计。6. 笔试题复盘与面试准备建议6.1 考场上怎么分配时间才不慌笔试和面试不同没有面试官能看你发挥你面对的是一张卷子和一个倒计时。时间分配非常重要。我的经验是刚拿到卷子先别急着做题花三到五分钟把所有题目快速浏览一遍给每道题标注一个会/不会/模棱两可的标记。会做的题直接先做模棱两可的题放到第二轮完全不会的题放到最后去蒙。千万不要在一道大编程题上死磕超过二十分钟一旦卡住就先做后面的回头再补。编程题哪怕不能写出完整代码也要把思路、数据结构、核心伪代码写清楚评卷人会按步骤给分空着肯定是零分。6.2 那些年考生最容易踩的坑刷了这么多套题我发现有几个错误是考生最容易犯的。第一是审题不清比如题目要求非递归实现结果你写了递归第二是边界条件遗漏比如对空数组、单元素数组、null输入没有处理第三是命名随意变量名全叫a、b、c代码一长自己都看不懂第四是不检查复杂度写了个暴力解还以为是最优解。针对这些坑我建议你在平时练习时就养成三个习惯。一是拿到题目先写注释把输入输出、边界条件、目标复杂度写清楚再动手二是写完代码后习惯性跑几个特殊用例比如空输入、极端值、重复元素三是写完代码后回头看一眼复杂度确认有没有更优解。这些习惯一旦养成考场上会自然带出来帮你避免大量低级失误。6.3 从笔试到面试这道题背后还想考察什么最后我想说一个很多人忽略的点笔试不只是为了筛人它的题目往往就是面试的风向标。你在笔试里做得不好的题面试官很可能会在面试环节追问看看你是真的不会还是紧张发挥失常。所以考完笔试之后千万别把卷子扔到一边。我建议你趁记忆还热着把每道题重新做一遍尤其是错题和犹豫过的题一条条弄明白。这套复盘动作才是笔试提升的关键。你刷一百套新题不如把一套题里所有不会的都彻底搞懂。我见过太多候选人笔试成绩出来后连自己哪些题做错了都不知道面试被问到原题还是一脸懵这就非常可惜了。如果你能通过一套题把相关知识点全部串联起来那这套题的价值就远远超过了它本身的分数。从我个人的备考经验来看去哪儿这套2015年的研发笔试题在今天依然是一套很值得做的训练题。它的特点是不偏不怪核心考点全部落在一个后端研发工程师真正会用到的基础知识上。与其去追求偏题怪题的解法不如把这套题里的每个知识点都学透、写熟、能讲明白。等到面试的时候你会发现自己不是在背答案而是在和面试官聊一个你真的理解的系统。这才是刷题最理想的状态。