Java大厂面试现场:谢飞机硬刚并发编程与微服务架构

Java大厂面试现场:谢飞机硬刚并发编程与微服务架构

场景设定:某头部互联网公司会议室,阳光斜照。面试官李老师面无表情地翻着简历,对面坐着笑容灿烂的程序员——谢飞机。


第一轮:基础夯实 · 并发编程的灵魂拷问

面试官李老师:谢飞机是吧?我看你写了熟悉Java并发编程,那我问你,synchronizedReentrantLock 有什么区别?

谢飞机:嗯……这个我知道!synchronized 是关键字,JVM 层面实现的,自动加锁解锁;ReentrantLock 是 API,要手动 lock() 和 unlock(),还支持公平锁、可中断、超时获取锁!

面试官李老师(微微点头):不错,那你知道 synchronized 在 JDK 1.6 之后做了哪些优化吗?

谢飞机:哦……这个……应该是有偏向锁、轻量级锁、重量级锁那个……升级机制?好像是为了减少线程阻塞带来的性能开销。

面试官李老师:很好。那如果我现在有一个高并发的秒杀场景,库存扣减用 synchronized 行不行?

谢飞机:呃……单机的话 maybe 还行?但要是分布式部署,那就不行了,得用 Redis 或者数据库乐观锁!

面试官李老师:反应不错。那你来说说,Redis 如何实现分布式锁?注意异常情况处理。

谢飞机:用 SET key value NX EX……value 是唯一标识,比如 UUID,释放的时候要 Lua 脚本保证原子性……宕机了可以用 RedLock……啊不对,RedLock 有争议……

面试官李老师(微笑):知道有争议,说明你还看过点资料。不错,继续。


第二轮:框架深挖 · Spring Boot 自动装配背后的秘密

面试官李老师:我们系统用了 Spring Boot,你说说它的自动装配原理?

谢飞机:就是 @SpringBootApplication 注解里有个 @EnableAutoConfiguration,它会去读 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,加载一堆 XxxAutoConfiguration 类,然后根据条件注解比如 @ConditionalOnClass 来决定是否创建 Bean。

面试官李老师:很好。那如果我自己写一个 starter,该怎么做?

谢飞机:新建一个 Maven 项目,引入 spring-boot-autoconfigure,写一个 AutoConfiguration 类,加上条件注解,然后在 META-INF/spring/ 下注册它。最后在另一个项目引入这个 starter 的依赖就行!

面试官李老师:不错。那你知道为什么 starter 一般要分离 autoconfigure 模块和 starter 模块吗?

谢飞机:呃……这个……可能是为了……解耦?或者……我不知道。

面试官李老师:是为了避免依赖传递问题。比如你的 autoconfigure 模块依赖了某个库,如果不拆开,使用者就会强制带上这个依赖。拆开后,starter 只是一个空壳,真正逻辑在 autoconfigure 里,更灵活。

谢飞机:哦!学到了学到了!


第三轮:架构设计 · 分布式事务在电商场景的落地

面试官李老师:现在我们做一个电商下单流程:创建订单 → 扣减库存 → 扣减余额 → 发送消息。这四个操作跨服务,如何保证一致性?

谢飞机:可以用 Seata 的 AT 模式!在每个数据库建 undo_log 表,Seata 会自动生成反向 SQL,像分布式事务的‘自动挡’!

面试官李老师:如果不用 Seata 呢?比如用消息队列?

谢飞机:那就用可靠消息最终一致性方案!比如下单后发个 MQ 消息,库存服务消费,如果失败就重试,加个幂等表防止重复扣减……

面试官李老师:那如果消息发出去了,但网络抖动,生产者不知道是否成功,怎么办?

谢飞机:呃……可以……发消息前先写个本地事务表,标记“已下单未发消息”,然后发消息,成功就改状态……啊!这是本地消息表方案!

面试官李老师:不错。那 Kafka 如何保证消息不丢失?

谢飞机:生产者设置 acks=allretries 重试;Broker 设置副本同步;消费者手动提交 offset……吧?

面试官李老师(点头):基本到位。不过要注意,acks=all 只能保证副本都收到,但 Leader 切换时仍可能丢数据,最好配合幂等生产者和事务消息。


面试官李老师:今天就到这里,你的基础还可以,深度有待加强。回去等通知吧。

谢飞机(站起来,整理衣服):好嘞!谢谢李老师!我回去就看《Spring 源码深度解析》!


面试问题解析与技术点总结

1. synchronized vs ReentrantLock

| 特性 | synchronized | ReentrantLock | |------|------------------|------------------| | 实现层面 | JVM 内置 | JDK API | | 锁获取 | 自动 | 手动(需 lock()/unlock()) | | 公平性 | 非公平 | 可设置公平锁 | | 中断响应 | 不支持 | 支持 lockInterruptibly() | | 超时获取 | 不支持 | 支持 tryLock(timeout) |

JDK 1.6 优化:引入偏向锁(无竞争时直接持有)、轻量级锁(CAS 操作避免互斥量)、重量级锁(内核态阻塞)。锁会根据竞争情况升级。

2. 分布式锁实现(Redis)

  • 基础命令SET resource_name unique_value NX EX 10(NX=不存在才设,EX=过期时间)
  • 释放锁:必须用 Lua 脚本保证原子性,判断 value 是否为自己再删除
  • RedLock 争议:Martin Kleppmann 指出其依赖系统时钟,存在时钟漂移风险。推荐使用 Redisson 的 RedissonLock 或基于 ZooKeeper 的方案。

3. Spring Boot Starter 设计

  • autoconfigure 模块:包含自动配置类、条件注解、核心逻辑
  • starter 模块:仅依赖 autoconfigure 模块 + 常用工具(如 Lombok、Web),便于用户引入
  • 目的:避免将 autoconfigure 的依赖传递给使用者,提升灵活性和可控性

4. 分布式事务解决方案

| 方案 | 说明 | 适用场景 | |------|------|----------| | Seata AT 模式 | 两阶段提交,自动生成回滚日志 | 强一致性要求不高,快速接入 | | 可靠消息最终一致性 | 本地事务表 + 消息队列 | 高并发,允许短时不一致 | | TCC(Try-Confirm-Cancel) | 手动实现三阶段 | 资金、库存等核心业务 | | SAGA 模式 | 长事务拆分为子事务,补偿机制 | 复杂业务流程 |

5. Kafka 消息可靠性保障

  • 生产者acks=all(所有 ISR 副本确认)、enable.idempotence=true(幂等性)、retries 设置
  • Brokerreplication.factor >= 3min.insync.replicas=2
  • 消费者:关闭自动提交,业务处理成功后手动提交 offset

注意:即使 acks=all,在极端情况下(如 Leader 突然宕机未同步 follower),仍可能丢失数据。建议结合事务消息(initTransactions + sendOffsetsToTransaction)实现精确一次(Exactly Once)语义。


结语:本文通过模拟真实面试场景,串联了 Java 并发、Spring Boot 原理、分布式事务、消息队列等核心技术点。建议读者不仅记住答案,更要理解背后的业务场景与权衡取舍。真正的高手,不是会背八股文,而是能在复杂系统中做出合理技术选型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值