TCC分布式事务:原理、架构与设计思想

TCC分布式事务:原理、架构与设计思想

TCC分布式事务

原理、架构与设计思想详解

info 定义与背景

TCC(Try-Confirm-Cancel)是一种基于业务补偿的分布式事务解决方案,通过将事务拆分为三个阶段实现最终一致性。在分布式系统中,当业务操作涉及多个独立的服务或数据源时,传统的ACID事务难以满足需求,TCC模式应运而生。

在分布式缓存系统中,如Redis集群,一条指令(如MSET)可能需要多个节点同时执行,可能有些节点成功而另一部分节点失败,导致一致性问题。TCC模式为解决这类问题提供了有效的方案。

layers TCC三个阶段详解

Try(尝试)

完成所有业务检查(一致性),预留必须业务资源(准隔离性)。此阶段仅做资源预留,不执行真正的业务操作。

Confirm(确认)

如果所有分支的Try都成功,则执行Confirm阶段。真正执行业务,不作任何业务检查,只使用Try阶段预留的业务资源。

Cancel(取消)

如果任何一个分支的Try失败,则执行Cancel阶段。释放Try阶段预留的业务资源,回滚事务。

people TCC分布式事务中的角色

AP(应用程序)

发起全局事务,定义全局事务包含哪些事务分支。是整个事务流程的发起者和业务逻辑的执行者。

RM(资源管理器)

负责分支事务各项资源的管理。每个参与者都需要实现Try、Confirm、Cancel三个方法,管理自己的资源。

TM(事务管理器)

负责协调全局事务的正确执行,包括Confirm、Cancel的执行,并处理网络异常等故障情况。

compare_arrows TCC与两阶段提交(2PC)的关系

TCC本质上就是一个应用层面的2PC,需要通过业务逻辑来实现。与传统的2PC相比,TCC具有以下特点:

  • 2PC通常在跨库的DB层面实现,而TCC在应用层面实现
  • TCC可以让应用自己定义数据库操作的粒度,使得降低锁冲突、提高吞吐量成为可能
  • 2PC是阻塞协议,而TCC是非阻塞的,资源锁定时间更短
  • TCC具有更好的可扩展性,适用于SOA架构

thumbs_up_down TCC的优缺点分析

优点

  • 可以让应用自己定义数据库操作的粒度
  • 降低锁冲突,提高吞吐量
  • 资源锁定时间短,性能更好
  • 适用于SOA架构,可扩展性好
  • 实现最终一致性,满足大多数业务场景

缺点

  • 对应用的侵入性非常强
  • 业务逻辑的每个分支都需要实现三个操作
  • 实现难度比较大,开发成本高
  • 需要按照不同的失败原因实现不同的回滚策略
  • Confirm和Cancel接口必须实现幂等

storage 在Redis集群中实现分布式事务

在Redis集群中,DEL、MSET等命令所涉及的key可能分布在不同的节点中,导致一致性问题。使用TCC模式可以解决此类问题:

  • Try阶段:检查所有key是否存在,锁定相关key,防止被其他操作修改
  • Confirm阶段:执行真正的MSET操作,释放锁
  • Cancel阶段:释放所有锁定的key,不做任何修改

通过这种方式,可以保证MSET操作要么全部成功,要么全部失败,从而实现分布式事务的一致性。

code TCC分布式事务的Golang实现示例

以下是一个简化的TCC事务管理器的Golang实现示例:

go TCC事务管理器实现
type TCCManager struct {
    participants map[string]Participant // 参与者集合
}

type Participant interface {
    Try() error                    // Try阶段方法
    Confirm() error                // Confirm阶段方法
    Cancel() error                 // Cancel阶段方法
}

// 执行TCC事务
func (tm *TCCManager) Execute() error {
    // Try阶段:所有参与者尝试执行
    for id, p := range tm.participants {
        if err := p.Try(); err != nil {
            // 如果Try失败,执行Cancel回滚
            tm.cancelAll()
            return fmt.Errorf("participant %s Try failed: %v", id, err)
        }
    }
    
    // Confirm阶段:所有参与者确认执行
    for id, p := range tm.participants {
        if err := p.Confirm(); err != nil {
            // 如果Confirm失败,记录错误,但无法回滚
            // 此时需要人工介入处理
            return fmt.Errorf("participant %s Confirm failed: %v", id, err)
        }
    }
    
    return nil
}

// 取消所有参与者的操作
func (tm *TCCManager) cancelAll() {
    for id, p := range tm.participants {
        if err := p.Cancel(); err != nil {
            // 记录Cancel失败的日志,需要人工介入
            log.Printf("participant %s Cancel failed: %v", id, err)
        }
    }
}

在实际应用中,还需要考虑网络超时、重试机制、幂等性等问题,以确保分布式事务的可靠性。

发表评论

人生梦想 - 关注前沿的计算机技术 acejoy.com 🐾 步子哥の博客 🐾 背多分论坛 🐾 知差(chai)网 🐾 DeepracticeX 社区 🐾 老薛主机 🐾 智柴论坛 🐾