美团后端开发面经(2024 秋招)
岗位:后端开发工程师(到店事业群 - 美食业务部)
背景:985 本科 + 硕士,主语言 Java,一段美团暑期实习(日常)
结果: offer,评级 L4
时间线:8.15 投递 → 8.22 一面 → 8.29 二面 → 9.5 三面(HR 面同步进行)→ 9.12 offer
一面(技术基础,1h)
一面面试官是组内的技术骨干,风格务实,问题环环相扣。
算法题(25min)
LeetCode 76. 最小覆盖子串
给定一个字符串 s 和一个字符串 t,返回 s 中涵盖 t 所有字符的最小子串。
from collections import Counter
def minWindow(s: str, t: str) -> str:
need = Counter(t)
window = Counter()
valid = 0
left, right = 0, 0
start, length = 0, float('inf')
while right < len(s):
c = s[right]
right += 1
if c in need:
window[c] += 1
if window[c] == need[c]:
valid += 1
while valid == len(need):
if right - left < length:
start = left
length = right - left
d = s[left]
left += 1
if d in need:
if window[d] == need[d]:
valid -= 1
window[d] -= 1
return "" if length == float('inf') else s[start:start + length]
追问:
- 时间/空间复杂度? $O(|s| + |t|)$ 时间,$O(|\Sigma|)$ 空间(字符集大小)
- 如果
t中有重复字符怎么办? Counter 天然处理,不需要额外逻辑 - 如果字符串 s 是流式输入的,如何改进? 可以用不定长滑动窗口,维护 need 的满足状态,每次新字符到来时尝试收缩左边界
Java 基础(20min)
HashMap 的
put流程完整说一下?- 计算 hash → 定位 bucket → 链表/红黑树插入 → 检查扩容(size > threshold = capacity * load_factor)
ConcurrentHashMap 在 JDK 1.7 和 1.8 的区别?
- 1.7:Segment 分段锁,每段一个 HashEntry 数组
- 1.8:取消 Segment,使用 CAS + synchronized(桶级别),红黑树优化长链表
线程池的核心参数有哪些?
- corePoolSize、maximumPoolSize、keepAliveTime、workQueue、threadFactory、rejectedExecutionHandler
拒绝策略有哪几种?
- AbortPolicy(默认抛异常)、CallerRunsPolicy(调用者线程执行)、DiscardPolicy(静默丢弃)、DiscardOldestPolicy(丢弃最老任务)
MySQL(10min)
- InnoDB 的 RR(可重复读)隔离级别如何解决幻读?
- 答:MVCC + Next-Key Lock(记录锁 + 间隙锁),锁住范围防止插入
- 聚簇索引和非聚簇索引的区别?
- 聚簇索引:叶子节点存储完整行数据(InnoDB 主键索引)
- 非聚簇索引:叶子节点存储主键值,需要回表
二面(项目 + 分布式,1h)
二面面试官是到店事业群的技术经理,更关注工程思维和系统设计。
算法题(20min)
LeetCode 138. 复制带随机指针的链表
class Node:
def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
self.val = x
self.next = next
self.random = random
def copyRandomList(head: 'Node') -> 'Node':
if not head:
return None
# 第一轮:复制节点并插入到原节点后面
curr = head
while curr:
new_node = Node(curr.val, curr.next, None)
curr.next = new_node
curr = new_node.next
# 第二轮:设置 random 指针
curr = head
while curr:
if curr.random:
curr.next.random = curr.random.next
curr = curr.next.next
# 第三轮:拆分链表
curr = head
new_head = head.next
while curr:
copy = curr.next
curr.next = copy.next
if copy.next:
copy.next = copy.next.next
curr = curr.next
return new_head
追问:
- 除了这种方式,还能怎么做? 可以用哈希表存储原节点到新节点的映射,空间换时间
- 时间/空间复杂度? $O(n)$ 时间,$O(1)$ 额外空间(迭代解法)
- 如果链表有环怎么办? 需要先检测环并处理(不过这道题一般来说没有环)
分布式锁(15min)
如何用 Redis 实现分布式锁?
我回答了 Redlock 方案:
import redis
import uuid
import time
class RedisDistributedLock:
def __init__(self, redis_client, lock_name, expire_time=30):
self.r = redis_client
self.lock_name = f"lock:{lock_name}"
self.expire_time = expire_time
self.identifier = str(uuid.uuid4())
def acquire(self):
# SET lock_name identifier NX EX expire_time
result = self.r.set(
self.lock_name,
self.identifier,
nx=True,
ex=self.expire_time
)
return result is not None
def release(self):
# 使用 Lua 脚本保证原子性
lua_script = """
if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else
return 0
end
"""
return self.r.eval(lua_script, 1, self.lock_name, self.identifier)
追问:
- 如果业务执行时间超过锁的过期时间怎么办? Redisson 的 Watch Dog 机制——启动守护线程定期续期
- Redis 是单节点的,如果挂了怎么办? Redlock 算法(在 N 个独立的 Redis 节点上加锁,多数成功才算获得锁)
- Zookeeper 实现分布式锁和 Redis 有什么区别? ZK 是顺序临时节点,利用 EPHEMERAL_SEQUENTIAL 实现公平锁,可靠性更高但性能略低
项目深挖(20min)
围绕实习中的优惠券系统:
- 优惠券如何防止超发?
- 答:Redis Lua 原子脚本扣减库存,数据库异步同步
- 如果 Redis 扣减成功但数据库写入失败怎么办?
- 答:先写数据库扣减,再删 Redis 缓存(Cache-Aside),异步对账补偿
- 如何防止用户重复领取?
- 答:幂等键(user_id + coupon_id)加唯一索引
- 优惠券过期怎么自动回收?
- 答:定时任务(xxl-job)扫描过期券 + Redis key 过期事件监听
开放性问题(5min)
如何设计一个餐厅排队系统?
- 我回答了取号、排队、叫号、过号重排四个状态,用 Redis Sorted Set 维护队列,WebSocket 推送叫号通知。
三面(HR 面,30min)
美团的技术面和 HR 面有时合并,有时分开。我的三面就是纯 HR。
- 为什么选择美团?
- 答:美团是「零售 + 科技」公司,到店业务直接连接线下实体商户,技术挑战大;同时美团的技术文化务实,重视工程能力。
- 你的职业规划?
- 答:1-3 年深耕后端技术栈,3-5 年成长为能独立负责系统模块的技术骨干。
- 手里有其他 offer 吗?
- 答:如实说有字节和京东,但美团更匹配我的业务兴趣。
- 期望薪资?
- 说了一个 range,HR 说会在范围内尽量争取。
美团面试特色总结
| 维度 | 特点 |
|---|---|
| 算法难度 | ⭐⭐⭐⭐ Medium 为主,偶尔 Hard,重视代码质量 |
| 技术深度 | ⭐⭐⭐⭐ 非常注重工程实践,Redis、MySQL、JVM 都会深挖 |
| 项目关注 | ⭐⭐⭐⭐⭐ 会追问到每个技术细节的实现和异常处理 |
| 系统设计 | ⭐⭐⭐ 二三面可能会问,但不像阿里那么重 |
| 面试氛围 | ⭐⭐⭐⭐ 务实、直接、不拖沓 |
美团面试官的经典追问风格:
- “如果这时候挂了怎么办?”
- “如果数据量翻 100 倍呢?”
- “你确定这个方案是最优的吗?有没有更好的?”
面试复盘与建议
美团面试的通关密码:
- Java 基础要扎实:HashMap、ConcurrentHashMap、线程池、JVM 内存模型是必考点。
- Redis 深入理解:不仅是缓存,分布式锁、限流、计数器、Sorted Set 的应用都要会。
- MySQL 不只八股文:索引优化、事务隔离级别、锁机制、分库分表策略要能结合实际场景讲。
- 项目要能扛住追问:每个项目准备"如果 XX 场景下出问题怎么解决"。
准备清单:
- 《深入理解 Java 虚拟机》核心章节
- 《Redis 设计与实现》数据结构 + 持久化 + 集群
- 《MySQL 技术内幕》InnoDB 存储引擎
- LeetCode Hot 100 + 剑指 Offer
- 准备 2-3 个能扛住 20 分钟追问的项目
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。