分布式事务没有银弹:从CAP定理到AT与TCC模式的选择指南

简介: 分布式事务为什么没有万能方案?本文从CAP定理与BASE理论讲起,对比AT模式、TCC模式的原理与坑点(脏写、空回滚、事务悬挂),帮你避开踩过的坑。

大家好,我是晚安code。

假设一个场景:线上一个用户下单,余额扣了、库存也扣了,订单却显示未支付。排查到最后,是订单库、账户库、库存库三个库各改各的,谁也管不了谁。这是分布式事务上的第一课:跨库操作没有本地事务兜底,出问题只是早晚的事。

一、一个扣款场景,把问题逼出来

分布式事务要解决的,不是"一次操作改多个地方",而是"多个地方要么同时成功、要么同时失败"。

本地事务(Local Transaction):在同一个数据库内完成的事务,要么全部提交,要么全部回滚。你可以理解为"同一本账本上的记录,错了一整页都能涂掉重写"。

用生活里的场景类比:三个人合租,住在 1 楼、3 楼、5 楼,晚上要同时关灯,得挨个通知。只要中间有一层没听到,就有一个人摸黑进门。跨库操作就是这种"挨个通知"的活,而本地事务只会管自己那盏灯。

分布式事务(Distributed Transaction):跨越多个数据库或服务的操作集合,要求所有参与方要么一起成功、要么一起回滚。你可以理解为"几本分处各地的账本,想在同一时刻改对"。

这篇文章我打算把分布式事务从原理到落地串一遍:先看 CAP 定理为什么让这条路这么难走,再看 BASE 理论给出的妥协方案,最后对比 AT 模式和 TCC 模式这两种主流实现,以及它们各自的坑。收藏一下,我们开始。

二、CAP定理:分布式系统的天花板

在 CAP 定理里,分区容错是必选项,一致性和可用性只能二选一。

CAP 定理(Consistency, Availability, Partition tolerance):分布式系统不可能同时满足一致性、可用性、分区容错性,最多同时保证其中两个。你可以理解为"酒店的地点、价格、房间大小,最多让你挑两个满意"。

三个指标拆开看:

1)一致性(Consistency):用户访问任意节点,读到的数据必须一样。node01 改了余额,node02 必须跟着变,否则用户换个节点就查到旧账。

2)可用性(Availability):读或写总能成功。只能读不能写、只能写不能读,或者都执行不了,都算弱可用或不可用。

3)分区容错(Partition tolerance):节点之间的网络断了,系统也要继续对外服务。Partition 就是网络故障把系统劈成几个互不相通的"孤岛"。

关键矛盾在这:网络不会 100% 保证畅通,分区一定会出现;而系统又必须持续运行。所以分区容错是硬指标,所有分布式系统都得满足。剩下的,只能在一致性和可用性里挑一个:

  • 选可用性(AP):节点继续读写,但同步不了的节点数据不一致,事后靠补偿慢慢收敛。
  • 选一致性(CP):把数据锁住,等网络恢复再放行,期间系统不可用或只能读。

现实就是这么不讲道理——只要网络会断,你就得在 A 和 C 之间二选一。

把取舍画成流程图,一眼就能看懂。看图 1:网络分区一旦出现,往左走是 AP,数据先乱一阵再收敛;往右走是 CP,先锁住不动,一致但不可用。

分布式事务的CAP定理取舍:网络分区后选择AP保可用性还是CP保一致性

贪心抱三个球只会全掉,认清只能选两个反而踏实

三、BASE理论:不强一致,但最终一致

BASE 理论放弃的不是一致性,而是强一致性——把"必须立刻一致"换成"最后一致就行"。

BASE 理论(Basically Available, Soft State, Eventually Consistent):分布式系统允许损失部分可用性、出现中间状态,最终把数据收敛到一致。你可以理解为"先把事办了,睡前保证把账平掉"。

三个词各管一段:

  • 基本可用(Basically Available):出故障时损失部分可用性,保住核心功能。抢购高峰让你排队等一会儿,而不是直接 502。
  • 软状态(Soft State):允许存在中间状态,比如数据暂时对不上。
  • 最终一致性(Eventually Consistent):不要求立刻一致,但中间状态结束之后,数据最终会一致。

顺着 BASE 的思路,分布式事务的解法分成两个方向:

  • AP 思想:各分支各自执行、各自提交,不锁数据。允许结果不一致,之后用补偿手段恢复,实现最终一致性。AT 模式走这条路。
  • CP 思想:各分支执行完先不提交,等彼此的提交结果,再一起提交或回滚。期间锁住资源,数据不可用,但保证一致。XA 模式走这条路。

所以分布式事务从来没有"一种标准答案",关键是先想清楚:你打算牺牲一致性,还是可用性?

四、AT模式:框架帮你补偿,但别忽视脏写

AT 模式最大的卖点是不用写补偿代码,代价是并发场景下容易踩脏写的坑。

AT 模式(Automatic Transaction):Seata 提供的一种分布式事务实现,利用数据快照自动回滚,开发者几乎无感。你可以理解为"系统定期给你的数据拍照,出事就按照片恢复"。

坦白讲,我最早就是无脑选了 AT 模式,因为它接入成本最低,几个注解就搞定。它分两个阶段走:

阶段一:每个分支事务执行前,先记录数据快照,再正常执行、正常提交。

阶段二:全局协调者汇总各分支的结果——全部成功,说明事务在阶段一已经提交完了,这里只需要删掉快照;只要有分支失败,就按快照把数据恢复到更新前,再删快照。

这个两阶段流程用文字说容易绕,看图 2,重点看阶段二的两个出口。

分布式事务AT模式两阶段流程:阶段一记录快照并提交,阶段二全成功删快照或按快照回滚

大多数场景下,AT 模式确实省心。但在极端情况,尤其是多线程并发访问同一个 AT 事务里的数据时,会出现脏写——某个分支回滚,把另一个事务刚写入的新值,一并覆盖回旧值了。

两个线程同时改同一条库存记录,一个事务回滚,另一个线程刚提交的新值被快照覆盖,账又对不上。排查了整整一天,最后锁定位在脏写。好家伙,快照回滚居然能滚出脏数据,这谁能想到?

解决办法是引入全局锁:在分支释放数据库锁之前,先拿到全局锁,保证同一时刻只有一个事务能操作这条数据,回滚时就不会踩到别人刚写的东西。

可能有人会问:AT 模式加了全局锁,并发性能不就废了吗?

这就是取舍。全局锁把冲突行的并发度压到 1,多个线程抢同一行时吞吐明显下降。以我现在的经验,写冲突不严重、读多写少的业务用 AT 很划算;写热点集中的场景,老老实实考虑 TCC 或者消息队列。

五、TCC模式:补偿逻辑自己写,更可控

TCC 模式牺牲了编码量,换来的是对补偿过程的完全掌控,适合高并发和补偿逻辑复杂的业务。

TCC 模式(Try-Confirm-Cancel):把分布式事务拆成预留、确认、取消三个阶段,三个方法都由开发者手写。你可以理解为"先交定金把东西占住,再付尾款,反悔了就退定金"。

三个方法各管一件事:

  • try:检查并预留资源。比如检查余额够不够,够就先把要扣的金额冻结起来。
  • confirm:真正完成业务。前提是 try 成功了,confirm 一定要能成功——confirm 里只放不会失败的收尾动作。
  • cancel:释放预留的资源,是 try 的反向操作。

用一个扣款例子串一遍。账户 A 余额 100,要扣 30:

1)Try:余额充足,冻结 30,可用余额变 70。此时总余额(冻结 + 可用)还是 100,分支事务直接提交,不用等别的分支。

2)Confirm:可用余额已经扣过了,直接把冻结的 30 划走,总余额变 70。

3)Cancel:释放冻结,冻结的 30 归零,可用余额回到 100。

TCC 的核心思想一句话就能讲透:扣款不直接扣,先锁进一个"冻结"口袋。看图 4 会更直观。

扣款不直接扣,先锁进冻结口袋,总余额保持不变

但 TCC 的坑也藏在手写逻辑里。一个分布式事务里有两个分支,try 阶段分支 A 成功、分支 B 阻塞。阻塞太久,全局事务超时,二阶段 cancel 触发,两个分支都要执行 cancel——可分支 B 压根没执行过 try。

空回滚(Empty Rollback):分支事务还没执行 try 就被要求 cancel,此时 cancel 必须什么都不做。你可以理解为"客人还没进店,店员就开始退他定金了"。

更麻烦的是,分支 B 的 try 阻塞结束后还会继续执行——但全局事务已经结束了,永远不会有 confirm 或 cancel 再来。这个事务只执行了一半,悬在那里:

事务悬挂(Transaction Suspension):分支的 try 被阻塞,全局事务已超时结束,阻塞结束后 try 才执行,整个事务永远收不了尾。你可以理解为"主人全家都出门了,客人还站在门口按门铃"。

try 还没执行,cancel 先到了;主人走了,客人还在门口。这两个问题不处理,线上迟早出事。

好在解法也明确:写 try 和 cancel 时维护一张事务状态表。只有 try 成功记录过,cancel 才允许真正回滚;try 执行前先查状态,确认全局事务还活着再动手。

六、怎么选:没有银弹,只有取舍

分布式事务没有银弹,选方案的本质,是选"你能接受哪方面的损失"。

方案 补偿方式 代码量 并发表现 适合场景
XA(CP) 数据库两阶段提交 低(锁资源) 金融级强一致
AT 模式(AP) 框架快照自动回滚 常规业务快速接入
TCC 模式(AP) 手写 try/confirm/cancel 高并发、补偿逻辑复杂

绝大多数业务用 AT 模式就能撑住,重点别把它当银弹;写热点集中、补偿逻辑绕的场景,才值得为 TCC 多写那几个方法。

可能有人会问:消息队列(本地消息表、事务消息)算不算分布式事务方案?

算。它是另一种思路——先把本地改动落库,再把"要通知下游"这个动作也可靠地投递出去,靠消息做到最终一致。好处是彻底不锁资源,坏处是做不到同步强一致,下游消费有延迟。选哪种,看你的业务能接受多少延迟。

说白了,每一类分布式事务方案,都是在"一致性、可用性、代码量"三者里做减法。在我这边,能异步走消息队列的优先消息队列,其次 TCC,AT 模式适合快速接入,XA 只留给真正必须强一致的核心链路。

我是晚安code,持续分享编程干货。觉得有用的话记得点赞收藏和关注~也欢迎在评论区聊聊:你在项目里用过哪种分布式事务方案,有没有被脏写或空回滚坑过?

目录
相关文章
|
7天前
|
云安全 人工智能 运维
阿里云联动百位企业安全专家,共识Agent防御最佳实践
当Agent成为新员工,你的安全边界在哪里?
1922 6
阿里云联动百位企业安全专家,共识Agent防御最佳实践
|
5天前
|
存储 人工智能 关系型数据库
阿里云AI产品与云产品最新组合套餐:Token Plan、AI coding及云服务器和建站等组合优惠价
阿里云推出全新“算力+模型+应用”一站式云与AI组合套餐活动,覆盖从个人开发者到中大型企业的全场景需求。核心亮点为分三档定价的Token Plan订阅服务,支持Qwen3.8-Max-Preview大模型调用,错峰时段最低可享0.2折优惠。活动同步推出AI Coding、智能体部署、云电脑托管、0代码建站等十余类场景化组合,搭配99元/年的普惠云服务器、88元/年的入门数据库等经典特惠产品,还为企业提供1V1定制化AI转型方案,大幅降低了不同用户群体拥抱AI的技术门槛与采购成本。
652 111
|
15天前
|
人工智能 JSON 安全
Fastjson远程代码执行漏洞,阿里云AI安全为您保驾护航
阿里云AI安全产品联动防御Fastjson攻击
2556 13
Fastjson远程代码执行漏洞,阿里云AI安全为您保驾护航
|
7天前
|
人工智能 弹性计算 数据库
阿里云优惠券种类解析:主要券种区别和适用群体及领取和使用指南
2026年阿里云构建了覆盖全用户的七类优惠券,本文逐一拆解了每类优惠券的核心规则、适用人群与使用技巧:大促限定的阶梯满减券分个人、企业双通道,最高可减800元;学生专属300元无门槛券支持全品类通用;按量付费用户可参与消费达标返券形成循环优惠;新用户有低门槛专享满减券尝鲜;老用户可领取系统自动发放的随机福利券;中大型企业迁云可申请最高100万元的专项补贴;云产品通用券还能在活动价基础上实现折上折。不同身份、不同采购场景的用户均可通过精准匹配对应优惠券,最大化享受优惠力度。
462 110
阿里云优惠券种类解析:主要券种区别和适用群体及领取和使用指南
|
13天前
|
人工智能 前端开发 Linux
Codex 桌面版安装 + CC Switch 接入第三方 API 完整教程(2026 最新)
2026最新教程:手把手教你安装Codex桌面版,通过CC Switch v3.17.0一键接入Fenno等国产API(兼容OpenAI Responses格式),跳过账号登录,完整启用代码审查、多步任务与上下文感知功能。零基础友好,全程图文实操。(239字)
1620 2
|
15天前
|
人工智能 自然语言处理 数据挖掘
Qwen3.8-Max-Preview深度全解析:2.4万亿参数旗舰MoE模型+Token Plan限时优惠完整落地指南
2026年7月,全新旗舰级混合专家大模型Qwen3.8-Max-Preview正式开放抢先体验,作为通义千问Qwen3系列规格最高、综合推理能力顶尖的新一代模型,该模型总参数量达到2.4万亿(2.4T),是当前线上可调用的原生多模态旗舰模型,综合推理水准对标海外顶级Fable 5模型,在复杂工程开发、长文档深度分析、多步骤智能体自治、跨境多语言创作、海量数据挖掘五大高难度业务场景实现跨越式性能提升。
1428 2
|
17天前
|
人工智能
Qwen3.8抢先体验!正式版即将发布并开源!
千问Qwen3.8即将开源,参数达2.4T,进化速度以“天”计,实力媲美Fable 5。预览版Qwen3.8-Max已上线阿里Token Plan等平台,限时优惠:日间Credits低至1折,夜间更优,个人/团队版月付仅35元起!
1499 55
|
2天前
Qoder 一周年 × Qwen3.8-Max 正式上线,多重好礼限时领
8月3日,Qwen3.8-Max 正式上线Qoder,迎来Qoder一周年。新老用户可领800次免费调用,下单再赠2000次;夜间(22:00–08:00)调用5折;邀请好友双方得积分与调用额度。
249 0