免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

京东后台开发面试高频题:Linux、网络、数据库与算法全解析

京东后台开发面试高频题:Linux、网络、数据库与算法全解析 前阵子整理后台开发面经的时候一直有读者让我单独聊聊京东这类大厂的实际考法。很多人刷题刷得很猛但在京东的面试里一个“进程和线程有什么区别”就能把准备不充分的人问得卡壳。原因很简单这类题看似基础面试官却会一直往下追问问到你说不出话为止。今天这篇就围绕京东后台开发面试中常见的 Linux、网络、数据库、算法题做个汇总每题尽量带解题思路有些我会给出可以直接复用的“答题骨架”方便你结合自己的经历去补细节。适合准备后台开发岗、尤其是目标大厂 Linux 服务端方向的同学参考。1. 京东后台开发面试流程与考察重点1.1 面试轮次与整体节奏京东后台开发的面试流程通常情况下是简历筛选、笔试、技术一面、技术二面最后 HR 面。部分部门还会有交叉面或加一轮技术终面但大体节奏是一致的。技术一面以考察基础为主操作系统、计算机网络、数据库、Linux 命令和简单算法题占了大头。技术二面更偏向项目深挖、系统设计思路以及遇到线上问题时的排查能力。我见过不少同学在一面准备得很充分二面反而栽了跟头原因是二面问题没有标准答案面试官会盯着项目里的一个细节反复追问。比如你说自己做过订单超时关闭他就会问延迟队列用的什么为什么不用定时扫表如果 Redis 宕机了怎么办这类问题不是靠背能过关的需要真正理解技术选型的边界和代价。1.2 京东面试官更看重的能力结构从整体反馈来看京东后台开发面试官比较看重三类能力第一是底层原理的理解深度比如问 Linux 的 IO 模型不是让你列几个名词而是要能讲清楚 epoll 的事件通知机制和水平触发、边缘触发的区别第二是线上问题的排查能力比如 CPU 飙高怎么定位、接口变慢怎么排查第三是代码落地能力手写题不一定很难但要求边界处理干净、代码风格清晰。这一点和很多中小厂不一样。中小厂可能更看重项目里用了什么框架而京东这类大厂更想确认你是不是真的理解系统在底层怎么运转。所以我建议准备面试时不要只刷题而是把 Linux 常用命令、网络状态、数据库执行计划这些偏“实战排查”的知识点一起串起来复习。2. Linux 与操作系统高频题从进程模型到 IO 多路复用2.1 进程和线程的区别别只答“资源分配 vs 调度”“进程和线程的区别”几乎是 Linux 后台开发面试的必问题但很多人答得太平淡就说进程是资源分配的最小单位线程是 CPU 调度的最小单位然后停下来。面试官这时候一般不会直接否定你而是追问一句“那这两个本质区别在系统层面体现在哪里”更好的答法是从地址空间、系统资源、切换成本、通信方式四个维度展开。进程有独立的虚拟地址空间一个进程崩了通常不影响另一个进程同进程内的线程共享地址空间、文件描述符表、信号处理器等资源所以线程间通信可以直接通过共享内存完成但也正因为共享一个线程越界写可能把整个进程搞挂。再补充一个实际例子多线程模型在处理高并发 IO 时很常见但线程切换需要陷入内核成本不可忽略。很多高性能服务开始用协程协程是在用户态做上下文切换不需要陷入内核所以切换成本更低。你把这个逻辑讲出来面试官会认为你不是在背概念而是真理解这件事的动机。2.2 僵尸进程、孤儿进程与守护进程怎么处理才算完整这道题京东面试出现过不止一次而且会越问越深。先明确定义僵尸进程是子进程先退出父进程还没有调用 wait/waitpid 回收它的退出状态此时子进程变成了僵尸进程孤儿进程是父进程先退出子进程被 init 进程收养由 init 负责回收。很多同学能说出来但问到“怎么避免僵尸进程”就卡住了。要答好至少覆盖这几点父进程主动调用 wait 或 waitpid子进程退出时给父进程发 SIGCHLD 信号父进程在信号处理函数里调用 waitpid如果父进程不关心子进程退出状态可以用 signal(SIGCHLD, SIG_IGN) 让内核自动回收。这里信号处理的写法实际写代码时要注意异步安全不能在信号处理函数里调用 printf 这类非异步安全函数。还有一种更隐蔽的追问如果父进程自己就是个常驻服务不能阻塞等待子进程退出怎么办常见的做法是让子进程再 fork 一个孙进程然后子进程立即退出这样孙进程被 init 收养由 init 回收父进程不用一直等。这个“两次 fork”的技巧在守护进程设计里也经常用建议准备的时候顺手写一遍。2.3 虚拟内存与页面置换从缺页中断到 swap这道题通常不是孤立问的面试官会从“进程地址空间分布”切入问堆和栈为什么相向生长然后转到虚拟内存。回答时可以抓住一条主线虚拟内存让每个进程觉得自己拥有连续独立的内存空间操作系统通过页表把虚拟地址映射到物理地址访问不存在的页面时触发缺页中断再按需加载。页面置换算法也常考。FIFO 实现简单但可能出现 Belady 异常LRU 是基于局部性原理的经典算法但真正的 LRU 在硬件层面很难精确实现所以操作系统常用 Clock 算法这种近似实现。你要能说出为什么工业场景不用严格 LRU这比单纯背“LRU 是淘汰最久未使用的页面”要加分很多。还有一个和线上排查紧密相关的点swap 使用率。服务内存一直在涨但物理内存还够的时候操作系统可能把一些冷页写到 swap导致访问变慢。排查时可以用cat /proc/meminfo | grep -i swap或vmstat 1看 si/so 列如果 si 和 so 一直非零说明系统正在频繁换页这往往是容量规划出了问题。2.4 select、poll、epoll 的演进逻辑网络编程高频题你在京东面经里几乎躲不掉。很多答案只是罗列区别select 用 fd_set 且默认 1024 限制poll 用 pollfd 数组突破上限epoll 用事件驱动没有上限。这些没错但真正有区分度的讲法是演进的逻辑。select 和 poll 的问题是每次调用都要把全部 fd 从用户态拷贝到内核态内核返回时也不知道哪些 fd 就绪调用方还得 O(n) 遍历。epoll 把整件事拆成了三步epoll_create 创建实例epoll_ctl 注册 fdepoll_wait 等待事件。内核通过红黑树维护注册的 fd用就绪链表记录有事件发生的 fdepoll_wait 返回时只需要把就绪链表里的 fd 拷贝给用户空间所以效率不随连接数线性下降。更进一步面试官通常会追问水平触发和边缘触发的区别。水平触发是只要缓冲区还有数据就会一直通知边缘触发是只有状态发生变化时通知一次。用 epoll 做边缘触发时必须把 fd 设为非阻塞并且一次性把数据读到 EAGAIN否则容易漏数据。这里建议你亲手写一遍 epoll 事件循环面试时说到细节才有底气。2.5 排查 CPU 飙高和性能瓶颈的 Linux 命令这一节属于“面试官不会直接考命令但会在场景题里试探你”的类型。比如他说“线上有个进程 CPU 占用 100%你怎么定位”如果你只回答 top 看一下肯定不够。完整的思路是先 top -H -p 找到具体线程再用 printf 或 gdb 把线程号转成十六进制最终通过 perf top 或 jstackJava 场景定位到热点函数。常用命令里至少要把这几个用熟ps 看进程状态top/htop 看实时负载vmstat 看 CPU、内存、IO 的整体情况iostat 看磁盘读写netstat/ss 看端口和连接状态strace 跟踪系统调用perf 做性能采样。京东这种业务场景下接口慢可能卡在磁盘 IO、网络 IO、锁竞争或 GC掌握命令是一回事能结合现象逐步排除才是面试官真正想看到的。我记得有一个很典型的场景题接口偶发超时QPS 不高但 CPU 也不高你怎么排查这种时候要拓宽思路优先看日志里有没有锁等待、看 MySQL 慢查询、看 Redis 大 key。不能一上来就 top、kill 重启那只是把问题掩盖了。3. 网络与服务端面试题TCP、HTTP、连接池3.1 TCP 三次握手和四次挥手除了状态还要答出“为什么”三次握手为什么不是两次这是很多同学最怕的问题。两次握手的问题在于服务端无法确认客户端的接收能力是否正常。如果客户端发出的 SYN 因为网络延迟重传服务器只收到一个连接请求就建立连接客户端可能根本没有准备好接收数据这时候服务端资源就浪费了。三次握手通过最后一次 ACK 让服务端确认“客户端能收到我发的包”双方收发能力都得到确认。四次挥手稍微绕一点核心是 TCP 是全双工的每一方向都要单独关闭。客户端先发 FIN服务端回 ACK此时客户端不再发数据但服务端可能还有数据没发完所以服务端把数据发完后才发 FIN客户端再回 ACK连接彻底关闭。你能把这个“数据还没发完”的细节讲出来面试官就知道你真理解全双工的含义。同时把状态机带上客户端发 FIN 进入 FIN_WAIT_1收到 ACK 进 FIN_WAIT_2收到服务端 FIN 后进 TIME_WAIT服务端收到 FIN 进入 CLOSE_WAIT发完 FIN 后进 LAST_ACK。TIME_WAIT 是我认为最值得展开的点因为它直接关系到大流量的京东这类场景。3.2 TIME_WAIT 过多怎么处理别急着开 reuse大流量服务经常出现大量 TIME_WAIT 连接很多同学的回答是“开启 tcp_tw_reuse”。这个方向不算错但要分清适用条件。TIME_WAIT 存在的意义是让旧连接的延迟报文在网络中彻底消失避免影响新连接同时确保被动关闭方收到最终的 ACK。排查时先看是主动关闭还是被动关闭。一般来说主动关闭方容易出现 TIME_WAIT如果是服务端主动关闭就要检查是不是代码里每次请求都新建连接没有复用连接池。解决方向优先是让客户端主动关闭或在服务端配置 keep-alive 复用连接减少频繁创建和关闭。至于修改内核参数net.ipv4.tcp_tw_reuse只在客户端视角有效而且要求开启时间戳选项tcp_tw_recycle在 NAT 环境下会产生严重问题很多新版本内核已不推荐使用。你在面试中主动提到 tcp_tw_recycle 的坑比单纯背参数效果要好得多。3.3 HTTP/1.1、HTTP/2 与长连接优化京东的后台开发岗不会只问 TCPHTTP 也是重点。最典型的题是 HTTP/1.1 和 HTTP/2 的区别。HTTP/1.1 的 keep-alive 允许连接复用但队头阻塞仍然存在前一个请求响应没返回后面的请求即使已经发出响应也得排队。HTTP/2 引入二进制分帧和多路复用多个请求可以在同一个 TCP 连接上交错传输理论上解决了应用层的队头阻塞。但这里有个容易忽略的坑HTTP/2 的多路复用没有解决 TCP 层的队头阻塞。如果底层 TCP 丢包整个连接上的所有流都会被阻塞因为 TCP 必须按序交付。到了 HTTP/3 改用 QUIC基于 UDP才把传输层的队头阻塞问题进一步缓解。面试官如果顺着这个思路问下去你能接住就是一次很加分的对话。实际业务中长连接也不是越多越好。连接数太大会占用文件描述符和内核内存一般服务端会设置 ulimit 和连接超时时间。有一个排查经验是ss -s看连接总数ss -tn state established ( dport :443 or sport :443 )看具体端口连接状态能帮你快速定位连接泄漏。3.4 连接池、线程池参数不是拍脑袋定的分布式系统面试里线程池参数算是一个“答得好有亮点、答不好漏洞百出”的问题。例如询问“线程池核心线程数怎么定”如果直接回答“CPU 密集设为 N1IO 密集设为 2N”在京东这种追问下很容易被继续问为什么 IO 密集要设大IO 密集时线程在等待 IOCPU 没有满载多余线程能利用空闲的 CPU 时间片但线程也不是越多越好因为线程过多会导致上下文切换开销增大甚至把 CPU 打满。正确思路是结合业务场景估算。IO 密集场景可以粗略用“线程数 CPU 核数 × (1 IO 等待时间 / CPU 计算时间)”来估算。如果你的服务一半时间在等 Redis 返回一半时间在计算双核机器可以尝试设 4 个左右的线程然后通过压测调优。连接池同理连接数要考虑数据库或下游服务能承受的最大并发不是越大越好。我在面经里经常看到有人被问“连接池设 50 还是 200”答案并不固定但你要能说出自己的判断依据下游服务的 QPS、单请求处理耗时、下游服务单连接吞吐上限这些数凑齐了估算才靠谱。4. MySQL 与 Redis索引、事务、缓存一致性4.1 B 树索引与最左前缀原则MySQL 的 InnoDB 索引题是后台开发必考。先说为什么用 B 树而不是 B 树B 树所有数据都放在叶子节点并且叶子节点之间用链表连接非常适合范围查询和顺序访问非叶子节点只存索引键一次磁盘 IO 能读入更多索引条目树的高度更矮IO 次数更少。紧接着面试官就会问联合索引的最左前缀原则。比如建立 (a, b, c) 联合索引查询条件是 a1 and b2 能用到索引查询条件是 b2 and c3 就不能用。原因不是“口诀”而是 B 树构建时先按 a 排序a 相同再按 b 排序最后按 c 排序。你的查询条件如果跳过了最左列索引的排序结构就没有参考价值了。还要能看懂explain的输出至少知道 key、rows、type、Extra 这几个字段。type 从 all、index、range、ref、eq_ref 到 const越靠右效率越高Extra 里出现 Using filesort 或 Using temporary 通常意味着排序或分组没充分利用索引需要优化。4.2 事务隔离级别与 MVCC为什么 MySQL 默认 RR事务的 ACID 一般都能背关键在于隔离级别。读未提交有脏读问题读已提交解决了脏读但存在不可重复读可重复读解决了不可重复读串行化最安全但性能差。MySQL InnoDB 默认是可重复读这和很多其他数据库默认读已提交不太一样你要能解释为什么。InnoDB 用 MVCC多版本并发控制实现非锁定读。每行记录有隐藏列记录创建版本号和过期版本号事务读取时根据当前事务版本快照判断哪些版本可见所以读操作不会被写阻塞。可重复读通过快照读保证同一个事务内多次查询看到相同数据同时用 next-key lock 解决幻读。但注意MySQL 的可重复读在快照读下能防止幻读如果走的是当前读比如select ... for update仍然需要 next-key lock 来锁住范围。能够区分快照读和当前读是这道题的隐藏考点。4.3 Redis 数据结构与内存淘汰Redis 面试题几乎每场都有。首先是支持的数据结构string、hash、list、set、zset以及 HyperLogLog、Bitmap、Geo 等扩展结构。要能说清楚每种结构适合什么业务。比如 zset 适合排行榜hash 适合存对象字段list 适合消息队列的临时存储。接着是过期删除和内存淘汰。Redis 的过期删除策略是惰性删除加定期删除结合。只靠惰性删除会导致过期 key 一直占内存只靠定期删除又难控制频率所以两者配合。内存淘汰策略有 noeviction、allkeys-lru、volatile-lru、allkeys-random 等。如果问你怎么选一般业务场景选 allkeys-lru因为热点数据通常会重复访问LRU 能保留热点但如果业务有 cache aside 的强一致需求可能要考虑 noeviction 加监控报警。最后很多人忽略的一点value 过大会成为大 key。大 key 会导致 Redis 阻塞、内存不均、迁移超时。你在面试中说自己会用redis-cli --bigkeys扫描大 key并会对大 key 做拆分或压缩这种实战细节非常加分。4.4 缓存穿透、击穿、雪崩与一致性这道题是京东后台开发的“常青树”。缓存穿透指查询一个不存在的数据请求直接打到数据库。解决方式第一是缓存空值并设置短暂过期时间第二是用布隆过滤器先过滤肯定不存在的 key。布隆过滤器有误判率要结合业务决定是否接受。缓存击穿指某个热点 key 失效瞬间大量请求同时穿透到数据库。解决思路是互斥锁重建缓存或者让缓存不过期后台异步更新。缓存雪崩是大量 key 在同一时间失效或者 Redis 本身宕机。前者用过期时间加随机值分散后者用高可用集群加降级方案。缓存一致性是更进阶的问题。常见做法是 Cache Aside Pattern读的时候先读缓存读不到读数据库再回写缓存写的时候先更新数据库再删除缓存。删除缓存失败要用重试机制或监听 binlog 异步删除。这里最好不要说“延迟双删”是银弹要强调最终一致性和补偿机制才是核心。5. 算法手撕题与题解复盘5.1 反转链表迭代、递归都要会反转链表是后台开发手写题里出现率极高的一道。别看简单面试官会要求你写出无 bug 的代码并且解释递归的调用栈过程。迭代写法核心是三个指针prev 指向前一个节点curr 指向当前节点next 暂存下一个节点循环里让 curr-next 指向 prev再整体后移。边界要注意循环结束后 prev 是新头节点curr 是 nullptr。递归写法稍微难理解一点。假设 reverseList(head-next) 已经返回反转后的新头此时 head-next 仍然指向原来的第二个节点而这个节点的 next 还指向 head所以需要执行 head-next-next headhead-next nullptr最后返回 newHead。很多同学写递归会漏掉 head-next nullptr这样链表会成环面试官马上就看出来了。京东的算法题有时不会直接考反转链表而是考变体比如反转链表前 N 个节点、按 K 个一组翻转。建议把 LeetCode 25 题 K 个一组翻转链表也刷一遍关键是递归处理每一组的头节点。5.2 LRU 缓存别只会用 LinkedHashMapLRU 缓存设计是面试官非常喜欢的手写题因为它同时考察数据结构和工程意识。最经典实现是哈希表加双向链表哈希表保证 O(1) 查找双向链表保证 O(1) 插入和删除。get 时把访问到的节点移到链表头部put 时如果 key 存在就更新并移到头部如果容量满了就删除链表尾部节点并移除哈希表映射。如果你直接用 LinkedHashMap虽然能通过但最好说清它内部原理accessOrder 为 true 时每次访问会把节点移到链表尾部而链表头部就是最近最少使用的节点。Java 里 removeEldestEntry 控制淘汰逻辑。能讲明白这一步面试官会认为你是理解机制而不是只会调用。C 面试里则常让你手写推荐用 unordered_map 加 list 迭代器。这里有个小细节list 迭代器存的是 pairint, int更新 value 时不要删除重建节点直接通过迭代器修改否则迭代器失效会出问题。边界条件测试时至少要覆盖容量为 1、重复 put 相同 key、get 不存在的 key。5.3 遇到没准备过的题怎么现场推演面试手写题最怕的不是难度而是“没见过”。我之前也踩过坑一看到陌生题就开始慌代码写一半发现思路不对。后来总结了一个比较稳妥的方法先和面试官确认输入和输出范围比如数组长度、数据量级、是否有序、是否有负数这些信息直接影响算法选择。第二步是暴力解。哪怕是 O(n^2) 的暴力方案也可以先说出来再一步步优化到 O(n log n) 或 O(n)。面试官通常更看重你的思考链条而不是直接给最优解。如果长时间没有思路可以主动说“我先从暴力解法开始分析瓶颈后尝试优化”这比干等要强很多。第三步是举小例子。在纸上写一个长度为 5 的小数组手动走一遍过程通常能帮你看清规律。比如遇到“最长连续序列”这类题先推一遍你很容易发现可以用哈希表去重并只从连续序列的起点开始向外扩展复杂度就从 O(n^2) 降到 O(n)。6. 项目深挖与 HR 面收尾经验6.1 用 STAR 结构讲项目别把面试官绕晕京东二面开始前面试官一般会直接说“你先介绍一个项目”。不少人的介绍方式是流水账我们项目用了 Spring Cloud有网关、有注册中心、有配置中心我负责订单模块。这样讲完面试官不知道你的角色也不知道项目难点在哪里。比较稳妥的是 STAR 结构Situation 是背景Task 是你负责的任务Action 是你具体做了什么Result 是最终效果和数据。讲项目时优先选有量化结果的项目比如接口耗时从 200ms 降到 50msQPS 从 1000 提升到 5000。如果没有这些数字也要说明优化的判断依据是什么否则听起来像在虚构。容易被追问的点也要提前准备你项目里 Redis 挂了会怎样数据库慢查询怎么优化消息丢失有没有补偿机制这些问题都不要求你答得完美但要有自己的思考。我在面经里看到太多人项目讲得很漂亮一被追问就支支吾吾最后毁在“数据可靠性”这类基础问题上。6.2 反问环节问什么才显得有准备HR 面或技术面最后面试官常会问“你有什么想问我的”。最忌讳的是说“没有”这会让对方觉得你对应聘岗位没有热情。但也不要上来就问薪资和加班情况这些更适合在 offer 谈判阶段问。技术面反问可以问团队技术栈和业务规模比如“团队现在主要用什么语言做后台服务”“线上 QPS 大概什么量级”“对新人有什么培养路径”。这既展示你对职位有真实兴趣也能帮你判断岗位是否适合自己。HR 面反问可以问“团队目前最需要解决的技术问题是什么”或者“这个岗位未来半年内最重要的目标是什么”。我的体会是反问环节不需要刻意表现真诚地问一个你真正关心的问题比背出来的“完美问题”自然得多。面试官都是老手一眼就能看出来你是走流程还是真的想了解团队。还有一个小建议每次面试结束后把被问到的问题按“掌握牢固、答得一般、完全不会”分类记录下来三天内把不会的题目补一遍。面经的意义不在于背题而在于通过一轮轮复盘把自己的知识盲区一个个填掉。到最后你会发现面试不再是对抗而是一次次验证自己系统能力的机会。
返回列表