去哪儿旅行 Java后端AI面面经
- 轮次
- AI面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 排查线上 JVM CPU 过高或内存泄漏时,会用到哪些核心工具和命令?
- 拿到占用 CPU 最高的线程 ID 后,如何与
jstack输出对应并定位问题代码? - Java 中有哪些对共享变量做无锁并发处理的方式?CAS 的实现逻辑是什么?
- CAS 的 ABA 问题在实际业务中如何解决?
AtomicStampedReference.compareAndSet需要传入哪些参数?- Redis 的 RDB 和 AOF 持久化机制分别是什么,适用于哪些场景?
BGSAVEfork 子进程后,主进程继续接收写请求时,Redis 如何保证 RDB 对应 fork 时刻的内存快照?- 同一个 key 连续执行大量
INCR后,Redis 如何避免 AOF 中的冗余命令导致文件过大? - Netty 的线程模型是什么?实现 HTTP 服务端与客户端交互时,线程如何流转?
- Netty 主从 Reactor 模型中,boss 线程组和 worker 线程组分别负责什么?
- 如何设计每秒写入一万条订单、支持自定义超时时间的订单自动取消与库存释放系统?
- 使用 RocketMQ 延时消息处理超时订单时,如何避免已经支付的订单被错误取消?
- RocketMQ 开源版默认只有固定延时等级,如何实现任意时长的超时消息投递?
- 一个后端项目最主要的技术挑战是什么,如何解决?
- 消息转发仅依赖 RocketMQ 原生可靠性时,会在哪些场景失效?
- 如何用具体指标或异常现象证明消息转发可靠性不达标?
- 最近半年如何学习并落地 AI 工具或大模型技术,最终效果如何?
- 选择 Agent Coding 工具时,应考虑哪些因素?
- 开发流程中的浏览器插件、协作平台 MCP、本地代理和热启动配置,哪些应由开发者亲自完成和验证?
《参考解析》
- JVM 高 CPU 排查:先用
top -H -p <pid>找到高 CPU 线程的十进制 ID,再用printf '%x\n' <tid>转成十六进制,在jstack <pid>输出中搜索对应的nid=0x...。结合线程状态和连续多次栈快照,判断是死循环、频繁 GC、锁竞争还是热点方法;内存泄漏则配合jcmd、jmap和堆转储分析工具定位持续增长的对象及其引用链。 - CAS 与 ABA:CAS 比较内存中的当前值与期望值,相等时原子写入新值,否则失败重试。ABA 表示值从 A 变为 B 又变回 A,单纯比较值无法发现中间变化;可用带版本戳的
AtomicStampedReference,其compareAndSet依次接收期望引用、新引用、期望版本戳和新版本戳。 - Redis 持久化:RDB 定期生成紧凑快照,恢复快但可能丢失最近一次快照后的数据;AOF 追加写命令,可按刷盘策略缩小数据丢失窗口,但文件和恢复成本更高。fork 后通过操作系统的写时复制保留快照视图;AOF 则通过重写把同一 key 的历史命令压缩为能恢复当前状态的最小命令集合。
- Netty 线程模型:boss 线程组负责监听端口和接收连接,把建立好的 Channel 注册给 worker;worker 线程组中的 EventLoop 负责连接上的读写事件和 ChannelPipeline 回调。耗时业务不能阻塞 I/O EventLoop,应提交到独立业务线程池并把结果安全地写回 Channel。
- 订单超时系统:订单创建与库存预占需要可幂等,超时任务按到期时间分片存储或进入支持定时投递的消息链路。消费者收到超时事件后必须以数据库中的订单状态为准,通过条件更新只把仍未支付的订单从待支付改为已取消;只有状态更新成功的一方释放库存。任意时长可用时间轮、分层时间桶或定时任务扫描到期索引实现,不能假定 RocketMQ 固定延时等级支持任意时间。
- 消息可靠性验证:给消息分配全链路唯一 ID,记录生产成功、Broker 确认、消费成功和业务落库四个阶段的计数与延迟。通过阶段间差值、积压量、重试与死信数量、抽样对账和故障注入定位丢失窗口,再决定是否需要本地消息表、事务消息或补偿任务。