分布式事务的一致性保障年度回顾:2PC、TCC到Saga的实践演进
分布式事务的一致性保障年度回顾2PC、TCC到Saga的实践演进事务一致性是分布式系统中最经典也最具挑战性的问题。过去一年团队在三个不同的业务场景中分别落地了2PC、TCC和Saga三种分布式事务方案。本文基于这些实践经验做一次系统性的对比回顾。一、一笔跨行转账导致的线上事故为什么分布式事务如此棘手今年3月支付系统的一笔跨服务转账出现了部分成功的问题A账户扣款成功但B账户入账服务因为超时而失败。回滚A账户的操作又因为网络抖动再次失败最终只能人工介入修复。这次事故触发了对现有事务方案的全面审视。当时使用的是一套自研的2PC方案。复盘发现三个问题第一协调者是单点故障后所有进行中的事务都处于不确定状态第二参与者在Prepare阶段持有锁锁超时时间设置不合理导致大量锁等待第三缺乏完善的事务日志和补偿机制故障恢复只能靠人工。二、三种分布式事务方案的核心原理对比2PC的核心是强一致性代价是同步阻塞和单点故障风险。适用于资金交易等对一致性要求极高的场景。TCC将资源预留和业务确认分离避免了2PC的同步阻塞问题。但要求业务实现Try-Confirm-Cancel三个接口业务侵入性强。三、Saga编排框架的完整实现import asyncio import logging from enum import Enum from typing import Dict, List, Callable, Any, Optional from dataclasses import dataclass, field from datetime import datetime import json logging.basicConfig(levellogging.INFO) logger logging.getLogger(Saga) class StepStatus(Enum): PENDING pending RUNNING running COMPLETED completed FAILED failed COMPENSATING compensating COMPENSATED compensated dataclass class SagaStep: name: str execute: Callable compensate: Callable timeout: float 30.0 retry_count: int 3 retry_delay: float 1.0 dataclass class StepResult: step_name: str status: StepStatus result: Any None error: Optional[str] None started_at: Optional[datetime] None completed_at: Optional[datetime] None class SagaExecutionError(Exception): Saga执行异常 def __init__(self, message: str, step_results: List[StepResult]): super().__init__(message) self.step_results step_results class SagaOrchestrator: Saga编排器 - Orchestration-based Saga def __init__(self, saga_name: str): self.saga_name saga_name self.steps: List[SagaStep] [] self.results: List[StepResult] [] self.context: Dict[str, Any] {} def add_step(self, step: SagaStep) - SagaOrchestrator: self.steps.append(step) return self async def _execute_step(self, step: SagaStep) - StepResult: 执行单个步骤含重试 result StepResult( step_namestep.name, statusStepStatus.RUNNING, started_atdatetime.now() ) for attempt in range(step.retry_count 1): try: logger.info(f[{self.saga_name}] 执行步骤 {step.name} f(尝试 {attempt 1}/{step.retry_count 1})) output await asyncio.wait_for( step.execute(self.context) if asyncio.iscoroutinefunction(step.execute) else asyncio.get_event_loop().run_in_executor(None, step.execute, self.context), timeoutstep.timeout ) if output is not None: self.context[step.name] output result.status StepStatus.COMPLETED result.result output result.completed_at datetime.now() logger.info(f[{self.saga_name}] 步骤 {step.name} 完成) return result except asyncio.TimeoutError: error_msg f步骤 {step.name} 超时 ({step.timeout}s) logger.error(error_msg) if attempt step.retry_count: result.status StepStatus.FAILED result.error error_msg return result await asyncio.sleep(step.retry_delay) except Exception as e: error_msg f步骤 {step.name} 异常: {type(e).__name__}: {e} logger.error(error_msg) if attempt step.retry_count: result.status StepStatus.FAILED result.error error_msg return result await asyncio.sleep(step.retry_delay * (2 ** attempt)) return result async def _compensate_step(self, step: SagaStep, result: StepResult) - StepResult: 执行补偿操作 comp_result StepResult( step_namef{step.name}_compensate, statusStepStatus.COMPENSATING, started_atdatetime.now() ) try: logger.info(f[{self.saga_name}] 补偿步骤 {step.name}) await asyncio.wait_for( step.compensate(self.context) if asyncio.iscoroutinefunction(step.compensate) else asyncio.get_event_loop().run_in_executor(None, step.compensate, self.context), timeoutstep.timeout ) comp_result.status StepStatus.COMPENSATED comp_result.completed_at datetime.now() logger.info(f[{self.saga_name}] 补偿 {step.name} 完成) except Exception as e: comp_result.status StepStatus.FAILED comp_result.error f补偿失败: {type(e).__name__}: {e} logger.error(f[{self.saga_name}] 补偿 {step.name} 失败: {e}) return comp_result async def execute(self) - List[StepResult]: 执行Saga事务 logger.info(f[{self.saga_name}] Saga执行开始 ({len(self.steps)} 步骤)) self.results [] try: # 正向执行 for i, step in enumerate(self.steps): result await self._execute_step(step) self.results.append(result) if result.status StepStatus.FAILED: logger.error(f[{self.saga_name}] 步骤 {step.name} 失败 f开始补偿已完成的 {i} 个步骤) # 反向补偿 for j in range(i - 1, -1, -1): comp_result await self._compensate_step( self.steps[j], self.results[j] ) self.results[j] comp_result raise SagaExecutionError( fSaga {self.saga_name} 在步骤 {step.name} 失败并已补偿, self.results ) logger.info(f[{self.saga_name}] Saga执行完成) return self.results except SagaExecutionError: raise except Exception as e: logger.error(f[{self.saga_name}] Saga异常终止: {e}) raise SagaExecutionError(str(e), self.results) # 使用示例跨行转账Saga async def main(): # 模拟数据库操作 accounts {A: 1000, B: 500} def deduct_a(context): 步骤1: A账户扣款 amount context.get(amount, 0) if accounts[A] amount: raise ValueError(fA账户余额不足: {accounts[A]} {amount}) accounts[A] - amount context[a_deducted] amount return amount def compensate_deduct_a(context): 补偿A账户扣款 amount context.get(a_deducted, 0) accounts[A] amount def credit_b(context): 步骤2: B账户入账 amount context.get(amount, 0) accounts[B] amount context[b_credited] amount # 模拟可能的失败 if amount 2000: raise RuntimeError(B账户入账超时) return amount def compensate_credit_b(context): 补偿B账户入账 amount context.get(b_credited, 0) accounts[B] max(0, accounts[B] - amount) saga SagaOrchestrator(跨行转账) saga.add_step(SagaStep(扣款, deduct_a, compensate_deduct_a)) saga.add_step(SagaStep(入账, credit_b, compensate_credit_b)) saga.context[amount] 300 try: results await saga.execute() print(f转账成功! A余额: {accounts[A]}, B余额: {accounts[B]}) for r in results: print(f {r.step_name}: {r.status.value}) except SagaExecutionError as e: print(f转账失败: {e}) print(f已补偿,A余额: {accounts[A]}, B余额: {accounts[B]}) for r in e.step_results: print(f {r.step_name}: {r.status.value}) if __name__ __main__: asyncio.run(main())四、三种方案的场景适配矩阵维度2PCTCCSaga一致性强一致最终一致最终一致隔离性高(锁资源)中(预留)低(无锁)业务侵入低高(需3接口)中(需补偿)性能低(同步阻塞)中高(异步)适用时长秒级分钟级小时/天级开发复杂度低高中运维复杂度中(协调者)高(补偿幂等)中(补偿幂等)典型场景金融支付预订类长流程审批选2PC当事务时长在秒级、需要强一致性、参与者数量少且稳定选TCC当需要预留和确认两阶段语义、对性能有一定要求选Saga当长事务分钟到天级别、需要高吞吐、可以接受最终一致性五、总结分布式事务没有银弹选择哪种方案取决于业务对一致性、性能和复杂度的取舍。过去一年的实践教会了一条原则不要让事务方案比业务逻辑更复杂。能用最终一致性解决的问题不要强求强一致性能用Saga编排的场景不要强行实现TCC的三个接口。下半年计划基于Saga框架建设统一的事务管理平台将补偿逻辑标准化和自动化。

相关新闻

如何快速搭建个人游戏串流中心:Sunshine全平台部署指南

如何快速搭建个人游戏串流中心:Sunshine全平台部署指南

如何快速搭建个人游戏串流中心:Sunshine全平台部署指南 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 你是否曾经梦想过在任何设备上都能流畅玩转PC上的3A大作&#x…

2026/7/27 11:28:32阅读更多 →
碧蓝幻想Relink终极指南:GBFR Logs免费DPS统计工具完整教程

碧蓝幻想Relink终极指南:GBFR Logs免费DPS统计工具完整教程

碧蓝幻想Relink终极指南:GBFR Logs免费DPS统计工具完整教程 【免费下载链接】gbfr-logs GBFR Logs lets you track damage statistics with a nice overlay DPS meter for Granblue Fantasy: Relink. 项目地址: https://gitcode.com/gh_mirrors/gb/gbfr-logs …

2026/7/27 11:28:32阅读更多 →
数据库领域AI落地的真实ROI分析:投入与产出的量化对比

数据库领域AI落地的真实ROI分析:投入与产出的量化对比

数据库领域AI落地的真实ROI分析:投入与产出的量化对比 当所有人都谈论"AI赋能数据库"时,很少有文章真正掰着手指算过账。过去半年,团队在三个项目中系统性地跟踪了AI投入的成本与产出,本文用数据说话,给出一…

2026/7/27 11:28:32阅读更多 →
高速ADC选型与设计实战:从ADC12D500RF/800RF参数解析到系统实现

高速ADC选型与设计实战:从ADC12D500RF/800RF参数解析到系统实现

1. 项目概述:从数据手册到设计洞察在射频和高速数字系统设计领域,选型一颗合适的模数转换器(ADC)往往是项目成败的关键第一步。面对动辄上百页的数据手册,尤其是像德州仪器(TI)的ADC12D500RF和A…

2026/7/27 14:10:53阅读更多 →
PvZ Toolkit终极指南:如何彻底掌控你的植物大战僵尸游戏体验

PvZ Toolkit终极指南:如何彻底掌控你的植物大战僵尸游戏体验

PvZ Toolkit终极指南:如何彻底掌控你的植物大战僵尸游戏体验 【免费下载链接】pvztoolkit 植物大战僵尸 PC 版综合修改器 项目地址: https://gitcode.com/gh_mirrors/pv/pvztoolkit 你是否曾经在植物大战僵尸中感到资源匮乏,或者想要尝试一些新的…

2026/7/27 14:10:53阅读更多 →
KMS智能激活工具终极指南:三步永久激活Windows和Office

KMS智能激活工具终极指南:三步永久激活Windows和Office

KMS智能激活工具终极指南:三步永久激活Windows和Office 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为Windows系统频繁弹出激活提示而烦恼吗?Office文档突然变成只…

2026/7/27 14:10:53阅读更多 →
CD-HIT完全指南:从安装到序列聚类的终极教程

CD-HIT完全指南:从安装到序列聚类的终极教程

CD-HIT完全指南:从安装到序列聚类的终极教程 【免费下载链接】cdhit Automatically exported from code.google.com/p/cdhit 项目地址: https://gitcode.com/gh_mirrors/cd/cdhit CD-HIT是一款高效的序列聚类工具,能够快速将蛋白质或核苷酸序列按…

2026/7/27 14:10:53阅读更多 →
终极指南:qmcdump免费解密QQ音乐加密音频的完整教程

终极指南:qmcdump免费解密QQ音乐加密音频的完整教程

终极指南:qmcdump免费解密QQ音乐加密音频的完整教程 【免费下载链接】qmcdump 一个简单的QQ音乐解码(qmcflac/qmc0/qmc3 转 flac/mp3),仅为个人学习参考用。 项目地址: https://gitcode.com/gh_mirrors/qm/qmcdump 还在为Q…

2026/7/27 14:10:53阅读更多 →
LiveKit实时音视频服务器:从架构解析到生产部署完整指南

LiveKit实时音视频服务器:从架构解析到生产部署完整指南

LiveKit实时音视频服务器:从架构解析到生产部署完整指南 【免费下载链接】livekit End-to-end realtime stack for connecting humans and AI 项目地址: https://gitcode.com/GitHub_Trending/li/livekit LiveKit是一个开源的实时音视频服务器,专…

2026/7/27 14:08:53阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/27 1:14:34阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/27 1:14:52阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/27 1:14:56阅读更多 →
SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

1. 项目概述:从寄存器手册到实战指南 如果你手头有一份类似德州仪器(TI)TMS320x240xA系列DSP的SPI模块技术手册,看着里面密密麻麻的寄存器位定义、时序图和公式,是不是感觉头大?这份资料虽然权威&#xff0…

2026/7/27 0:00:24阅读更多 →
【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

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

2026/7/27 0:00:24阅读更多 →
2007-2023年各市区县生态文明建设示范区DID

2007-2023年各市区县生态文明建设示范区DID

数据简介 自改革开放以来,我国依赖高投入、高资源消耗和高污染等传统发展模式实现了经济短期内的快速增长, 然而这也导致了严重的生态环境危机。因此,国家有力于推动企业高质量经济发展,协同生态保护的方针,从而从201…

2026/7/27 0:00:24阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/25 23:03:25阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/26 19:05:21阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/26 19:05:21阅读更多 →