分布式事务
分布式事务就像“多人协作完成一件事”,比如公司跨部门合作完成一个项目,需要多个部门同时成功才能算项目完成。如果某个部门出问题,整个项目就得取消,不能只完成一部分。在Java中,分布式事务就是确保多个服务(或数据库)的操作要么全部成功,要么全部失败,保持数据一致性。下面用简单话术解释几种常见实现方式:
一、两阶段提交(2PC):像“公司开会表决”
1.
第一阶段(投票表决):
○
协调者(项目经理)问所有参与者(部门负责人):“你们能完成任务吗?”(比如扣库存、支付、生成订单)
○
参与者检查自己能否完成,如果可以,就锁定资源(比如冻结库存),并回复“可以”。
2.
第二阶段(执行结果):
○
如果所有部门都回复“可以”,协调者说:“执行吧!” 各部门完成操作,释放资源。
○
如果任何部门回复“不行”,协调者说:“全部取消!” 各部门回滚操作,释放资源。 缺点:效率低,部门需要等所有人投票结果,可能长时间占用资源;如果协调者挂了,可能卡住。
二、补偿型事务(TCC):像“签合同+违约赔偿”
1.
Try(尝试预留资源):比如转账,先冻结转出账户的钱,但不扣款。
2.
Confirm(确认执行):如果所有服务都成功冻结资源,再真正扣款和到账。
3.
Cancel(取消/补偿):如果任何服务失败,就执行“逆向操作”,比如解冻账户的钱。 例子:用户下单时,冻结库存和支付金额;如果支付失败,就解冻库存和退款。 缺点:代码复杂,需要手动编写Try/Confirm/Cancel逻辑,且可能多次重试。
三、本地消息表:像“写备忘录+定期检查”
1.
写备忘录:比如订单服务在完成本地事务(生成订单)后,同时往数据库里写一条“待处理消息”(比如“通知支付系统”)。
2.
定期检查:另一个服务(支付系统)定时扫描消息表,看到待处理消息后,执行操作(比如扣款),并标记消息为“已处理”。
3.
失败重试:如果支付失败,订单服务会重发消息,直到成功。 优点:依赖数据库,实现简单;确保消息最终被处理。 缺点:需要额外消息表,可能增加复杂性。
四、可靠消息最终一致性:像“发重要邮件+回执确认”
1.
发消息:订单服务发送消息到消息队列(如RocketMQ),消息队列保证消息不丢失。
2.
确认送达:消息队列收到消息后,回复“已收到”。
3.
执行并确认:支付系统从队列消费消息,执行扣款,并发送“处理结果”到另一个队列。
4.
检查状态:订单服务定期检查支付结果,如果失败就重发消息。 优点:消息可靠,最终一致性;适合高并发场景。 缺点:依赖消息队列,需要处理消息重复消费的问题。
五、最大努力通知:像“发普通快递+多次尝试”
1.
发通知:比如订单完成后,发短信通知用户,不管是否成功。
2.
多次重试:如果失败,定期重试发送,直到成功或达到次数上限。 适用场景:对一致性要求不高,允许少量失败(比如通知类业务)。
如何选择?
●
强一致性(必须全部成功):用2PC或TCC(但TCC更灵活)。
●
允许最终一致性(可以等一会儿):用本地消息表或可靠消息队列。
●
简单场景:本地消息表或最大努力通知。
●
高并发、复杂场景:可靠消息队列(如RocketMQ + Seata框架)。
总结: 分布式事务没有“万能解法”,需要根据业务场景选合适的方案。核心思想是:要么全部成功,要么全部回滚,避免数据混乱。如果允许数据短暂不一致(比如几秒后自动修复),可以用消息队列;如果对一致性要求极高(如银行转账),可能需要更复杂的方案。
群交流(262200309)

浙公网安备 33010602011771号