首页/新闻资讯/正文详情

从银行转账失败到分布式事务:总结与思考

发布时间:2026/11/5 16:37:01 来源:云帆数科 栏目:资讯中心
从银行转账失败到分布式事务:总结与思考
从银行转账失败到分布式事务总结与思考引言在日常生活中银行转账失败并不罕见。你可能遇到这样的情况转出账户扣款成功但转入账户迟迟未到账。这种看似简单的“扣款成功但到账失败”现象背后隐藏着分布式系统中数据一致性的核心难题。从单体架构到微服务、从单机事务到分布式事务技术演进的过程本质上是对“正确性”与“可用性”之间的平衡。本文将从银行转账失败的场景出发深入剖析分布式事务的原理并提供可运行的代码示例带你理解如何设计一个可靠的转账系统。## 银行转账的“朴素”实现为什么它不可靠假设你正在设计一个简单的银行转账系统。最直接的思路是在数据库中对两个账户进行更新操作。例如用 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/14 19:52:49

基于Swin Transformer与小波时频分析的轴承故障智能诊断
基于Swin Transformer与小波时频分析的轴承故障智能诊断

1. 项目背景与核心价值 轴承作为旋转机械的核心部件,其健康状态直接影响设备运行安全。传统振动信号分析方法存在特征提取依赖专家经验、诊断准确率受噪声影响大等痛点。这个项目创新性地结合了小波时频分析和Swin Transformer深度学习模型,实现了端到端… · 2026/10/15 3:31:50

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

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

Rust原来很简单二:所有权系统
Rust原来很简单二:所有权系统

Part 2 核心篇 —— 所有权系统 本篇覆盖 第 6 ~ 10 章:所有权、借用与引用、生命周期、字符串与切片、内存模型。 ⚠️ 这是全书最重要的一篇。 把它吃透,Rust 从此“很简单”;跳过它,你会处处碰壁。请慢下来,动手敲每一段代码。 第 6 章 所有权:Rust 的第一性原理 6… · 2026/11/5 16:26:08

基于Hadoop+Spark的民宿智能推荐系统设计与实现
基于Hadoop+Spark的民宿智能推荐系统设计与实现

1. 项目概述:大数据时代的民宿智能推荐这个毕业设计项目融合了当前大数据领域最主流的技术栈,构建了一个完整的民宿推荐系统解决方案。作为一名长期从事大数据系统开发的工程师,我认为这个选题非常贴合实际应用场景——随着旅游业的复苏和共享… · 2026/11/5 14:59:25

ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计
ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计

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

UART接口24位ADC搭配RS485,解决远距离温度监控难题
UART接口24位ADC搭配RS485,解决远距离温度监控难题

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

UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践
UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践

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

GD32E10x官方例程入门:从GPIO点灯到串口调试
GD32E10x官方例程入门:从GPIO点灯到串口调试

简介:这份GD32E10x系列官方例程面向嵌入式硬件与单片机开发者,基于ARM Cortex-M3内核,汇集兆易创新GD32E10x的示例代码,适合工业控制、消费电子、通信设备等场景的学习、验证与二次开发。压缩包共935个文件,约11.16MB&… · 2026/11/5 13:52:29

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

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

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

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

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

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

多智能体协作系统架构设计与实践优化
多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中… · 2026/11/5 0:00:39

大模型系统性入门实战指南:从原理到部署微调的全链路路线
大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#… · 2026/11/5 0:00:39

鸿蒙文件系统沙箱机制解析与开发实践
鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的… · 2026/11/5 0:00:39

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

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

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

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

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

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

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码