Java 后端事务:从 Spring 代理到幂等、状态机和补偿
Java 后端事务从 Spring 代理到幂等、状态机和补偿开头很多人复习事务时会先背几个词ACID 传播级别 隔离级别 脏读 幻读 分布式事务这些当然要会但如果只停在概念面试里很容易被追问打散。更接近真实业务的理解应该是一次业务操作 ├── 中间失败怎么办 - 事务 ├── 同时有多个请求怎么办 - 锁 / 条件更新 ├── 重复请求怎么办 - 幂等 ├── 状态能不能这样变 - 状态机 ├── 跨服务怎么办 - 分布式事务 / MQ / Outbox └── 半成功后怎么办 - 补偿也就是说事务不是孤立知识点。它经常和锁、幂等、状态机、消息和补偿一起出现。一、事务到底解决什么问题事务最核心的作用是保证一组数据库操作要么全部成功要么全部失败。比如一个下单动作创建订单 扣减库存 生成支付记录如果订单创建成功库存扣减失败系统状态就不一致了。所以这些数据库操作通常要放在一个本地事务里。数据库本身提供事务能力begin;insertintoorders(...);updatestocksetquantityquantity-1wheresku_id?;insertintopayment_record(...);commit;Spring 的Transactional不是替代数据库事务而是帮我们管理事务边界避免每个方法都手写begin、commit和rollback。二、ACID 不要只背定义事务有四个经典特性ACID。特性含义例子Atomicity 原子性一个事务里的操作不可分割转账时 A 扣钱和 B 加钱必须一起成功Consistency 一致性事务前后满足业务规则转账前后总金额不变Isolation 隔离性并发事务之间不能产生不可接受的互相干扰两人同时买最后一件商品不能都扣成功Durability 持久性提交后数据持久保存支付提交后服务重启订单仍是已支付面试里比较好的回答方式是事务是一组数据库操作的执行单元保证这些操作满足 ACID。比如下单时订单、库存、支付记录必须保持一致如果中间失败需要整体回滚。三、Spring 事务是怎么实现的Spring 声明式事务的关键是AOP 代理 事务拦截器 数据库事务管理器一次正常调用大概是Controller - Spring 代理对象 - 开启或加入事务 - 调用真实 Service 方法 - 正常返回提交 - 抛出异常按规则回滚可以理解成下面这个伪代码publicObjectinvoke(){beginOrJoinTransaction();try{Objectresulttarget.method();commit();returnresult;}catch(Throwableex){if(shouldRollback(ex)){rollback();}else{commit();}throwex;}}所以Transactional的关键不是“标了就一定生效”而是调用必须经过 Spring 代理。四、Transactional常见失效场景1. 同类内部调用ServicepublicclassOrderService{publicvoidcreateOrder(){saveOrder();}TransactionalpublicvoidsaveOrder(){// insert order}}createOrder()里调用saveOrder()本质是this.saveOrder()没有经过 Spring 代理所以事务逻辑可能不会生效。常见解决方式是拆成两个 Service让调用经过 Spring Bean。2. 异常被吃掉TransactionalpublicvoidcreateOrder(){saveOrder();try{deductStock();}catch(Exceptione){log.error(deduct stock failed,e);}}异常被捕获后方法正常返回Spring 会认为可以提交事务。关键失败不能只打印日志要继续抛出异常或者显式标记回滚。3. 异常类型不匹配Spring 默认对RuntimeException和Error回滚。对于 checked exception如果业务上也要求回滚需要显式配置Transactional(rollbackForException.class)4. 新线程和远程调用Spring 事务上下文通常绑定在线程上。新开的线程不会自动继承外层事务。远程接口、MQ、WebSocket、第三方支付也不属于本地数据库事务。它们需要幂等、消息、重试和补偿设计。五、事务传播级别传播级别解决的问题是一个事务方法调用另一个事务方法时内层方法应该加入外层事务、新开事务、非事务执行还是要求必须有/没有事务Spring 一共有 7 种传播级别传播级别有外部事务时无外部事务时常见用途REQUIRED加入当前事务新建事务默认最常用REQUIRES_NEW挂起外部事务新建事务新建事务独立日志、失败记录NESTED在外部事务内建保存点类似REQUIRED局部回滚SUPPORTS加入当前事务非事务执行可复用查询NOT_SUPPORTED挂起外部事务非事务执行非事务执行非事务长操作MANDATORY加入当前事务抛异常强制由上层提供事务NEVER抛异常非事务执行明确禁止事务1.REQUIRED默认级别有事务就加入没有事务就创建。适合订单创建这类必须一起成功失败的业务。2.REQUIRES_NEW不管外部有没有事务都新建一个独立事务如果外部有事务先挂起外部事务。典型场景订单事务 T1 - 保存订单 - 挂起 T1 - 日志事务 T2 提交 - 恢复 T1 - T1 后续失败回滚这样即使订单失败日志也可能保留下来。但不要滥用。比如订单和库存应该一起成功失败如果把库存扣减写成独立REQUIRES_NEW可能出现库存已扣 订单回滚3.NESTEDNESTED是保存点不是完全独立事务。外层事务 T1 - 保存订单 - 建立 savepoint - 发优惠券失败 - 回滚到 savepoint - 订单继续如果外层事务最终回滚内层保存点里的内容也会跟着回滚。六、事务隔离级别隔离级别解决并发事务之间的可见性问题。三个常见并发现象问题含义脏读读到别人未提交的数据不可重复读同一事务两次读同一行结果不同幻读同一事务两次范围查询记录集合不同四种隔离级别隔离级别说明READ UNCOMMITTED读未提交可能脏读READ COMMITTED读已提交避免脏读REPEATABLE READ可重复读MySQL InnoDB 默认SERIALIZABLE串行化隔离最强并发最低MySQL InnoDB 里要特别注意普通 SELECT - 快照读依赖 MVCC UPDATE / DELETE / SELECT ... FOR UPDATE - 当前读读取最新数据并加锁所以不要简单说“可重复读解决一切幻读”。更严谨的说法是InnoDB 在REPEATABLE READ下通过 MVCC 提供一致性快照对锁定读和更新操作会结合行锁、间隙锁和 next-key lock 控制并发。七、幂等重复执行也不能重复产生副作用幂等的核心是同一个业务请求执行一次和执行多次最终对系统的业务影响一致。重复请求不只来自用户重复点击还可能来自网络超时重试。RPC 重试。支付平台重复回调。MQ 至少一次投递。定时任务重跑。补偿任务重复执行。1. HTTP 方法的幂等性按常见 REST 语义方法常见含义是否天然幂等GET查询是PUT整体替换或确定性更新通常是DELETE删除资源从最终状态看通常是POST创建或提交动作通常不是PATCH部分更新不天然是取决于设计注意这只是语义约定。真正是否幂等还要看服务端怎么实现。2. 常见幂等方案唯一业务号 唯一索引比如支付流水号createuniqueindexuk_payment_noonpayment_record(payment_no);第一次插入成功重复插入违反唯一约束。重要业务要尽量把幂等兜底放在数据库层。状态机 条件更新支付回调不要无条件更新updateorderssetstatusPAIDwhereid?andstatusWAIT_PAY;第一次回调影响 1 行重复回调影响 0 行。幂等表MQ 消费常用message_consume_record ├── message_id ├── business_id ├── consume_status └── consume_time先记录消息是否处理过再执行业务。业务执行和消费记录最好放在一个本地事务里。Token 令牌适合短周期防重复提交获取 token - 提交时携带 token - 服务端校验并删除 token乐观锁updateapprovalsetstatusPASSED,versionversion1whereid?andversion?andstatusWAIT_AUDIT;更新失败说明数据已经被别人改过。分布式锁分布式锁解决的是“同一时间只允许一个请求进入”。它不是完整幂等。锁过期后重复请求仍然可能再次进入。所以重要业务还要有唯一键、状态条件更新或幂等表兜底。八、状态机控制业务能不能这样变化很多业务系统本质上都是状态流转。订单WAIT_PAY - PAID - COMPLETED审批WAIT_AUDIT - PASSED / REJECTED任务WAITING - RUNNING - SUCCESS / FAILED状态机解决的是当前状态是否允许迁移到目标状态。它和幂等经常结合在一起updateorderssetstatusPAIDwhereid?andstatusWAIT_PAY;这条 SQL 同时表达只有 WAIT_PAY 才能变成 PAID 重复 PAID 不再执行 并发更新只能有一个成功九、事务、锁、幂等的关系这三个东西经常被混在一起。1. 事务解决一次请求内部多张表操作是否一起提交或回滚。2. 锁解决同一时间多个请求是否可以同时进入同一资源的关键区。3. 幂等解决同一个业务请求重复执行是否会重复产生业务副作用。支付例子事务订单和支付记录一起更新 锁避免同一订单同一时间多次处理 幂等支付平台重复回调也不会重复发权益 状态机订单只能从待支付变已支付 补偿已支付但订单未归并时后续任务修复十、分布式事务跨服务后本地事务不够了单库里订单表 库存表 支付表可以用一个本地事务。拆成服务后订单服务 - order_db 库存服务 - stock_db 支付服务 - pay_db一个普通Transactional管不了三个数据库也管不了远程服务。这时有几类方案。1. XA / 2PC两阶段提交Prepare所有参与者准备 Commit/Rollback统一提交或回滚优点是一致性强缺点是性能和可用性压力大可能阻塞资源。2. TCCTry预留资源 Confirm确认 Cancel取消余额扣减例子Try冻结 100 Confirm扣除冻结金额 Cancel释放冻结金额优点是业务可控缺点是每个业务都要实现三套动作还要处理幂等、空回滚和悬挂。3. SagaSaga 把一个长事务拆成多个本地事务。每一步成功后进入下一步失败时执行补偿动作。适合允许最终一致的长流程。4. MQ 最终一致性订单和库存例子订单服务本地事务 - 创建订单 - 写出待发送事件 消息投递 - 库存服务消费 - 幂等扣减库存 - 失败重试或补偿这里真正要保证的是消息不能丢。消费端必须幂等。失败要重试。长期失败要告警或人工处理。5. Outbox 本地消息表Outbox 的思路是同一个本地事务里 1. 修改业务表 2. 写入 outbox 消息表 事务提交后 3. 后台任务投递消息 4. 投递成功后标记消息状态这样避免“数据库提交了但消息没发出去”。但投递任务可能重复发送所以消费者仍然要幂等。6. SeataSeata 是常见分布式事务框架提供 AT、TCC、Saga、XA 等模式。面试时可以知道它解决哪类问题但如果项目里没有真实落地不要把它说成生产经验。十一、几个面试综合题1. 下单时如何保证订单和库存一致可以分层回答如果订单和库存在同一个数据库里可以用本地事务包住订单创建和库存扣减。库存扣减不能只先查再改应该使用带库存条件的原子更新例如quantity 1根据影响行数判断是否扣减成功。重复提交要有订单号或请求号幂等。如果订单和库存拆成不同服务普通本地事务就不够了可以使用可靠消息或 Outbox 实现最终一致库存消费端要幂等失败后重试或补偿。2. 支付回调重复通知怎么办推荐回答支付回调要先校验外部流水号、金额和订单状态。状态推进使用条件更新只允许待支付变成已支付。重复回调时影响 0 行不再重复执行业务动作。后续如果还有发权益、订单归并等动作要么在本地事务内完成要么通过消息、Outbox 或定时补偿保证最终一致。3. MQ 消费两次怎么办推荐回答MQ 通常是至少一次投递消费者必须幂等。可以用消息 ID 或业务 ID 建消费记录表先插入消费记录成功才执行业务如果重复消息再次到达发现已处理就直接返回。业务处理和消费状态更新要注意放在同一个本地事务里。4. 为什么用了事务还要锁推荐回答事务解决一次请求内部的提交和回滚锁解决多个请求是否能同时进入同一资源的关键区。比如库存只剩 1 件两个请求同时读到可用事务本身不一定阻止它们都进入扣减逻辑。可以用锁降低并发进入但最终仍要用数据库条件更新和唯一约束兜底。十二、不要这样回答这些说法很容易被面试官追问击穿“加了Transactional就能保证所有一致性。”“Redis 锁就是幂等。”“先查一下有没有有就不插入这样就防重复了。”“REQUIRES_NEW更安全所以所有内部方法都用它。”“MySQL 可重复读就是完全没有幻读。”“用了 MQ 就自然最终一致。”“分布式事务就是上 Seata所有场景都适合。”更好的习惯是先判断问题类型再选择对应方案。十三、结尾事务这块真正要建立的是一张图本地失败 - 事务 并发进入 - 锁 / 原子条件更新 重复执行 - 幂等 状态变化 - 状态机 跨服务 - 分布式事务 / MQ / Outbox 半成功 - 补偿能把这张图讲清楚再结合订单、支付、库存、任务同步这些通用场景事务面试就不再是零散背题而是一个完整的后端一致性模型。

相关新闻

基于Veyforge物理AI合成的Sim2Real高校实训方案-TsingtaoAI

基于Veyforge物理AI合成的Sim2Real高校实训方案-TsingtaoAI

物理 AI 合成驱动,让机器人在虚拟世界中成长,在现实世界中落地。面向高校的物理AI合成数据、高保真仿真与真机迁移一体化实训——TsingtaoAI VeyForge 项目团队 一、行业背景 Embodied AI正在推动人工智能从“能思考”走向“能动手”。机器人、无人车、…

2026/8/4 17:44:05 阅读更多 →
Spring Boot 3.x参数解析问题解决方案

Spring Boot 3.x参数解析问题解决方案

1. 问题现象与背景分析最近在升级到Spring Boot 3.x版本后,不少开发者遇到了控制器方法无法正确接收请求参数的问题。具体表现为:当使用RequestParam或直接声明方法参数时,前端传递的参数值在后端接收时变成了null。这个问题在Spring Boot 2.…

2026/8/4 17:43:04 阅读更多 →
2026年内蒙古智慧燃气安全监测管理系统的建设与服务商观察

2026年内蒙古智慧燃气安全监测管理系统的建设与服务商观察

燃气安全监测放在内蒙古版图上思考,秤砣就得往"广"和"冷"两个方向多压几分。内蒙古东西跨度超过两千四百公里,从城市门站到旗县终端,任何监测盲区都可能因信息传不回来变成管理黑洞。每年十月到次年四月漫长采暖季&#…

2026/8/4 17:43:04 阅读更多 →

最新新闻

朱雀 AIGC 检测原理是什么?能准确识别文章 AI 率和去 AI 痕迹效果吗?

朱雀 AIGC 检测原理是什么?能准确识别文章 AI 率和去 AI 痕迹效果吗?

朱雀 AIGC 检测原理是什么?能准确识别文章 AI 率和去 AI 痕迹效果吗? 你问这个问题,多半是因为心里有个更具体的疑问:我把 AI 写的东西改过一轮之后,它还认得出来吗? 这篇分两半回答。前一半讲原理&#…

2026/8/4 19:18:43 阅读更多 →
Logisim-evolution时序仿真终极指南:掌握数字电路时钟域设计实战技巧

Logisim-evolution时序仿真终极指南:掌握数字电路时钟域设计实战技巧

Logisim-evolution时序仿真终极指南:掌握数字电路时钟域设计实战技巧 【免费下载链接】logisim-evolution Digital logic design tool and simulator 项目地址: https://gitcode.com/gh_mirrors/lo/logisim-evolution Logisim-evolution是一款功能强大的开源…

2026/8/4 19:18:43 阅读更多 →
国产PLM有哪些?2026新能源电池选型攻略与核心功能解析

国产PLM有哪些?2026新能源电池选型攻略与核心功能解析

一、行业新态:2026新能源电池PLM应用刚需与市场格局2026年新能源电池产业加速向精细化、高安全、快迭代方向升级,动力电池、储能电池产品迭代周期持续压缩,材料配方、电芯结构、PACK工艺更新频次大幅提升,对产品全生命周期数字化管…

2026/8/4 19:18:43 阅读更多 →
利用ssh传递大文件

利用ssh传递大文件

利用ssh传递大文件 一、目的地配置检查(接收方电脑)1.1 优班图检查ssh和rsync 是否安装1.2 在实验室电脑(Ubuntu)上获取IP地址二级目录三级目录 一、目的地配置检查(接收方电脑) 1.1 优班图检查ssh和rsync…

2026/8/4 19:18:43 阅读更多 →
【干货】学会这6步,普通人也能做好数据分析全流程指南(附电商实战案例)

【干货】学会这6步,普通人也能做好数据分析全流程指南(附电商实战案例)

很多人觉得数据分析高大上,动不动就想用复杂的模型,好像不学点机器学习都不好意思开口。很多人拿着复杂的数据,做着精美的图表,最后给出的结论却是“这个月销售额下降了,建议下月提升”。真正的数据分析,需…

2026/8/4 19:18:43 阅读更多 →
数字信号最佳接收:从准则、模型到匹配滤波器的工程实践

数字信号最佳接收:从准则、模型到匹配滤波器的工程实践

1. 先搞清楚“最佳接收”到底要解决什么问题 如果你在学通信原理,看到“数字信号的最佳接收”这个概念,第一反应可能是公式复杂、推导繁琐。但它的核心目标其实很直接: 在噪声干扰下,如何从一堆乱七八糟的信号里,最准…

2026/8/4 19:17:43 阅读更多 →

日新闻

AI Agent白手起家26: 使用标准事件驱动大模型实践

AI Agent白手起家26: 使用标准事件驱动大模型实践

纲要 练习目标:掌握大模型标准事件的调用回顾 LangChain 中的核心标准事件 invokestreambatchastream_eventswith_structured_output 环境准备实战代码:多种事件调用对比 同步调用与流式输出批量处理异步事件流监听结构化输出 运行说明与预期结果总结与扩…

2026/8/4 0:00:40 阅读更多 →
dealsea是什么?跨境卖家必知的美国deal站入门指南

dealsea是什么?跨境卖家必知的美国deal站入门指南

说实话,第一次听说美国这个老牌折扣网站的跨境卖家,十个有八个会问同一个问题:这个平台到底是干嘛的?我见过一个做家居出口的朋友,他在亚马逊上月销二十万美金,却从来没用过它。我给他看了首页——一屏一屏…

2026/8/4 0:01:40 阅读更多 →
清华大学重磅EST:植物自导电闪蒸焦耳热600°C/2600°C两步法!稀土超积累植物秒级转化为CeO₂-石墨烯电催化剂!

清华大学重磅EST:植物自导电闪蒸焦耳热600°C/2600°C两步法!稀土超积累植物秒级转化为CeO₂-石墨烯电催化剂!

通讯作者:邓兵、刘建国通讯单位:清华大学DOI:https://doi.org/10.1021/acs.est.6c00603研究背景稀土元素(REEs)是清洁能源技术与电子器件不可或缺的核心原料,然而传统提取方式依赖能耗高、排放大的采矿与强…

2026/8/4 0:01:40 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/4 13:24:41 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/4 11:41:39 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/4 5:26:40 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/4 13:38:24 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/4 11:09:16 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/4 13:38:40 阅读更多 →