支付系统的分布式事务:两阶段提交与 TCC 的落地对比
📅 2026/7/23 1:44:26
👁️ 次浏览
支付系统的分布式事务两阶段提交与 TCC 的落地对比一、一笔支付背后可能涉及三个服务、两个数据库和一个第三方在电商支付链路中一笔典型的支付操作涉及以下步骤扣减用户账户余额、创建支付订单、调用第三方支付渠道、增加商家收款记录。这四个步骤发生在三个不同的服务里账户服务、订单服务、支付网关各自的数据库是独立的。如果这四个步骤在一个单体数据库事务中BEGIN→ 执行四个操作 →COMMIT一致性由数据库保障。但在微服务架构下这四个步骤跨了三个数据库传统的事务语义失效了。扣减余额成功了但创建订单失败了——用户的余额少了商家也没收到钱。这就是分布式事务要解决的核心问题。二、两阶段提交的机制与致命缺陷两阶段提交2PC是分布式事务最经典的理论方案但也是生产环境中最少直接使用的方案。第一阶段投票阶段协调者向所有参与者发送准备提交请求。每个参与者在本地执行事务逻辑但不提交然后返回就绪或中止。第二阶段提交阶段如果所有参与者都返回就绪协调者发送提交请求所有人正式提交。如果有一个参与者返回中止协调者发送回滚请求。2PC 的核心问题是同步阻塞。在第一阶段完成后所有参与者都必须保持事务打开状态等待协调者的第二阶段指令。如果协调者宕机了参与者就会一直等待——锁资源数据库行锁、连接等全部被挂起的事务持有其他请求无法访问这些数据。这就是所谓的阻塞协议的代价。2PC 还有一个单点故障问题。协调者是整个协议的核心如果它在第二阶段发送指令时宕机部分参与者收到了提交请求另一些没收到——数据就不一致了。三、TCC 的补偿机制TCCTry-Confirm-Cancel是 2PC 的一种工程化改良引入了补偿的概念。Try 阶段预留资源。不真正执行扣减而是冻结或预占。比如冻结账户余额可用余额减少冻结金额增加创建状态为待确认的订单。Confirm 阶段所有参与者 Try 成功后执行真正提交。把冻结金额转为实际扣款把订单状态改为已支付。Cancel 阶段任一参与者 Try 失败后所有参与者回退 Try 操作。解冻余额取消订单。TCC 相比 2PC 的核心改进是Try 阶段不持有长时间锁。资源预留如冻结余额是一个状态变更不需要数据库事务一直挂起等待。即使 Confirm 阶段的服务宕机了也可以通过定时任务扫描待确认状态的记录重新执行 Confirm。/** * TCC 分布式事务的转账实现 * * 场景从账户 A 转账 100 元到账户 B * * 为什么 TCC 比 2PC 更实用 * 1. Try 阶段不持有锁只做资源预留 * 2. Confirm/Cancel 都是幂等操作可重试 * 3. 有明确的补偿路径Cancel 回退 Try */ public class TccTransferService { /** * Try 阶段尝试预留资源 * * 原则只预留不真正扣减 */ public boolean tryTransfer(String fromAccount, String toAccount, int amount, String tccId) { // 冻结转出方余额 // INSERT INTO frozen_record(tcc_id, account, amount) VALUES(...) // UPDATE account SET available available - amount WHERE ... // 约束available 0防止超额冻结 boolean frozen accountService.freeze(fromAccount, amount, tccId); if (!frozen) { return false; // 余额不足Try 失败 } // 创建待确认的转账记录 transferDao.insertPendingTransfer(tccId, fromAccount, toAccount, amount); return true; } /** * Confirm 阶段确认提交 * * 原则必须是幂等的可能被重试多次 */ public void confirmTransfer(String tccId) { TransferRecord record transferDao.getByTccId(tccId); if (record null || CONFIRMED.equals(record.getStatus())) { return; // 幂等已确认的跳过 } // 解冻 → 真正扣款 accountService.confirmFreeze(record.getFromAccount(), record.getAmount(), tccId); // 增加收款方余额 accountService.credit(record.getToAccount(), record.getAmount()); // 更新记录状态 transferDao.updateStatus(tccId, CONFIRMED); } /** * Cancel 阶段回滚 * * 原则必须是幂等的补偿 Try 阶段的所有操作 */ public void cancelTransfer(String tccId) { TransferRecord record transferDao.getByTccId(tccId); if (record null || CANCELLED.equals(record.getStatus())) { return; // 幂等已取消的跳过 } // 解冻余额 accountService.unfreeze(record.getFromAccount(), record.getAmount(), tccId); // 更新记录状态 transferDao.updateStatus(tccId, CANCELLED); } }四、TCC 的实践难点TCC 理论上是优雅的但实践中三个难点。业务逻辑的侵入性在单体应用的简单转账逻辑中只有一行余额 A 减 100余额 B 加 100。但在 TCC 模式下需要把这个逻辑拆成 Try冻结余额 A、Confirm真正扣 A 加 B、Cancel解冻 A三个方法。代码量翻了 3 倍。空回滚Cancel 可能在 Try 之前被调用比如 Try 请求超时协调者以为失败了就调了 Cancel但 Try 其实还没执行。Cancel 方法需要能处理没冻结但收到解冻请求的情况。幂等设计Confirm 和 Cancel 都可能被重试。必须在数据库层面设计好幂等键用 tcc_id 作为唯一约束否则重复执行会出大问题。五、总结分布式事务没有银弹。2PC 理论完美但工程上难以落地同步阻塞、单点故障。TCC 是更实用的方案用补偿机制替代了同步等待每个阶段都是独立的、幂等的、可重试的操作。但 TCC 的侵入性很高——它要求业务模型在设计时就支持 Try-Confirm-Cancel 三段式。对于简单的场景用本地消息表实现最终一致性可能比 TCC 更合适。技术方案没有绝对的优劣只有和场景的匹配度。
大型 SaaS 产品的 Vite 迁移实录:从 Webpack 到 Vite 的 6 个月演进
一、迁移背景与前期评估
该项目为面向企业客户的 SaaS 平台,前端仓库包含 32 个子应用(微前端架构),总模块数超过 6800 个。技术栈为 React 18 Typ…
📅 2026/7/23 0:08:15
AI 服务流量回放:用历史请求构建推理服务回归测试集
一、你的推理服务升级了新模型,测试集准确率涨了,线上用户投诉翻了倍
推理服务的回归测试有一个独特的难题:测试集的分布和真实流量的分布经常不一致。你的测试集覆盖了 100 类…
📅 2026/7/22 21:14:19
推理 GPU 的碎片化治理:小模型合卡与大模型独占策略
一、你的 8A100 集群 GPU 利用率 35%,但新任务调度不上去——全是碎片
GPU 集群的碎片化问题比 CPU 集群更严重,因为 GPU 的"资源粒度"是整卡。你不能把 0.3 张 A100 分配给一个…
📅 2026/7/21 0:32:55
1. 项目概述最近在分析AI技术对就业市场的影响时,我发现了一个有趣的现象:以ChatGPT为代表的大语言模型正在重塑劳动力市场的信息传递方式。这种变化不仅体现在求职招聘环节,更深刻地影响了整个职业发展路径中的信息透明度。作为从业者&#…
📅 2026/7/23 1:43:59
1. 为什么选择Python作为深度学习的第一语言当我在2016年第一次接触深度学习时,面临的首要问题就是选择哪种编程语言。经过多方比较和实践验证,Python最终成为我的不二之选。这不仅因为其简洁的语法特性,更因为其背后庞大的生态系统支持。Pyt…
📅 2026/7/23 1:43:59
1. 项目概述:为什么Linux新手需要这份指南?如果你刚接触Linux,尤其是从Windows或macOS转过来,想远程控制另一台电脑,第一反应可能是找熟悉的TeamViewer或者AnyDesk。但当你兴冲冲地去官网下载时,却发现它们…
📅 2026/7/23 1:43:59
1. 为什么传统优化方案越来越失效?前端性能优化领域有个有趣的现象:每当有人提出"页面加载慢怎么办"的问题,90%的开发者会条件反射般回答"启用Gzip压缩"、"配置CDN加速"、"合并静态资源"这三板斧。这…
📅 2026/7/23 1:43:59
1. 阿里云语音合成API核心功能解析阿里云实时语音合成API基于WebSocket协议实现文本到语音的实时转换,其核心能力可归纳为三大技术维度:多模态语音输出控制支持MP3/PCM音频格式输出采样率可在8k-48kHz间灵活配置提供音量(0-100)、…
📅 2026/7/23 1:43:59
你是不是也遇到过那种看着高大上,实际用起来全是坑的所谓“科学世界”?这篇内容直接告诉你,怎么在 geo science world 里找到真正有价值的信息,而不是被一堆花里胡哨的包装给绕晕。看完这篇,你不仅能分清真假,还能学会怎么高效利用这些资源,省下不少冤枉钱和时间。咱们说…
📅 2026/7/23 1:43:17
更多请点击:
https://intelliparadigm.com
第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…
📅 2026/7/23 0:00:26
最近好多同行在群里问 geo s1230 到底值不值得买。说实话,这机器在二手市场挺火。但水很深,新手很容易踩雷。我干了十年设备维护,见过太多冤大头。今天不扯虚的,直接上干货。先说价格,心里得有底。目前成色不错的二手货,大概在一万二到一万五之间。如果低于八千,别犹豫,…
📅 2026/7/23 0:01:16
更多请点击:
https://codechina.net
第一章:AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析 在对2,346篇跨行业AI生成文案的A/B测试数据进行聚类分析后,我们发现࿱…
📅 2026/7/23 0:01:26
1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…
📅 2026/7/23 1:06:38
1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…
📅 2026/7/23 1:06:38
更多请点击:
https://intelliparadigm.com
第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…
📅 2026/7/23 1:06:38
目录
第一步:选对模板,省心一半
第二步:打开扫码点餐功能
开启功能按钮
桌台管理与桌码生成
第三步:个性化设计,打造品牌感
调整点餐页面
设置点餐规则 你还在让顾客站着排队点餐吗?2025年ÿ…
📅 2026/7/22 7:05:39
在业务中快速构建一个能理解私有文档、准确回答专业问题的智能助手,是很多开发团队面临的共同挑战。传统方案往往需要从零开始搭建复杂的 RAG(检索增强生成)系统,涉及文档解析、向量化、检索、大模型调用等多个环节,整…
📅 2026/7/22 17:06:14
FAE放射组学分析工具:医学影像特征探索的完整解决方案 【免费下载链接】FAE FeAture Explorer 项目地址: https://gitcode.com/gh_mirrors/fae/FAE
你是否曾经面对海量医学影像数据感到无从下手?想要从CT、MRI等影像中提取有价值的定量特征&#…
📅 2026/7/22 5:05:32