Java大厂面试实录:从Spring Boot到微服务架构,谢飞机的三轮闯关记(附技术详解)
Java大厂面试实录:从Spring Boot到微服务架构,谢飞机的三轮闯关记
面试官:王总(某互联网大厂技术总监,严肃认真) 求职者:谢飞机(水货程序员,自信满满但技术半吊子)
【第一轮面试:Java基础与Spring Boot】
场景设定:面试开始,王总翻开简历,抬头看了一眼紧张兮兮的谢飞机。
王总:(面无表情)谢飞机是吧?看你简历上写做过电商项目,那我们就从电商场景聊起。先问几个基础问题。
王总:第一个问题,你在电商项目里肯定用过HashMap来缓存商品信息,那你说说HashMap的底层实现原理?
谢飞机:(眼睛一亮,这题我背过!)王总好!HashMap底层是数组+链表+红黑树实现的。当发生哈希冲突时,链表长度超过8且数组长度超过64就会转成红黑树,这样查询时间复杂度从O(n)降到O(log n)。put的时候先算hash值,通过(n-1)&hash定位数组位置...
王总:(微微点头)嗯,基础还不错。那Spring Boot的自动配置你了解吗?我们项目大量使用Spring Boot,你来说说@SpringBootApplication注解背后做了什么?
谢飞机:(继续自信)这个我也知道!@SpringBootApplication是个组合注解,包含@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan。核心是@EnableAutoConfiguration,它会通过SpringFactoriesLoader加载META-INF/spring.factories文件中的配置类,根据@Conditional注解判断是否生效...
王总:(露出赞许的微笑)不错,看来基础功课做得可以。最后一个问题,电商秒杀场景下并发量很大,你用过线程池吗?说说线程池的核心参数有哪些?
谢飞机:(拍胸脯)线程池我太熟了!7个核心参数:
corePoolSize:核心线程数maximumPoolSize:最大线程数keepAliveTime:空闲线程存活时间unit:时间单位workQueue:工作队列threadFactory:线程工厂handler:拒绝策略
当任务来时,先判断核心线程是否满,满了就放队列,队列满了就创建非核心线程,都满了就执行拒绝策略!
王总:(满意地点头)很好,基础很扎实。那我们进入下一个环节...
【第二轮面试:微服务与中间件】
场景设定:王总喝了口茶,表情开始变得严肃。
王总:基础不错,现在我们聊聊实际业务场景。我们有个电商秒杀系统,高峰期QPS能达到10万+。第一个问题,如何用Redis保证秒杀时的库存一致性?
谢飞机:(开始有点虚)呃...这个...用Redis的话...就是先把库存预加载到Redis里,然后用...用那个...decr操作?对,用decr原子操作来扣减库存,这样可以保证...保证不超卖...
王总:(皱眉)只是decr吗?如果Redis和数据库数据不一致怎么办?
谢飞机:(擦汗)那就...那就用消息队列异步同步?或者...用那个分布式锁?
王总:(叹气)好吧,那你详细说说分布式锁怎么实现?
谢飞机:(更加紧张)分布式锁...用Redis的话就是用setnx...设置一个key...然后设置过期时间...防止死锁...具体实现类是...是Redisson?
王总:(摇头)说得不够清晰。那我们换个话题,你们项目用Dubbo做服务治理吗?说说Dubbo的服务调用流程?
谢飞机:(含糊其辞)Dubbo的话...消费者调用...然后通过注册中心...找到提供者...然后RPC调用...具体流程是...是那个...序列化、网络传输、反序列化...
王总:(明显不满意)太笼统了。最后一个问题,我们系统用Kafka做消息队列,如果出现消息积压怎么处理?
谢飞机:(开始胡扯)消息积压...那就增加消费者?或者...优化消费逻辑?或者...扩容?具体方案我...我项目中没遇到过这种情况...
王总:(面无表情记录)好的,我们进入最后一轮...
【第三轮面试:分布式架构与系统设计】
场景设定:王总合上简历,眼神犀利。
王总:最后一轮,我们聊聊系统设计。假设让你设计一个支持百万并发的电商秒杀系统,你会怎么设计整体架构?
谢飞机:(彻底懵圈)百万并发...这个...首先...要用微服务架构...然后...用Redis缓存...再用...用消息队列削峰...具体怎么设计...我...我画不出来...
王总:那分布式事务怎么保证一致性?比如秒杀下单,要同时扣库存、创建订单、扣余额,怎么保证这三个操作要么全成功要么全失败?
谢飞机:(开始瞎编)分布式事务...用...用2PC?或者...那个...TCC?还是...Saga?具体实现...我...我用的是本地事务...
王总:(摇头)最后两个问题。第一个,Spring AI你了解吗?我们准备在电商系统中引入AI智能客服。
谢飞机:(完全不知道)Spring AI...是...是Spring框架的AI模块吗?我...我没用过...
王总:那MCP协议呢?Model Context Protocol?
谢飞机:(一脸茫然)MCP...是...是Microservice Communication Protocol吗?
王总:(叹气,合上笔记本)好了,今天的面试就到这里。你的基础还可以,但在分布式架构和新技术方面还有欠缺。我们会综合评估,三天内给你答复,你先回去等通知吧。
谢飞机:(尴尬起身)好的好的,谢谢王总,那我等您通知...
【技术详解:让小白也能学会】
一、HashMap底层原理
业务场景:电商系统中缓存商品信息、用户会话等
技术要点:
- 数据结构:JDK1.8采用数组+链表+红黑树
- 哈希计算:
(key.hashCode() ^ (key.hashCode() >>> 16)) & (n-1),高位参与运算减少冲突 - 树化条件:链表长度≥8 且 数组长度≥64
- 扩容机制:容量翻倍,重新hash分布
// 核心put流程
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
二、Spring Boot自动配置原理
业务场景:快速搭建电商微服务,减少配置工作
技术要点:
- 核心注解:
@EnableAutoConfiguration - 加载机制:通过
SpringFactoriesLoader读取META-INF/spring.factories - 条件装配:
@ConditionalOnClass、@ConditionalOnMissingBean等 - 配置覆盖:用户自定义Bean优先于自动配置
@Configuration
@ConditionalOnClass(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
三、线程池核心参数
业务场景:电商秒杀、批量订单处理等高并发场景
技术要点:
ThreadPoolExecutor executor = new ThreadPoolExecutor(
10, // corePoolSize: 核心线程数
20, // maximumPoolSize: 最大线程数
60L, // keepAliveTime: 空闲线程存活时间
TimeUnit.SECONDS, // unit: 时间单位
new LinkedBlockingQueue<>(1000), // workQueue: 工作队列
new ThreadFactory() { // threadFactory: 线程工厂
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("seckill-thread-" + t.getId());
return t;
}
},
new ThreadPoolExecutor.CallerRunsPolicy() // handler: 拒绝策略
);
拒绝策略:
AbortPolicy:抛出异常(默认)CallerRunsPolicy:调用者线程执行DiscardPolicy:直接丢弃DiscardOldestPolicy:丢弃最老任务
四、Redis分布式锁
业务场景:秒杀库存扣减、订单状态更新
技术要点:
// Redisson实现分布式锁
RLock lock = redissonClient.getLock("seckill:lock:" + productId);
try {
// 加锁,等待3秒,锁定10秒自动释放
if (lock.tryLock(3, 10, TimeUnit.SECONDS)) {
try {
// 扣减库存
Long stock = redisTemplate.opsForValue().decrement("seckill:stock:" + productId);
if (stock < 0) {
throw new RuntimeException("库存不足");
}
// 创建订单...
} finally {
lock.unlock();
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
关键问题:
- 原子性:使用Lua脚本保证判断和删除的原子性
- 可重入:Redisson通过hash结构支持可重入
- 看门狗机制:自动续期,防止业务未完成锁就释放
五、Kafka消息积压处理
业务场景:订单创建后异步通知库存、积分、物流等系统
解决方案:
- 增加消费者:扩容Consumer实例数(不超过Partition数)
- 优化消费逻辑:批量处理、异步化
- 临时扩容:创建更多Partition,迁移数据
- 降级处理:记录到数据库,后续补偿
// 批量消费优化
@KafkaListener(topics = "order-create", groupId = "order-group")
public void consume(List<ConsumerRecord<String, String>> records) {
// 批量处理
List<OrderMessage> messages = records.stream()
.map(record -> JSON.parseObject(record.value(), OrderMessage.class))
.collect(Collectors.toList());
// 批量入库
orderService.batchProcess(messages);
}
六、Dubbo调用流程
业务场景:电商微服务间RPC调用
完整流程:
1. 消费者启动,向注册中心订阅服务
2. 提供者启动,向注册中心注册服务
3. 注册中心返回提供者地址列表给消费者
4. 消费者调用时:
- 从地址列表负载均衡选择一个提供者
- 序列化请求参数
- 通过Netty发送网络请求
- 提供者接收请求,反序列化
- 执行本地方法
- 序列化结果返回
- 消费者反序列化结果
七、分布式事务解决方案
业务场景:秒杀下单(扣库存+创建订单+扣余额)
方案对比: | 方案 | 一致性 | 性能 | 复杂度 | 适用场景 | |------|--------|------|--------|----------| | 2PC | 强一致 | 低 | 高 | 传统银行系统 | | TCC | 最终一致 | 中 | 高 | 资金类业务 | | Saga | 最终一致 | 高 | 中 | 长事务 | | 本地消息表 | 最终一致 | 高 | 低 | 电商订单 |
本地消息表实现:
@Transactional
public void createOrder(OrderRequest request) {
// 1. 创建订单
orderMapper.insert(order);
// 2. 写入本地消息表
messageMapper.insert(new Message(
UUID.randomUUID().toString(),
"ORDER_CREATED",
JSON.toJSONString(order),
MessageStatus.PENDING
));
// 3. 扣减库存(调用库存服务)
inventoryService.deduct(request.getProductId(), request.getQuantity());
}
// 定时任务发送消息
@Scheduled(fixedDelay = 1000)
public void sendPendingMessages() {
List<Message> messages = messageMapper.selectPending();
for (Message msg : messages) {
try {
kafkaTemplate.send("order-topic", msg.getContent());
msg.setStatus(MessageStatus.SENT);
messageMapper.update(msg);
} catch (Exception e) {
// 重试或告警
}
}
}
八、Spring AI与MCP协议
Spring AI:Spring官方的AI集成框架,提供统一的API对接各大模型
@Service
public class AIService {
@Autowired
private ChatClient chatClient;
public String chat(String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
MCP(Model Context Protocol):Anthropic提出的模型上下文协议,标准化AI与外部工具的交互
核心概念:
- Resources:数据源(文件、数据库等)
- Tools:可执行的操作
- Prompts:提示词模板
面试总结
谢飞机虽然基础尚可,但在以下方面需要加强:
- 分布式系统实战经验:需要深入理解分布式锁、事务、一致性等
- 系统设计能力:需要培养从0到1设计高并发系统的能力
- 新技术敏感度:需要关注Spring AI、MCP等前沿技术
给求职者的建议:
- 基础要扎实,但更要注重实战
- 多参与高并发项目,积累经验
- 持续关注技术社区,保持学习热情
本文通过幽默的面试场景,覆盖了Java面试的核心知识点。希望对正在准备面试的同学有所帮助!
更多推荐

所有评论(0)