核心内容摘要
9.1版本奖励软件
深蓝保Java一面复盘高并发、JVM调优、索引优化…这些面试题你真的会答吗最近参加了一场深蓝保的Java后端实习岗位模拟面试整个过程节奏紧凑、问题深入尤其是对项目细节和底层原理的追问非常“致命”。
本文将完整还原这场面试对话涵盖高并发场景设计、线程池监控、OOM排查、千万级表加索引策略等高频考点并附上我的思考与回答思路希望能帮助正在准备Java后端面试的同学少走弯路
开场自我介绍 动机 技术栈面试官提问“请先做个简单的自我介绍说说为什么看这个机会以及你主要使用的技术栈。
”我回答“您好我是XX大学计算机专业的大三学生目前有两段Java后端相关的实习/项目经历。
我对保险科技领域很感兴趣了解到深蓝保在智能核保和用户服务方面做了很多创新希望能在实际业务中提升自己的工程能力和系统设计思维。
技术栈方面我主要使用Spring Boot MyBatis-Plus Redis RabbitMQ构建后端服务数据库用的是 MySQL部署在 Docker Nginx 环境下。
对 JVM、多线程、MySQL 索引优化也有一定研究。
”
项目深挖从缓存到高并发
项目里的优化点面试官提问“你在项目中提到做了性能优化具体有哪些优化点”我回答“主要有三点接口响应慢通过 Arthas 发现某个查询接口平均耗时 800ms原因是多次循环内查数据库。
我改成了批量查询 缓存预热降到 120ms。
第三方接口频繁调用比如调用征信 API我们做了本地缓存RedisTTL 设为 5 分钟并配合异步刷新。
SQL 慢查询通过EXPLAIN发现缺失联合索引添加后 QPS 提升了 3 倍。
”
第三方接口结果缓存如何保证实时性面试官追问“你说用了缓存但如果第三方数据变了怎么尽可能保证实时性”我回答“这个问题确实很关键。
我考虑了两种方案方案一第三方支持回调Webhook。
我们在系统里暴露一个回调接口当第三方数据变更时主动通知我们我们立刻失效或更新缓存。
方案二定时主动刷新。
如果对方不支持回调我们就用定时任务比如每 30 秒去拉取最新数据但只在缓存即将过期前触发避免无效请求。
实际项目中我们结合了两种方式核心数据用 Webhook非核心用定时刷新 TTL 双保险。
”面试官继续追问“如果回调失败怎么办”“我们会记录失败日志并加入重试队列比如用 RabbitMQ 的 DLX 机制最多重试 3 次同时告警通知运维介入。
”
并发安全ConcurrentHashMap 底层原理面试官提问“ConcurrentHashMap 是如何保证并发安全的”我回答“在 JDK
8 中ConcurrentHashMap 主要通过CAS synchronized实现线程安全不再使用分段锁Segment。
具体来说数据结构是Node 数组 链表/红黑树插入元素时先 CAS 尝试插入如果该位置已有元素则对该头节点加 synchronized 锁只锁住当前桶bucket而不是整张表扩容时采用多线程协助扩容机制多个线程可以同时迁移不同区间的桶提升效率。
这样既保证了高并发下的安全性又避免了 HashTable 那种全局锁的性能瓶颈。
”⚡
高并发实战电商秒杀场景的线程池配置面试官提问“假设你要设计一个电商秒杀系统线程池参数该怎么配”我回答“秒杀场景的特点是瞬时高并发、短任务、拒绝策略敏感所以线程池配置要特别谨慎。
我会这样设计核心线程数corePoolSize设为 CPU 核数比如 4~8因为秒杀逻辑主要是 I/O 密集型查库存、扣减、写订单但也不能太大避免上下文切换开销。
最大线程数maximumPoolSize可适当放大比如 100~200应对突发流量。
阻塞队列不用无界队列我会选ArrayBlockingQueue有界队列比如容量 1000防止 OOM。
拒绝策略自定义拒绝策略比如返回“活动太火爆请稍后再试”或者降级到 MQ 异步处理。
此外我会配合限流Sentinel 缓存Redis 预减库存 异步下单来保护后端服务。
”
可观测性如何实时监控线程池指标面试官追问“你怎么知道线程池是否快撑不住了如何监控”我回答“我们可以通过ThreadPoolExecutor 提供的监控方法获取关键指标getActiveCount()活跃线程数getQueue().size()等待队列长度getCompletedTaskCount()已完成任务数实践中我会定时采集这些指标通过 Micrometer 或 Prometheus 暴露给 Grafana设置告警规则比如“队列长度 80% 容量”或“活跃线程持续 10 秒 maxPoolSize”在 Spring Boot 中还可以用Bean注册ThreadPoolTaskExecutor并绑定到 Actuator 端点。
这样就能实现实时监控 自动告警提前发现资源瓶颈。
”
线上事故处理OOM 排查与解决面试官提问“如果线上服务突然 OOM你会怎么排查”我回答“OOM 排查我
总结为四步法Step 1保留现场确保 JVM 启动时加了-XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/logs/heap.hprof自动生成堆转储文件。
Step 2分析内存快照用MATMemory Analyzer Tool或JProfiler打开 hprof 文件查看Dominator Tree找出占用内存最大的对象
常见问题缓存未设上限、静态集合不断 add、大对象未释放。
Step 3结合日志 监控查看 GC 日志需开启-Xloggc看是否频繁 Full GC对比 OOM 前后的业务操作比如是否刚上线新功能。
Step 4修复 验证如果是缓存问题加 LRU 限制或改用 Caffeine如果是内存泄漏修复代码并做压力测试。
曾经我在一个项目里发现 OOM 是因为一个 static Map 存放用户会话最终改用 Guava Cache 解决。
”️
DBA级难题千万级表在线加索引面试官提问“现在有一张 2000 万行的用户表要加一个普通索引怎么做到不影响线上服务”我回答“直接ALTER TABLE ADD INDEX会锁表绝对不行。
我的方案是✅使用 pt-online-schema-changePercona Toolkit它会创建一张影子表_user_new加上新索引将原表数据分批拷贝到新表chunk 方式每次 1000 行同时通过触发器Trigger同步原表的 DML 操作INSERT/UPDATE/DELETE到新表最后原子切换表名删除旧表。
整个过程几乎零锁表对线上影响极小。
补充如果是 MySQL
6也可以用Online DDLALGORITHMINPLACE, LOCKNONE但要注意不支持全文索引、空间索引仍可能因 buffer pool 不足导致性能抖动建议在低峰期执行并监控information_schema.innodb_metrics。
压轴题你做过最好的一次技术优化面试官提问“最后一个问题你过去做过最好的一次技术优化是什么”我回答“最让我自豪的一次是在校园二手交易平台项目中将商品搜索接口从 2s 优化到 200ms。
原来是每次搜索都全表扫描 多表 JOIN我做了三件事引入 Elasticsearch做全文检索同步用 Canal 监听 binlog热点关键词缓存把‘手机’‘笔记本’等高频词结果缓存在 RedisTTL 5 分钟前端防抖 后端限流避免恶意刷搜索。
上线后CPU 使用率下降 60%用户留存提升了 15%。
这次经历让我深刻体会到性能优化不是炫技而是为用户体验服务。
”✅
总结面试考察的核心能力这场面试看似问得散实则层层递进重点考察项目深度能否讲清楚“为什么这么做”而不仅是“做了什么”系统思维高并发、缓存、数据库、JVM 要能串联起来工程素养监控、告警、线上问题处理能力底层原理ConcurrentHashMap、线程池、MySQL 索引机制必须吃透。
建议面试前务必对自己的项目“盘到骨子里”每个技术选型都要准备好“为什么不用其他方案”的答案。
如果你也在准备 Java 后端面试欢迎点赞 收藏 关注后续我会持续更新深蓝保二面、字节/腾讯模拟面等高质量复盘内容。
评论区开放讨论你在面试中被问过哪些“灵魂拷问”欢迎分享