美团 AI应用开发 一面
1. 做一下自我介绍
2. 如果一个核心链路已经同步调用很多下游了,为什么还要引入消息队列,而不是继续堆线程池
消息队列真正解决的不是“异步”两个字,而是削峰、解耦、容错和流量治理。同步链路堆线程池只能把等待成本从调用方挪到自己进程里,并不能改变系统容量边界;一旦下游抖动,请求会在调用链上层层堆积,最终把连接池、线程池和网关超时一起拖崩。引入 MQ 后,主链路可以只做核心事务,非核心逻辑异步化,下游能力不足时也能通过堆积和消费速率控制做缓冲。不过 MQ 不是银弹,如果业务要求强一致、低延迟、同步结果可见,盲目异步反而会把复杂度转移到补偿和状态机里。
3. 从生产端到消费端,怎么把“消息不丢”这件事讲完整
消息不丢从来不是某一个组件的承诺,而是一整条链路共同完成的。生产端需要有发送确认、失败重试、消息落库或事务消息兜底;Broker 侧要有刷盘策略、副本同步、故障恢复和积压治理;消费端必须做幂等、失败重试、死信隔离和位点提交控制。很多人说“MQ 保证可靠性”,其实最多保证消息尽量送达,不能保证业务一定执行成功。真正线上稳定的是“消息可靠传递 + 消费结果幂等 + 补偿闭环”,而不是单纯开个重试。
public void onMessage(OrderEvent event) {
if (consumeLogRepository.exists(event.getBizId())) {
return;
}
try {
orderService.handle(event);
consumeLogRepository.save(event.getBizId());
} catch (Exception e) {
throw e;
}
}
4. 线上说系统能扛多少 QPS,这个值你怎么测出来,怎么判断瓶颈到底在哪
QPS 不是压出来一个峰值就算数,必须结合延迟、错误率、资源利用率和稳定持续时间一起看。通常会先明确压测场景,区分读多写少、冷热数据、是否命中缓存、是否包含下游依赖,再逐层观察 CPU、GC、线程池、连接池、网络带宽、磁盘 IO 和数据库执行时间。真正的瓶颈定位不是看哪个指标最高,而是看链路里哪个资源最先饱和并开始放大尾延迟。很多系统表面上 CPU 不高,但其实是线程阻塞、锁竞争、下游超时或连接池耗尽导致吞吐上不去。
5. 你在使用消息队列的过程中遇到过最棘手的问题是什么,最后怎么收敛的
比较典型的棘手问题不是“不会发消息”,而是消息重复、乱序、消费放大和异常重试叠加之后把业务状态打乱。比如订单履约链路里,一个状态变更事件因为网络闪断触发重复投递,消费者又带有重试逻辑,最后库存回滚和优惠券补偿都被执行多次。最后的收敛方式通常不是调大超时,而是把事件做业务主键幂等、把状态流转做成有限状态机,再把重试策略和补偿任务拆开。这样即使发生重复或乱序,状态仍然能自洽。
6. 消息积压突然出现时,你会怎么区分是生产端突刺、消费端退化,还是中间件本身异常
先看堆积曲线是不是短时突刺还是持续增长,如果短时拉高后能自动消化,通常是流量峰值;如果持续堆高,说明消费能力长期低于生产速度。接着要拆消费者侧,看单条处理耗时、线程池活跃数、批量拉取参数、下游依赖耗时、失败重试次数和死信增长情况。如果 Broker 监控显示分区分布异常、磁盘刷盘变慢或副本同步延迟,也可能是中间件问题。真正排查时最怕只盯 MQ 面板,因为堆积往往只是结果,根因经常在数据库、缓存击穿、RPC 抖动或者消费逻辑锁冲突。
7. 用 Redis 做分布式锁时,setNx 的 key 和 value 为什么都不能随便设计
key 决定锁的粒度,value 决定锁的归属。key 如果设计得太粗,会导致不相关请求相互阻塞;太细则无法保护共享资源,锁等于白加。value 必须是全局唯一标识,比如请求 ID 或实例 ID 加线程标识,因为释放锁时要判断“是不是自己加的锁”,不能谁都能删。很多线上事故不是锁没加上,而是锁过期后被别的线程拿到,原线程执行完又把别人的锁删了,这就是为什么一定要 compare-and-delete。
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
8. 数据库里为什么很多高并发更新场景更倾向于乐观控制,而不是一上来就悲观锁
因为悲观锁的前提是假设冲突很频繁,所以先锁住再说,但在线上很多热点更新场景里,真正昂贵的是锁等待、事务持有时间和死锁风险。乐观控制更适合“冲突有,但不是常态”的情况,它把竞争推迟到提交时,通过 version 或条件更新判断是否成功。这样吞吐通常更高,也更利于扩展。不过乐观不是免费午餐,如果冲突率本来就高,重试风暴会把数据库打得更惨,所以是否用乐观控制,关键还是看数据热点和冲突模型。
9. 悲观锁和乐观锁真正的分界线是什么,怎么根据业务挑选
分界线不在于哪个“更高级”,而在于你对冲突的预期、失败成本和业务语义。像库存扣减、热点账户余额、少量强冲突资源,悲观锁更容易把语义收紧;但像用户资料更新、状态位修改、配置变更这类读多写少或冲突概率低的场景,乐观控制能明显减少阻塞。更高阶一点的判断是看失败是否可重试,重试代价高不高,失败是否会影响用户体验。如果重试成本远高于等待成本,乐观未必是更优解。
update coupon_account s
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专栏聚焦 AI-Agent 面试高频考点,内容来自真实面试与项目实践。系统覆盖大模型基础、Prompt工程、RAG、Agent架构、工具调用、多Agent协作、记忆机制、评测、安全与部署优化等核心模块。以“原理+场景+实战”为主线,提供高频题解析、标准答题思路与工程落地方法,帮助你高效查漏补缺.