从银行转账失败到分布式事务:总结与思考
从银行转账失败到分布式事务总结与思考引言在日常生活中银行转账失败并不罕见。你可能遇到这样的情况转出账户扣款成功但转入账户迟迟未到账。这种看似简单的“扣款成功但到账失败”现象背后隐藏着分布式系统中数据一致性的核心难题。从单体架构到微服务、从单机事务到分布式事务技术演进的过程本质上是对“正确性”与“可用性”之间的平衡。本文将从银行转账失败的场景出发深入剖析分布式事务的原理并提供可运行的代码示例带你理解如何设计一个可靠的转账系统。## 银行转账的“朴素”实现为什么它不可靠假设你正在设计一个简单的银行转账系统。最直接的思路是在数据库中对两个账户进行更新操作。例如用 Python 模拟一个单机事务pythonimport sqlite3def transfer(from_account, to_account, amount): conn sqlite3.connect(bank.db) cursor conn.cursor() try: # 开始事务 cursor.execute(BEGIN TRANSACTION) # 从源账户扣款 cursor.execute(UPDATE accounts SET balance balance - ? WHERE id ?, (amount, from_account)) # 检查扣款后余额是否不足模拟业务校验 cursor.execute(SELECT balance FROM accounts WHERE id ?, (from_account,)) if cursor.fetchone()[0] 0: raise Exception(Insufficient balance) # 向目标账户加款 cursor.execute(UPDATE accounts SET balance balance ? WHERE id ?, (amount, to_account)) # 提交事务 conn.commit() print(Transfer success) except Exception as e: # 回滚事务 conn.rollback() print(fTransfer failed: {e}) finally: conn.close()这段代码在单机数据库环境中是可靠的因为事务保证了 ACID原子性、一致性、隔离性、持久性。然而当系统分布到多个服务例如账户服务、通知服务、审计服务时问题就出现了。如果扣款成功但通知服务宕机用户可能以为转账失败而重复操作导致数据不一致。这就是分布式事务要解决的核心问题。## 分布式事务的挑战CAP 理论与最终一致性在分布式系统中我们无法同时满足一致性、可用性和分区容忍性CAP 理论。银行转账场景通常要求强一致性即“扣款成功”与“加款成功”必须同时发生或同时回滚。但网络分区如服务宕机不可避免因此需要引入分布式事务协议。常见的分布式事务模型包括-2PC两阶段提交在协调者与参与者之间分阶段征询和提交但存在阻塞问题和单点故障风险。-TCCTry-Confirm-Cancel业务层面的补偿机制通过预留资源、确认操作、取消操作来实现最终一致性。-Saga长事务将大事务拆分为多个本地事务通过补偿事务Undo处理失败情况。下面以 Saga 模式为例用 Python 模拟一个跨服务的转账流程。## 实战用 Saga 模式实现分布式转账Saga 的核心思想是每个操作都有对应的补偿操作。当某个步骤失败时事务管理器会依次执行之前的补偿操作来撤销已执行的动作。以下是一个简化的实现pythonimport timefrom typing import Dict, List, Callableclass SagaTransaction: def __init__(self): self.steps: List[Dict[str, Callable]] [] def add_step(self, action: Callable, compensate: Callable): 添加一个步骤action 为正常操作compensate 为补偿操作 self.steps.append({action: action, compensate: compensate}) def execute(self): 执行 Saga 事务 executed [] # 记录已成功执行的步骤索引 for i, step in enumerate(self.steps): try: step[action]() executed.append(i) print(fStep {i} executed successfully) except Exception as e: print(fStep {i} failed: {e}) # 回滚已执行的操作 for j in reversed(executed): try: self.steps[j][compensate]() print(fCompensated step {j}) except Exception as comp_error: print(fCompensate for step {j} failed: {comp_error}) return False return True# 模拟账户服务状态account_balances {A: 1000, B: 0}def debit(from_id, amount): 扣款操作 if account_balances[from_id] amount: raise Exception(Insufficient balance) account_balances[from_id] - amount print(fDebited {amount} from {from_id})def compensate_debit(from_id, amount): 扣款的补偿操作加回金额 account_balances[from_id] amount print(fCompensated: added {amount} back to {from_id})def credit(to_id, amount): 加款操作模拟可能失败的情况 # 假设加款服务有 50% 概率失败 if time.time() % 2 0: raise Exception(Credit service unavailable) account_balances[to_id] amount print(fCredited {amount} to {to_id})def compensate_credit(to_id, amount): 加款的补偿操作扣除金额 account_balances[to_id] - amount print(fCompensated: deducted {amount} from {to_id})# 构建 Saga 事务saga SagaTransaction()saga.add_step( actionlambda: debit(A, 100), compensatelambda: compensate_debit(A, 100))saga.add_step( actionlambda: credit(B, 100), compensatelambda: compensate_credit(B, 100))# 执行success saga.execute()print(fTransaction {succeeded if success else failed})print(fFinal balances: A{account_balances[A]}, B{account_balances[B]})运行这段代码你会看到如果扣款成功但加款失败系统会自动触发补偿操作将扣款回滚从而保证最终一致性。注意Saga 模式属于“最终一致性”而非“强一致性”因为补偿操作本身也可能失败需要结合重试、幂等性设计来完善。## 深入原理2PC 与 TCC 的对比### 两阶段提交2PC2PC 通过协调者Coordinator和参与者Participant之间的两次交互来实现原子性-准备阶段协调者询问所有参与者是否准备好提交。参与者需要锁定资源并返回“是/否”。-提交阶段如果所有参与者都同意协调者发送提交指令否则发送回滚指令。2PC 的缺点在于参与者锁定资源期间会阻塞其他事务且协调者是单点故障。如果协调者宕机参与者可能一直处于锁定状态。### TCC 模式TCCTry-Confirm-Cancel是一种业务层面的 2PC 变种-Try预留业务资源如锁定账户资金。-Confirm确认执行业务如实际转账。-Cancel取消预留资源如释放锁定。TCC 避免了 2PC 的数据库锁问题但要求业务接口支持幂等性因为网络重试可能导致重复操作。例如转账的 Try 阶段将资金从可用余额转移到冻结余额Confirm 阶段将冻结余额转移到目标账户Cancel 阶段将冻结余额归还。## 总结从银行转账失败的简单场景出发我们看到了分布式事务并非银弹。2PC 提供强一致性但牺牲了性能和可用性Saga 和 TCC 通过补偿机制实现最终一致性但要求业务逻辑精心设计。在实际系统中需要根据业务场景权衡-金融交易如转账、支付通常要求强一致性可考虑 2PC 或 TCC但需做好超时和重试。-订单系统如下单、扣库存适合 Saga允许短暂不一致通过异步补偿恢复。-日志、通知等非关键操作可以接受最终一致性甚至使用消息队列幂等性设计。分布式事务的实践本质是“权衡”——通过牺牲部分性能或一致性换取系统的可用性和扩展性。没有完美的方案只有最适合当前场景的设计。希望本文能帮助你从原理到实践更清晰地理解分布式事务的本质。

相关新闻

Django毕设选题推荐:基于 Django 的高校荣誉奖项信息化管理平台设计实现 学生获奖信息收录与证书管理系统【附源码、mysql、文档、调试+代码讲解+全bao等】

Django毕设选题推荐:基于 Django 的高校荣誉奖项信息化管理平台设计实现 学生获奖信息收录与证书管理系统【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/10/2 4:54:27 阅读更多 →
Python计算机毕设之基于 Web 的适老化健康守护预警系统 基于 Python 的老年人健康状态追踪与异常告警管理系统(完整前后端代码+说明文档+LW,调试定制等)

Python计算机毕设之基于 Web 的适老化健康守护预警系统 基于 Python 的老年人健康状态追踪与异常告警管理系统(完整前后端代码+说明文档+LW,调试定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/10/2 0:33:36 阅读更多 →
Python计算机毕设之基于 Django 的音乐发布与社区交流系统 智能音乐推荐与好友分享平台设计(完整前后端代码+说明文档+LW,调试定制等)

Python计算机毕设之基于 Django 的音乐发布与社区交流系统 智能音乐推荐与好友分享平台设计(完整前后端代码+说明文档+LW,调试定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/9/22 19:07:55 阅读更多 →

最新新闻

Qwen团队变动后开发者指南:部署微调与API接入全攻略

Qwen团队变动后开发者指南:部署微调与API接入全攻略

你的技术群里有没有被同一条消息刷屏?说的是Qwen技术负责人和多名核心团队成员离职。这件事我听到的时候第一反应是去翻官方公告,结果没看到正式说明,倒是各种猜测已传得满天飞。今天不聊八卦,从一个天天拿Qwen做项目的开发者的角…

2026/10/3 10:54:53 阅读更多 →
Oracle数据卸载模板:Shell脚本编排与SQL执行实践

Oracle数据卸载模板:Shell脚本编排与SQL执行实践

简介:这是一份面向数据仓库与ETL开发人员的Oracle数据卸载Shell脚本模板,适合需要将库内数据按批次导出为文本并完成后续传输的运维与开发场景。使用者只需在SQL模板文件中填写待卸载的查询语句,并在文件名配置中指定对应输出名称&#xff0c…

2026/10/3 10:54:53 阅读更多 →
Oracle数据模板卸载脚本实战:shell驱动sqlplus的避坑指南

Oracle数据模板卸载脚本实战:shell驱动sqlplus的避坑指南

简介:这份资源是一套面向数据仓库与ETL开发人员的Oracle数据卸载Shell脚本模板,适合需要将库内数据按批次导出为文本文件并完成后续传输的工程师使用。包内共4个文件,包含1个sh主脚本、1个config环境配置、2个txt模板文件,压缩包仅…

2026/10/3 10:54:53 阅读更多 →
Unity资产库工具:从素材混乱到URP转换与植被自动化的流水线

Unity资产库工具:从素材混乱到URP转换与植被自动化的流水线

1. 从素材混乱到资产流水线:我为什么要做这个工具做Unity项目超过三年的人,大概率都经历过同一个噩梦:项目文件夹里躺着十几个来源不同的素材包,有的是Asset Store买的,有的是外包给的,有的是从旧项目里扒出…

2026/10/3 10:54:53 阅读更多 →
Unity内存泄漏实战:事件订阅为何导致GC失效及根治方案

Unity内存泄漏实战:事件订阅为何导致GC失效及根治方案

1. 从一个真实的内存泄漏案例说起 前阵子帮朋友排查一个 Unity 项目,场景是这样的:一个卡牌游戏,战斗界面反复打开关闭,每次关闭再打开,内存就往上蹿一截,打开个二三十次,低端机上直接闪退。朋友…

2026/10/3 10:54:53 阅读更多 →
DRV8818+STM32F469工业级步进电机高精度控制实战

DRV8818+STM32F469工业级步进电机高精度控制实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 10:53:53 阅读更多 →

日新闻

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南 【免费下载链接】ex-skill 前任 skill 项目地址: https://gitcode.com/gh_mirrors/exsk/ex-skill 前任.skill 是一个运行在 Claude Code 上的开源 Skill:导入微信、iMessage、短信、…

2026/10/3 0:00:27 阅读更多 →
45个经典Linux面试题:从命令到网络排障的完整考点解析

45个经典Linux面试题:从命令到网络排障的完整考点解析

刚开始带应届生的时候,我最头疼的就是他们拿着一摞Linux面试题背得滚瓜烂熟,一上机全露馅。后来自己从被面的人变成面别人的人,才慢慢摸清楚:Linux面试题考的根本不是答案本身,而是你面对一个不确定的系统问题时&#…

2026/10/3 0:01:28 阅读更多 →
SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

简介:本资源是一份面向SAP ABAP开发人员、生产计划专员及ERP实施顾问的实操型操作指南,聚焦SAP生产预留核心业务场景,系统解决物料预留创建、查询、校验与批量处理等高频问题。文档以结构化方式覆盖预留背景原理、OMC2编码规则、工厂级参数配…

2026/10/3 0:01:28 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/3 9:14:33 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/3 9:47:50 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/10/3 9:42:31 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:35 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:36 阅读更多 →