分布式事务理论及常用组件 —— 汇总

关于分布式事务,工程领域主要讨论的是强一致性和最终一致性的解决方案。典型方案包括:

两阶段提交(2PC, Two-phase Commit)方案
eBay 事件队列方案
TCC 补偿模式
缓存数据最终一致性

1. 一致性理论

分布式事务的目的是保障分库数据一致性,而跨库事务会遇到各种不可控制的问题,如个别节点永久性宕机,像单机事务一样的ACID是无法奢望的。另外,业界著名的CAP理论也告诉我们,对分布式系统,需要将数据一致性和系统可用性、分区容忍性放在天平上一起考虑。

两阶段提交协议(简称2PC)是实现分布式事务较为经典的方案,但2PC 的可扩展性很差,在分布式架构下应用代价较大,eBay 架构师Dan Pritchett 提出了BASE 理论,用于解决大规模分布式系统下的数据一致性问题。BASE 理论告诉我们:可以通过放弃系统在每个时刻的强一致性来换取系统的可扩展性。

  1. CAP理论在分布式系统中,一致性(Consistency)、可用性(Availability)和分区容忍性(Partition Tolerance)3 个要素最多只能同时满足两个,不可兼得。
    其中,分区容忍性又是不可或缺的。

    一致性:分布式环境下多个节点的数据是否强一致。可用性:分布式服务能一直保证可用状态。当用户发出一个请求后,服务能在有限时间内返回结果。分区容忍性:特指对网络分区的容忍性。举例:Cassandra、Dynamo
    等,默认优先选择AP,弱化C;HBase、MongoDB 等,默认优先选择CP,弱化A。
  2. BASE理论核心思想:
    基本可用(BasicallyAvailable):指分布式系统在出现故障时,允许损失部分的可用性来保证核心可用。
    软状态(SoftState):指允许分布式系统存在中间状态,该中间状态不会影响到系统的整体可用性。
    最终一致性(EventualConsistency):指分布式系统中的所有副本数据经过一定时间后,最终能够达到一致的状态。

2. 一致性模型

数据的一致性模型可以分成以下 3 类:
强一致性:数据更新成功后,任意时刻所有副本中的数据都是一致的,一般采用同步的方式实现。 弱一致性:数据更新成功后,系统不承诺立即可以读到最新写入的值,也不承诺具体多久之后可以读到。 最终一致性:弱一致性的一种形式,数据更新成功后,系统不承诺立即可以返回最新写入的值,但是保证最终会返回上一次更新操作的值。 分布式系统数据的强一致性、弱一致性和最终一致性可以通过Quorum NRW算法分析。

3. 分布式事务解决方案

  1. 2PC方案——强一致性

2PC的核心原理是通过提交分阶段和记日志的方式,记录下事务提交所处的阶段状态,在组件宕机重启后,可通过日志恢复事务提交的阶段状态,并在这个状态节点重试,如Coordinator重启后,通过日志可以确定提交处于Prepare还是PrepareAll状态,若是前者,说明有节点可能没有Prepare成功,或所有节点Prepare成功但还没有下发Commit,状态恢复后给所有节点下发RollBack;若是PrepareAll状态,需要给所有节点下发Commit,数据库节点需要保证Commit幂等。

2PC方案的问题:同步阻塞。数据不一致。单点问题。升级的3PC方案旨在解决这些问题,主要有两个改进:增加超时机制。两阶段之间插入准备阶段。但三阶段提交也存在一些缺陷,要彻底从协议层面避免数据不一致,可以采用Paxos或者Raft算法。

  1. eBay 事件队列方案——最终一致性

eBay 的架构师Dan Pritchett,曾在一篇解释BASE 原理的论文《Base:An Acid
Alternative》中提到一个eBay
分布式系统一致性问题的解决方案。它的核心思想是将需要分布式处理的任务通过消息或者日志的方式来异步执行,消息或日志可以存到本地文件、数据库或消息队列,再通过业务规则进行失败重试,它要求各服务的接口是幂等的。描述的场景为,有用户表user
和交易表transaction,用户表存储用户信息、总销售额和总购买额,交易表存储每一笔交易的流水号、买家信息、卖家信息和交易金额。如果产生了一笔交易,需要在交易表增加记录,同时还要修改用户表的金额。

论文中提出的解决方法是将更新交易表记录和用户表更新消息放在一个本地事务来完成,为了避免重复消费用户表更新消息带来的问题,增加一个操作记录表updates_applied来记录已经完成的交易相关的信息。
这个方案的核心在于第二阶段的重试和幂等执行。失败后重试,这是一种补偿机制,它是能保证系统最终一致的关键流程。

  1. TCC (Try-Confirm-Cancel)补偿模式——最终一致性

某业务模型如图,由服务 A、服务B、服务C、服务D 共同组成的一个微服务架构系统。服务A 需要依次调用服务B、服务C 和服务D
共同完成一个操作。当服务A 调用服务D 失败时,若要保证整个系统数据的一致性,就要对服务B 和服务C 的invoke
操作进行回滚,执行反向的revert 操作。回滚成功后,整个微服务系统是数据一致的。
实现关键要素:服务调用链必须被记录下来。每个服务提供者都需要提供一组业务逻辑相反的操作,互为补偿,同时回滚操作要保证幂等。必须按失败原因执行不同的回滚策略。

  1. 缓存数据最终一致性

在我们的业务系统中,缓存(Redis 或者Memcached)通常被用在数据库前面,作为数据读取的缓冲,使得I/O
操作不至于直接落在数据库上。以商品详情页为例,假如卖家修改了商品信息,并写回到数据库,但是这时候用户从商品详情页看到的信息还是从缓存中拿到的过时数据,这就出现了缓存系统和数据库系统中的数据不一致的现象。
要解决该场景下缓存和数据库数据不一致的问题我们有以下两种解决方案:为缓存数据设置过期时间。当缓存中数据过期后,业务系统会从数据库中获取数据,并将新值放入缓存。这个过期时间就是系统可以达到最终一致的容忍时间。更新数据库数据后同时清除缓存数据。数据库数据更新后,同步删除缓存中数据,使得下次对商品详情的获取直接从数据库中获取,并同步到缓存。

常用组件: Seata,Sega,Atomikos

参考文章

  1. 分布式事务(1)—2PC和3PC原理
  2. 分布式事务、3pc
  3. 对分布式事务及两阶段提交、三阶段提交的理解
  4. SpringCloudAlibaba笔记(十):Seata–分布式事务
  5. Seata实战-AT模式分布式事务原理、源码分析
  6. Springboot+atomikos+jta实现分布式事务统一管理
  7. Seata实战-分布式事务简介及demo上手
  8. Seata分布式事务模式详细整理
### Xinference 分布式部署与应用 #### 安装与配置 为了在分布式环境下使用 Xinference,首先需要确保所有节点上都已正确安装了该框架。Xinference 支持多种操作系统平台上的安装方式,其中最简便的方式是利用 `pip` 工具来完成安装工作[^3]。 ```bash pip install xorbits-inference ``` 由于 Xinference 的依赖项较多,在初次安装过程中可能会消耗一定的时间。对于生产环境中大规模集群的部署,则建议预先准备好离线包并优化网络环境以加速下载速度。 #### 部署架构概述 Xinference 设计之初便考虑到了分布式的应用场景需求,其核心特性之一就是能够快速搭建起高效的分布式推理服务。具体来说: - **多节点协同**:支持跨多个计算资源(如 CPU/GPU)执行复杂的机器学习任务; - **灵活调度机制**:可根据实际负载情况动态调整各组件间的工作分配策略; - **高可用性保障**:即使部分节点发生故障也不会影响整体系统的正常运行; 这些特点使得 Xinference 成为构建稳定可靠的在线预测服务平台的理想选择[^1]。 #### 实现细节说明 当涉及到具体的分布式实现时,主要关注以下几个方面: ##### 资源规划与初始化设置 启动之前要仔细评估目标硬件设施的能力范围,并据此合理划分各个子系统所占用的比例。比如可以指定某些服务器专门用于存储中间结果或是作为前端请求入口等角色定位。 ##### 数据分片处理逻辑 针对大型数据集的操作往往难以一次性加载入内存中完成运算,因此引入了分区的概念——即将原始输入按照特定规则拆分成若干个小批次分别交给不同实例去独立加工后再汇总输出最终答案。这一过程既提高了吞吐量又降低了单点压力。 ##### 并发控制算法设计 考虑到并发访问可能导致的竞争条件问题,内部实现了细粒度锁以及其他同步原语用来协调竞争关系,从而保证事务的一致性和隔离级别达到预期标准。 ##### 故障转移预案制定 任何时刻都有可能出现意外状况致使个别成员掉线失效,为此建立了一套完善的灾备恢复方案,能够在第一时间感知异常信号并将对应的任务重新指派给其他健康单元继续承担下去直至恢复正常状态为止。 通过上述措施共同作用下,Xinference 不仅能在本地计算机上流畅运作也能无缝扩展到云端乃至混合云这样的复杂拓扑结构之上提供一致性的用户体验和服务质量承诺[^2]。 #### 应用案例展示 假设现在有一个基于 Transformer 架构的语言理解模型想要迁移到 Xinference 上面做实时响应的话,那么只需要编写少量 Python 代码就可以轻松搞定整个迁移流程: ```python from xorbits.inference import load_model, predict model_path = "path/to/transformer/model" loaded_model = load_model(model_path) input_text = ["你好世界", "今天天气真好"] predictions = predict(loaded_model, input_texts=input_text) print(predictions) ``` 这段脚本展示了如何加载预训练好的模型文件以及调用 API 接口来进行批量文本分类操作。当然这仅仅是冰山一角而已,更多高级特性和最佳实践指南可参阅官方文档获取更多信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值