
最近整理了一份某老牌互联网公司Java后端社招的面试实录发现不少题目其实没有想象中那么玄。整个过程大概是简历筛过后两轮技术电话面接着现场三面最后HR面收尾。这份面试名单里的题目和答案非常适合准备社招的同学对着复习它把Java并发、JVM、MySQL、Redis、系统设计和HR高频问题都串了一遍。先给一个结论社招和校招最大的不同是面试官高频地拿“生产场景”来追问。知识点光会背不行你得把思路落到“线上出了问题怎么排查、方案之间怎么取舍、性能指标怎么证明”上面。这篇文章我会按面试的真实节奏来写把高频题目和参考答案拆开讲也把我在准备过程中踩过的坑一并说出来。1. 社招Java面试的整体节奏与考察逻辑1.1 社招和校招的考察点差异社招面试尤其Java后端岗位上来很少让你背“和equals区别”这种基础题面试官默认你已经写过几年代码再问八股文没有意义。他们要验证的是你有没有独立解决过线上问题、能不能把一个方案讲清楚、出了故障会用什么手段定位。我自己有个深刻体会同样问HashMap校招可能问“底层结构是什么”社招会追问“JDK 7和JDK 8的并发问题有什么区别你线上遇到过ConcurrentModificationException吗后来怎么处理的”。如果只背过Java Guide没有真实场景很容易卡在第二层。所以准备社招第一条原则是把每一个知识点还原到场景里。你要能回答“什么情况下用它”“不用它会怎样”“出了问题怎么监控和恢复”。能做到这三层回答面试官的印象分会明显不一样。1.2 通用面试流程与各环节准备重点不同团队面试轮次会略不同但大厂社招基本逃不出这个框架阶段主要考察内容常见时长准备重点简历筛选工作年限、项目方向、技术栈匹配不一定有面试按岗位JD改简历突出指标技术一面Java集合、并发、JVM、基础算法60-90分钟高频八股手写题要能讲场景技术二面MySQL、Redis、消息队列、项目深挖60-90分钟结合项目讲选型不能只背概念交叉面/终面系统设计、工程规范、抗压能力45-60分钟准备一道完整的系统设计题HR面稳定性、沟通、薪资、离职原因30-40分钟表达稳不贬低前公司一面和二面最容易淘汰人。一轮挂往往不是因为你不会某个冷门知识点而是“追问两轮就答不上来”或者“只会名词解释”。职场里有个说法社招面试是把你放到一个虚拟项目组里面试官假装你是同事问“你负责的这个模块出问题了怎么办”。所以不要背题库把思路练顺。还有一点容易被忽略算法题在Java后端社招里占比不高但会出1-2道中等题比如LRU缓存、Top K、链表反转。这类题不刷不行但也不用All in LeetCode题海。每天保底两三道保持手感就够了。2. 基础题最容易被“连环追问”集合框架与并发编程2.1 HashMap和ConcurrentHashMap的底层原理这几乎是我见过最不会缺席的Java面试题。面试官通常先问HashMap再问并发安全自然引出ConcurrentHashMap。HashMap要答到这些点JDK 8底层是数组链表红黑树默认容量16负载因子0.75扩容时容量翻倍。0.75是空间利用率和冲突概率的折中。太高容易频繁冲突太低浪费空间。哈希方法会做高低位异或扰动让key的哈希值分布更均匀。链表长度超过8且数组容量大于等于64时链表转红黑树否则优先扩容。JDK 7扩容时采用头插法并发场景可能形成循环链表导致get死循环JDK 8改成尾插死循环问题解决但并发下仍可能丢数据所以HashMap不适合做共享状态。面试官真正想听的不是你背出“链表转红黑树阈值是8”而是你知道为什么要这样设计。如果被问“为什么阈值是8”可以说哈希碰撞服从泊松分布桶内链表长度到8的概率已经极低转红黑树是为了兜底。ConcurrentHashMap是重点。JDK 8版本抛弃了JDK 7的Segment分段锁改成CASsynchronized锁住桶头节点。这样做的好处是锁粒度更细内存占用更低。size()统计时不是严格精确的它通过baseCount和CounterCell累加保证了弱一致性。很多人容易在这里翻车因为会把“ConcurrentHashMap是弱一致性的”理解成“不安全”需要解释弱一致性是针对迭代器、size、get等操作不代表并发写会丢数据。如果你想展示深度可以主动提一句ConcurrentHashMap在扩容时有一个协助扩容机制多个线程可以一起搬运桶节点减少扩容造成的停顿。这种细节会让面试官觉得你真的看过源码而不是只看过博客。2.2 volatile与synchronized内存屏障与锁升级并发题第二个高频点是volatile。基础定义是三个保证可见性、禁止指令重排序、不保证原子性。但面试官不会满足于定义通常会追问“底层怎么实现的”。volatile实现可见性靠的是内存屏障。JVM在volatile写操作前后插入StoreStore、StoreLoad屏障强制把工作内存中的最新值刷回主内存读操作前插入LoadLoad、LoadStore屏障使线程从主内存重新读取。简单说volatile就是让多线程之间看到同一个“最新版本”。经典题目是双重检查锁单例public class Singleton { private static volatile Singleton instance; public static Singleton getInstance() { if (instance null) { synchronized (Singleton.class) { if (instance null) { instance new Singleton(); } } } return instance; } }为什么这里必须加volatile因为new Singleton()不是原子操作它包含分配内存、初始化对象、把引用指向内存三步。JVM可能对这三步进行重排序导致另一个线程拿到一个“引用已经赋值但对象还没初始化完”的半成品。volatile禁止了这种排序保证拿到的一定是完整对象。synchronized也要准备升级路径。JDK 6之后synchronized不再是“重”锁锁有四种状态无锁、偏向锁、轻量级锁、重量级锁。竞争不激烈时偏向锁会把线程ID记录在对象头的Mark Word里一旦有竞争升级为轻量级锁通过CAS抢锁抢不到或等待时间过长升级为重量级锁涉及操作系统互斥量。常被追问的还有“synchronized和ReentrantLock怎么选”。可以这样答synchronized用法简单JVM自动加锁解锁ReentrantLock支持可中断、超时、公平锁、多个Condition条件变量。如果只是方法级同步优先选synchronized如果需要做复杂的并发控制比如“等待超时返回”或“读写分离”用ReentrantLock更合适。2.3 线程池的7个参数为什么说这是必考题线程池在我经历的技术面里几乎是100%出现的。而且面试官喜欢给各种组合比如“核心线程数是5、最大线程数是10、队列容量是100现在来了50个任务会新建线程吗”这种问题稍微犹豫就可能答错。线程池七个参数先背熟corePoolSize核心线程数。maximumPoolSize最大线程数。keepAliveTime非核心线程空闲存活时间。unit存活时间单位。workQueue等待队列。threadFactory创建线程的工厂。handler拒绝策略。任务提交后的执行流程是当前线程数小于corePoolSize优先新建线程执行任务。线程数已经达到corePoolSize任务放进阻塞队列。队列满了并且线程数小于maximumPoolSize继续新建线程。队列满了线程数也到了maximumPoolSize触发拒绝策略。很多人会记混第三步。记住一个口诀只有队列满了才会去创建非核心线程队列没满系统会认为还能缓冲不会把线程数往上提。四种拒绝策略也要能说清楚AbortPolicy抛异常DiscardPolicy直接丢弃DiscardOldestPolicy丢弃最老任务CallerRunsPolicy让提交任务的线程自己执行。实际工程里我比较喜欢CallerRunsPolicy因为它在任务过多时会产生“反压”让上游线程自己去跑任务等于自动限流。回答线程池参数时最好能补一句参数估算思路。CPU密集型任务核心线程数可以设为CPU核数1避免过多线程切换IO密集型任务可以设成2倍CPU核数或者用公式线程数CPU核数×(1等待时间/计算时间)。最后再补一句不要用Executors提供的便捷工厂方法因为newFixedThreadPool队列是无界的任务堆积会导致内存膨胀newCachedThreadPool最大线程数是Integer.MAX_VALUE极端情况会创建大量线程拖垮机器。3. JVM与故障排查贴近生产才有说服力3.1 类加载机制与双亲委派的一个经典坑类加载机制属于JVM高频基础题但社招里更常见的是“你遇到过哪些类加载问题”的追问。先答标准流程类加载分为加载、验证、准备、解析、初始化五个阶段。双亲委派模型指的是如果一个类需要被加载会先让父加载器尝试加载父加载器无法加载时才由自己加载。从下往上查找从上往下尝试。这样设计是为了避免核心类比如java.lang.String被用户自定义的类替换掉。面试官如果深挖会问“什么场景下需要打破双亲委派”。可以从SPI机制讲JDBC驱动是接口定义在JDK里但实现类是第三方提供的引导类加载器加载不了只能通过线程上下文类加载器来加载。Web容器也需要打破双亲委派因为同一个Tomcat里可能部署多个应用它们依赖同一个类的不同版本。之前帮甲方查过一个NoClassDefFoundError问题应用启动正常运行到某个接口才报找不到类。最后用-verbose:class看加载日志才发现是依赖冲突把一个旧版本的类先加载了。生产环境遇到类似问题不要先猜代码去看依赖树排查排重多数情况不是代码写错而是ClassLoader加载了错误版本。3.2 垃圾回收器选型与GC日志分析JVM必考题之二就是垃圾回收。主线是分代收集、GC Roots、垃圾回收器演进。G1是目前很多互联网公司的默认选择它把堆拆成大小相等的Region维护一个优先列表后台线程会优先回收回收收益最大的Region所以能实现可预测的停顿时间。ZGC更进一步利用染色指针和读屏障实现了超低停顿适合超大堆场景。回答时不必把所有参数都背下来但要说清适用场景低延迟场景选G1或ZGC超大堆选ZGC追求吞吐量可以考虑Parallel ScavengeParallel Old。我从实际调试中总结了一个经验矩阵现象可能原因排查方向业务接口偶尔卡顿Young GC停顿偏长看Survivor空间、动态年龄判断CPU飙升且Full GC频繁内存泄漏或大对象过多jstat观察GC次数jmap导dump老年代持续增长不下降对象无法被回收MAT分析Dominator Tree频繁创建临时对象代码存在大量字符串拼接检查循环里的操作JVM参数不需要背全但至少要熟悉这些常用项-Xms、-Xmx、-XX:NewRatio、-XX:MaxGCPauseMillis、-XX:HeapDumpOnOutOfMemoryError。如果在面试中提到“线上我加过-XX:PrintGCDetails结合GC日志定位过Full GC”含金量会高很多。3.3 OOM排查的一次真实复盘带步骤与命令有一年在做一个批量审批系统时晚上跑批任务把测试环境内存打爆了接口全部超时然后出现java.lang.OutOfMemoryError: Java heap space。那次排查过程很有代表性。第一步保现场。启动参数提前加好-XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/data/logs/heap.hprof虽然理解出错时才会生成dump但这样能保住第一手现场。第二步看日志。项目日志和错误日志同时看错误日志里有没有明显的循环、大集合、文件读取输出先定位个大概。第三步统计GC情况。用jstat -gcutil pid 1000 5看Eden和老年代使用情况。如果Full GC频繁且每次回收后内存下降不大说明老年代里积累了无法释放的对象。第四步分析dump。用MAT打开heap.hprof看Dominator Tree找到占用内存最大的对象路径。那次定位到一个存储审批意见的ArrayList里面有几十万个对象原因是代码一次性把所有审批记录load进内存再做聚合写完redis后list没有被及时释放。修复方案很简单改成批次读取每500条处理一次并且把list的作用域缩小。这里面最值得学的一课是OOM不一定都是“内存不够”更多时候是代码在错误的地方加载了过多数据。回答时如果能说出一个类似的完整案例面试官会认为你真的在线上待过。4. 数据库与中间件业务体量越大越爱考这些4.1 MySQL索引失效场景与最左前缀MySQL几乎是后端岗位的标配索引是必考项。最少要讲清楚三个点InnoDB为什么用B树、最左前缀、索引失效场景。InnoDB的聚簇索引就是主键索引叶子节点存完整行数据二级索引叶子节点存主键值。所以通过二级索引查询要先回表才能拿到完整数据。B树为什么合适它矮胖三层就能存上千万数据磁盘IO次数少叶子节点有双向链表适合范围查询。很多同学会被问到“为什么不选红黑树”因为红黑树高度高磁盘IO次数多MySQL底层是磁盘存储必须控制IO。联合索引要背熟最左前缀规则建立索引(a,b,c)查询条件必须包含a才有机会走到该索引只有b和c是走不了的。类似地如果你跳过a直接查c索引也会失效。常见失效场景列出来对索引列使用函数比如where DATE(create_time) 2024-01-01。隐式类型转换比如where mobile 13800138000mobile是varchar这里会发生类型转换。左模糊like %abc因为B树只能按前缀匹配。or条件里包含了非索引列。对索引列做了计算比如where id 1 10。排查时用EXPLAIN看type从高到低是const、eq_ref、ref、range、index、ALL。出现ALL说明全表扫了。Extra里有Using filesort通常意味着排序没走索引也该查查。实际开发里我踩过一个坑给一个表同时建了(a,b)和(a)两个索引。结果(a)是完全冗余的因为(a,b)已经能够覆盖所有以a为前缀的查询。冗余索引不仅浪费磁盘还拖慢写入。后来清理掉写入性能提升明显。这一条建议在项目里复盘时好好过一遍。4.2 事务隔离级别与MVCCMySQL隔离级别是必背项但容易被追问的是MVCC实现。四个隔离级别先过一遍Read Uncommitted能读到未提交数据有脏读问题。Read Committed只能读到已提交数据解决脏读但不可重复读。Repeatable Read同一个事务内多次读取结果一致InnoDB默认级别可防止大部分幻读。Serializable完全串行性能低。MVCC是InnoDB实现快照读的机制。每一行隐藏着两个字段最近修改事务ID和回滚指针。事务开启时系统会生成一个read view记录活跃事务列表。通过对比事务ID决定当前事务能看到哪个版本的数据。面试官最爱问的是RR级别下快照读和当前读分别怎么防幻读。快照读靠MVCC读的是某个历史快照当前读比如select ... for update靠的是临键锁也就是记录锁加间隙锁把要读的区间锁住让其他事务无法在这个区间插入新数据。所以“RR能防幻读”并不是绝对靠MVCC得说清楚。实际业务里我倾向用乐观锁来避免大量行锁竞争。比如秒杀扣库存更新语句加条件stock 0或者维护一个version版本号更新时比较版本一致才成功。这类答案能让面试官看到你不是只会背隔离级别。4.3 Redis真的只是缓存吗数据一致性是个深水坑Redis在社招面试里的占比不亚于MySQL而且很多问题都围绕“缓存和数据库一致性”展开。先给基础答案Redis是内存数据库但生产环境推荐开启AOF追加写加RDB定期快照防止重启丢数据。持久化策略不是默认的要结合业务容忍度配置。缓存一致性最经典的是Cache Aside模式读的时候先读缓存读不到再读数据库然后把数据写回缓存写的时候先更新数据库再删除缓存。为什么先更新数据库而不是先更新缓存因为写数据库和写缓存两个操作不可能做到原子单向操作都有窗口期。先更新数据库再删缓存至少能保证缓存里的数据是旧值时会等下一次读请求回源更新如果要先更新缓存万一数据库更新失败缓存里的新值就污染了。如果被追问“删缓存失败了怎么办”可以答删除失败可以通过消息队列异步重试不要在主链路里反复重试。进一步还可以说延迟双删先删除缓存等一两秒再删除一次。这个方案能覆盖读请求在删除缓存期间把旧值写回缓存的极端情况。缓存穿透、击穿、雪崩这三个兄弟也要准备穿透查询一个不存在的key每次都打到数据库。解决布隆过滤器拦截或者把空值也缓存起来。击穿某个热点key过期瞬间大量请求直达数据库。解决热点key不过期或者用互斥锁只让一个线程去重建缓存。雪崩大量key在同一时间过期或者Redis实例故障。解决过期时间加随机数加缓存网关降级和熔断。面试题如果问到“Redis为什么快单线程还好用”可以答Redis核心是事件循环单线程避免了锁竞争和上下文切换同时基于内存的数据结构操作非常快。注意现在Redis 6之后引入多线程IO但命令执行仍是主线程。这个补充很加分。4.4 消息队列、分布式锁与幂等性中间件题目最容易把基础不牢的人筛掉。高频问题大概四类消息不丢失、重复消费、顺序消息、分布式锁。消息不丢失要分三个环节看。生产者发送消息要开启ack确认发送失败重试Broker收到消息后要落盘持久化再返回成功消费者拿到消息处理完业务逻辑后再手动提交offset不能先提交后处理否则处理过程中宕机就会丢消息。重复消费不可避免唯一的解法是让消费者具备幂等性。常见做法是消费端搞一张去重表用消息唯一ID做唯一索引插入失败说明是重复消息直接返回成功。这个方案比较简单也比较通用。分布式锁的经典方案是Redis的setnx带过期时间但必须带唯一value防止误删别人的锁。举例线程A拿到锁执行时间超过过期时间锁自动释放线程B拿到锁此时A执行完调用del会把B的锁删掉。所以删除锁之前要先比对value是自己的才能删用Lua脚本保证原子性。更强的方案是使用ZooKeeper临时顺序节点锁挂在有序节点上最小节点的线程拥有锁会话断开节点自动消失。但ZooKeeper性能不如Redis适合对一致性要求更高的场景。消息顺序的问题通常应对方式是让同一个业务key进同一个队列。比如订单号取模分发保证同一个订单的所有消息按顺序消费。面试官如果继续追问“全局顺序怎么办”说实话绝大多数业务不需要全局顺序强行全局顺序会让系统可用性大幅下降。能够说出这种取舍比硬背方案显得更有经验。5. 系统设计题不是让你写架构而是看你怎么拆解5.1 一道经典设计题秒杀系统的拆解思路系统设计题在社招终面出现概率极高。不用慌它没有唯一答案但考察点很明确需求分析、方案边界、核心链路、异常兜底。以秒杀为例面试官会说“10万用户同时抢1000件商品你会怎么设计”。不能上来就画个Spring Boot架构要把问题拆开。第一步问清楚需求。有多少真实并发是否需要登录是否可以预扣库存订单多久超时释放这些不确认后面的方案都是空中楼阁。面试官不会反感你提问反感的是你什么条件都不问就开始背方案。第二步定核心链路。前端做秒杀按钮置灰、限流网关层做IP和用户维度的限流核心服务用Redis的Lua脚本原子扣减库存库存扣完了直接返回“已售罄”扣减成功的请求投递消息队列下游消费后异步创建订单数据库来一条“库存和订单状态”的最终一致性落库防止把数据库压垮。第三步讲防超卖。库存放在Redis里扣减用Lua脚本保证原子性。数据库层面更新库存时加条件stock 0。两条都做才叫保障。第四步讲风险兜底。如果用户下单后一直不支付库存要释放所以订单要设置超时自动关闭。如果Redis或者消息队列故障要有降级方案比如关闭秒杀活动或者改为排队模式。最后再说监控秒杀接口的成功率、扣减耗时、订单积压量都要有告警。秒杀这类题主要看你会不会“削峰填谷”。流量进系统后同步处理会拖垮所有下游所以需要用消息队列把高峰削掉把单量填平。能主动说出这个思路过关概率会大幅提升。5.2 从提问方式看面试官想听到什么系统设计题里面试官不关心你画的架构图多漂亮更关心三个点有没有先定义约束。比如“库存可以超卖吗”“支付是异步还是同步”“数据一致性要求是什么”。能不能识别瓶颈。比如知道Redis是缓存还是数据源消息队列积压会不会导致下游雪崩。有没有容灾兜底。限流、降级、熔断、超时处理这些是不是主动想到的。很多人一开口就是“用Redis缓存商品、用MQ异步下单”但没有说明“为什么用Redis而不是本地缓存”“为什么扣库存不在数据库做”。面试官会追问取舍。这时候要把自己的选择权解释清楚Redis抗高并发去重和扣减MySQL只做最终落库这样才能既保证性能又保证稳定。我在准备系统设计题时总结了一个模板先确认规模再设计存储再定义接口再画主流程最后谈失败预案。这个顺序背下来任何设计题都能套。套完之后记得说一句“这个方案在一致性上牺牲了什么换来了什么”这会让面试官觉得你有架构思维。6. 软素质与HR面社招翻车最多的不是技术6.1 如何讲清楚项目STAR法则在面试中的用法我见过不少技术不错的候选人程序员表达项目时一塌糊涂。典型说法是“我负责订单模块用了Spring Cloud和Redis解决了高并发问题”。面试官听完根本不知道你具体干了什么。面试官最怕的事情是不确定项目经历是不是你真实做过。因为一旦项目是你实际做的细节一定经得起追问。所以讲解项目的核心原则是让逻辑链条完整闭合让每一个技术决策都有原因。我推荐用STAR法则组织Situation项目背景用户量级、访问量、团队构成。Task你承担的任务是性能优化、架构升级还是新功能开发。Action具体方案以及为什么选这个方案。要说明对比过哪些备选方案。Result量化结果比如接口耗时降低了多少、QPS提升到多少、错误率下降了多少。一个合格的表述长这样“当时订单系统大促期间接口平均响应时间到了800ms经常报警。我负责优化下单主链路对比了同步扣库存和Redis预扣库存两个方案最终选择Redis Lua脚本预扣消息队列异步建单。压测结果接口从800ms降到120ms错误率从0.5%降到0.02%。”这里有一个提醒量化数据一定不要编。如果面试官顺着你的数据追问“压测是怎么做的并发量多少有没有做长稳测试”你编出来的一定会露馅。可以留20%的模糊空间但核心数据要真实。6.2 HR面高频问题背后的考核点HR面虽然不考技术但每年都会有人挂在最后一步。HR主要看三个东西稳定性、沟通、期望值。“为什么辞职”这个问题错误回答是“前公司技术太烂”“领导不行”“加班太多”。正确思路是强调个人成长诉求希望接触更大体量业务、更复杂的技术挑战。HR不关心前公司如何只关心你现在是否带着负面情绪。“未来3年规划”也是一个必问题。不需要说得多宏大但要说清楚是走专业路线还是管理路线。大多数Java后端岗可以答“希望深耕分布式系统和高并发方向逐步成长为能带项目的技术骨干”这个回答既具体又不越界。“能接受加班吗”要谨慎回答。太绝对“可以”显得没底线太强硬“绝不”又显得不稳定。可以答“可以接受业务节奏需要时的加班但不接受无意义内耗”。这个度比较符合大多数公司的实际状态。薪资问题不要给一个死数字可以说“综合目前薪资和岗位情况期望涨幅在X%-X%之间最终可以沟通”。如果HR问“上一家多少钱”可以含糊说“按年包算包含奖金”不用把每个月拆得太细。重点是态度坦诚不虚报。7. 备战时间线、刷题策略与避坑经验7.1 一个月冲刺计划怎么安排我建议把准备周期压缩到三到四周太长容易疲惫太短来不及梳理。时间核心任务每日投入产出物第一周整理项目经历刷算法高频题2-3小时三个可讲的项目故事算法题约30道第二周Java并发、JVM、MySQL、Redis2-3小时一份自己的面试速记按标题整理第三周系统设计模拟面试2小时一道秒杀和一道消息幂等设计稿第四周投递简历、真实复盘视进度每场面试记录查漏补缺算法不用贪多。LeetCode按类型刷链表、二叉树、字符串、动态规划基础、栈队列每种刷十道左右再刷几道高频考题比如LRU、合并区间、两数之和。遇到不会的看完题解后自己默写一遍效果比刷三遍看得多要好。模拟面试一定要做。找朋友扮演面试官把项目故事按时间线讲一遍。压测阶段可以录音回放很多“嗯”“然后”“那个”的口头禅自己回听一遍才知道有多影响表达。7.2 我在面试后总结的6条避坑清单第一简历不要写“精通”。写“熟悉”和“深入理解”比较稳妥一旦写了精通面试官就会往死里问直到问倒你为止。第二不会的问题不要乱编。可以说“这个细节我不确定但根据我的了解大概是XX方向我会在确认后回补”。面试官更看重诚实和推导能力而不是看你怎么圆谎。第三算法题一定要先写边界条件。有一次我写二叉树递归没判空直接空指针。后来所有递归题我都习惯第一步先把rootnull处理掉。第四项目里的量化指标要经得起推敲。面试官追问“QPS怎么测出来的”你不能只回答“压测看到的”最好能说出工具、压测模型、服务器配置。第五面试最后一定要反问。不问问题会显得没有主动思考。可以问“这个团队当前的技术挑战是什么”“系统现在的核心矛盾是稳定性还是迭代速度”既能判断公司现状也能展示思考深度。第六每场面试后做复盘。把被追问住的问题记下来整理成“追问陷阱”清单。有一次我连续两场都在同一道缓存一致性问题被追问到卡壳复盘后把“延迟双删、失败重试、最终一致”这个回答链路练顺下一场就变成了送分题。回头再看这份面试记录我最大的体会是面试不是考你会不会背而是考你能不能像同事一样沟通。一个知识点如果能从用法讲到原理再讲到生产事故面试官自然会觉得你是“干过活的人”。这套方法不仅仅适用于那一家公司任何互联网大厂Java后端岗都可以按这个思路去准备。