拼多多 服务端研发 一面面经:状态机、缓存一致性与并发场景
- 轮次
- 一面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 自我介绍
- 介绍实习
- Spring 状态机是干什么的,为什么要用这个,状态机具体的转移是怎么设计的?
- 服务端版本升级的时候这个状态机怎么办?持久化机制怎么做的?
- 缓存刷新策略怎么做的?怎么保证缓存跟 DB 的一致性?
- 是否使用了本地缓存,QPS 大概是多少?
- 实习的时候团队有多少人?
- 为什么暑期没有转正,老家是哪里的?
- 有没有深入调过 JVM 的参数?
- 讲一个你实际遇到的并发场景,并说一下怎么解决的
- 有没有用过线程池,具体怎么用的?
- 有没有用过消息队列,顺序消费、消息丢失、重复消费这几个问题怎么解决?
- 有没有遇到过 MySQL 特别慢或者超时的问题?怎么定位和优化?
- 实习的时候有没有遇到线上问题,怎么定位和根治的?
- 当时出问题的时候第一时间是怎么做的?
- 如果遇到跟同事理解不一样的情况怎么处理?
- 有没有写过前端代码?
- 了解拼多多的工作时长吗?
- 暑期的时候为什么没来拼多多?
- 求职意向怎么样,怎么排序,比如薪资、城市等?
手撕:LeetCode Hot100 53. 最大子数组和
《参考解析》
-
状态机题先答「为什么用」,再答升级兼容:核心价值是把业务流程显式化成状态、事件、转移三要素,替掉层层嵌套的 if-else,让状态流转可枚举、可校验、可审计;转移设计要说清初始态与终态、事件与守卫条件、每个动作做什么、非法转移怎么拒绝,持久化把当前状态与执行记录落库并配幂等键防重复触发。版本升级时的兼容才是真正考点:状态枚举只增不删,历史状态必须留分支处理,否则老数据一进新代码就成未知状态;新增状态要准备存量迁移与灰度方案,在途任务要么等排空、要么按老版本状态机继续驱动。「状态枚举是持久化数据的一部分,不能随便改」这一层答出来,面试官就知道你真上过生产。
-
缓存一致性:先确认能用 Cache Aside,再谈补偿:主流做法是更新 DB 后删除缓存,而不是更新缓存;进一步可以延迟双删、订阅 binlog 失效、给短 TTL 兜底。本地缓存要额外处理多实例的不一致窗口——主动失效广播或很短的过期时间。被问 QPS 时给出量级、命中率和峰值,比报一个精确数字可信得多。
-
并发场景要挑真事讲,讲清竞态在哪:按「场景与并发点 → 造成的后果 → 用了什么手段(数据库行锁、Redis 原子脚本、CAS、队列串行化)→ 怎么验证」来说。只说「加了锁」不够,要说明锁的粒度和范围、为什么不会死锁、有没有压测或对账验证。
-
线程池要答出参数是怎么推出来的:核心线程数、最大线程数、队列容量、拒绝策略之间的关系(队列一长,最大线程数基本失效)比背参数名重要。业务分 CPU 密集与 IO 密集两类,IO 密集按等待与计算时间之比放大;线上要有监控——活跃线程数、队列堆积、拒绝次数。
-
消息队列三个问题分三处答:顺序消费靠同一业务键路由到同一分区或队列、单分区单消费者;不丢消息看生产端确认与重试、broker 持久化与副本、消费端处理完再提交位点;不重复消费本质是端到端幂等,Kafka 自己保证不了,要靠唯一键、去重表或状态机。先承认「至少一次投递下必然可能重复」,再给幂等方案,是最容易被认可的答法。
-
慢查询定位要报出工具和判断依据:慢日志找出具体 SQL,explain 看访问类型、命中索引、扫描行数和 Extra 里的排序与临时表,再判断是索引缺失、索引失效、回表太多还是深分页。优化手段按代价排序:加或改索引、覆盖索引、改写 SQL、拆大事务,最后才考虑读写分离和分库分表。
-
线上问题的答法分两步:先止损,再根治:第一时间的动作是回滚、降级、限流、切流,保住用户和现场(日志、堆栈、dump),而不是先埋头查原因;之后才是定位、修复、复盘,并把监控告警和预案补上。跟同事意见不一致时,用日志、数据或一次小实验说话,别停在「我觉得」。
-
手撕:最大子数组和:Kadane 一遍扫描,f(i) = max(nums[i], f(i-1) + nums[i]),同时维护全局最大值。注意全负数数组要返回最大的那个负数而不是 0——这是这道题最常见的错。面试时可以先确认要不要返回下标、能不能用额外空间。