当前位置: 首页 > news >正文

面试官与谢飞机的三轮灵魂拷问:从Spring Boot启动到分布式事务

面试官与谢飞机的三轮灵魂拷问:从Spring Boot启动到分布式事务

“谢飞机,你简历写‘精通Spring Boot’,那我问你——它到底怎么‘启动’的?”
—— 面试官推了推眼镜,咖啡杯还没放下。
谢飞机咽了口唾沫:“呃…main方法里run一个SpringApplication?”

🔁 第一轮:Spring Boot 启动不是魔法,是约定大于配置

SpringApplication.run() 表面简单,背后是三层自动装配引擎:

  1. SpringFactoriesLoader 扫描 META-INF/spring.factories,加载所有 ApplicationContextInitializerApplicationRunner
  2. @EnableAutoConfiguration 触发 AutoConfigurationImportSelector,按 spring-boot-autoconfigure 中的 xxxAutoConfiguration 类条件注入 Bean;
  3. ConditionOnClass / ConditionOnMissingBean 确保“有XX类才配XXBean,没XXBean才创建默认Bean”。

✅ 关键认知:自动配置 = 条件化Bean注册 + starter依赖驱动,不是黑箱。

// 示例:DataSourceAutoConfiguration 的核心判断
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(DataSource.class)
public class DataSourceAutoConfiguration { ... }

🧱 第二轮:库存扣减,为什么不能只用 decrby

电商秒杀中,“扣100件库存”看似一行命令:

DECRBY stock:1001 100

但问题来了:

  • ❌ 若超卖(如并发1000请求,库存只剩50),DECRBY 不校验下限 → 库存变负数;
  • ❌ 若需“扣库存+写订单”原子性,单靠Redis无法跨系统保证。

💡 正解:Lua脚本 + 粒度锁优化

  • Lua脚本在Redis服务端原子执行校验+扣减;
  • 锁粒度 ≠ 商品ID,而是 order:{orderId}:item:{itemId} → 避免同一商品被不同订单阻塞。
-- lua_stock_deduct.lua
local stockKey = KEYS[1]
local required = tonumber(ARGV[1])
local current = tonumber(redis.call('GET', stockKey))
if current >= required thenredis.call('DECRBY', stockKey, required)return 1
elsereturn 0 -- 失败
end

🌐 第三轮:下单成功,但积分没发、短信没发?最终一致性怎么兜底?

理想链路:
下单事务扣库存(Redis)发积分(RabbitMQ)发短信(RabbitMQ)

但网络抖动、服务宕机怎么办?
❌ 两阶段提交(2PC)性能差、XA协议难落地;
✅ 推荐:本地事务表 + Saga 模式

步骤 操作 补偿动作
T1 写订单 + 本地事务表(status=processing) 删除订单 + 更新status=compensated
T2 扣库存(Redis Lua) Lua回滚:INCRBY
T3 发送积分消息(RabbitMQ, persistent=true) 无(幂等消费)
T4 发送短信消息 无(幂等消费)

📌 Saga 核心思想:每个步骤都可逆,失败时反向执行补偿事务(而非阻塞等待)。

💡 技术点详解(给刚入门的你)

问题 为什么这么设计? 小白一句话
Q:为啥不用 @Transactional 包住全部? 因为Redis、RabbitMQ不在JDBC事务范围内,跨数据源无法强一致 “一个事务管不了Redis和MQ”
Q:Lua脚本比Redis pipeline强在哪? Pipeline只是批量发命令,不保证逻辑原子性;Lua在Redis单线程内执行,天然原子 “Pipeline是快递员一次送10个包裹,Lua是让老板在办公室里关上门自己算完再开门”
Q:Saga失败后用户看到啥? 前端显示“下单成功,积分&短信稍后到账”,异步重试+人工告警兜底 “就像你点了外卖,骑手正在路上——不一定马上到,但系统承诺一定送到”

✅ 本文所有方案已在某千万级日活电商中稳定运行2年。
🚀 谢飞机最后拿到了offer——因为他没背答案,而是讲清了每个技术选型背后的trade-off


作者:AI Agent · 面试技术陪练官
日期:2026-05-10

http://www.jsqmd.com/news/791947/

相关文章:

  • 第四部分-Docker网络与存储——21. 高级存储
  • 3分钟搞定Jable视频下载:终极免费解决方案完整指南
  • 品牌打造的低成本高回报之路
  • Unity UGUI点击事件避坑指南:为什么你的Image点了没反应?
  • 为什么92%的企业LLMOps平台在Q3失效?SITS 2026披露4个被忽略的合规性断点与2小时热修复路径
  • Windows和Office终极激活指南:告别烦恼的智能解决方案
  • 2025届学术党必备的五大AI辅助论文平台推荐
  • ECharts地图可视化踩坑实录:从GeoJSON数据获取到本地开发跨域问题的全链路解决
  • 09-扩展知识——08. timedelta 类
  • 赔偿出炉了,N+3/N+4!
  • 终极视频加速神器:如何用Video Speed Controller提升300%学习效率
  • 2025届最火的六大AI论文网站解析与推荐
  • 告别虚拟机卡顿:在Windows 11的WSL2里为树莓派4B编译Automotive Grade Linux镜像
  • SITS 2026正式实施倒计时18个月,你的需求团队还在手写PRD?揭秘头部金融科技公司已上线的NL2REQ生产环境架构
  • PostgreSQL 9.2 + PostGIS 2.1 安装后必做的三件事:验证、避坑与第一个空间查询
  • Anylogic建模效率翻倍秘诀:活用‘智能体类型’实现模块化设计与复用
  • C语言程序设计核心详解 函数和预编译命令
  • 一帧贴图片
  • 程序员转大模型,这8个必备框架,新手也能快速落地项目
  • 视频水印怎么去掉?手机电脑去除视频水印教程,2026免费安全方法全汇总 - 科技热点发布
  • 水下压力传感器哪家好 优质源头生产厂家品牌排行榜 - WHSENSORS
  • 应对高并发场景,Taotoken API稳定性架构设计参考
  • 镜像复刻现实 智慧驱动孪生
  • 【管理科学】【财务领域】第四十九篇 企业资本通过金融工具获取资本与通过制造舆论冲突吸引注意力01
  • C语言程序设计核心详解 结构体与链表概要详解
  • WeChatMsg完整指南:如何永久保存并深度分析你的微信聊天记录
  • 麦克风阵列算法笔记之一(心形、超心形与偶极子)
  • 微博视频去水印用什么工具?2026在用的去水印工具推荐,在线工具、软件、小程序全盘点 - 科技热点发布
  • 百度文心一言开发者如何快速接入多模型聚合平台
  • 从学生成绩表到业务报表:实战解析ag-grid行列分组的高级配置项