一、TCC基础介绍
TCC 模式是最经典的分布式事务解决方案,它将分布式事务分为两个阶段来执行,try 阶段对每个分支事务进行预留资源,如果所有分支事务都预留资源成功,则进入 commit 阶段提交全局事务,如果有一个节点预留资源失败则进入 cancel 阶段回滚全局事务。
以传统的订单、库存、账户服务为例,在 try 阶段尝试预留资源,插入订单、扣减库存、扣减金额,这三个服务都是要提交本地事务的,这里可以把资源转入中间表。在 commit 阶段,再把 try 阶段预留的资源转入最终表。而在 cancel 阶段,把 try 阶段预留的资源进行释放,比如把账户金额返回给客户的账户。
注意:try 阶段必须是要提交本地事务的,比如扣减订单金额,必须把钱从客户账户扣掉,如果不扣掉,在 commit 阶段客户账户钱不够了,就会出问题。
二、TCC模型的工作流程
在分布式事务中,TCC(Try-Confirm-Cancel)是一种常见的事务控制机制,用于确保在分布式系统中事务的一致性和完整性。TCC 模型主要由以下三个角色组成:
TM(Transaction Manager):事务管理器
RM(Resource Manager):资源管理器
TC(Transaction Coordinator):事务协调器
1. TM(Transaction Manager)- 事务管理器
事务管理器负责管理整个事务的生命周期。它主要负责以下任务:
在 TCC 模型中,事务管理器会调用各个资源管理器的 Try、Confirm 和 Cancel 接口来控制事务的执行。
2. RM(Resource Manager)- 资源管理器
资源管理器负责具体资源的管理和操作。它主要负责以下任务:
- 实现 Try、Confirm 和 Cancel 接口
- 执行实际的业务操作
在 TCC 模型中,每个资源管理器负责一个或多个资源(例如数据库、文件系统等)的操作,并通过 Try、Confirm 和 Cancel 接口来参与事务的控制。
3. TC(Transaction Coordinator)- 事务协调器
事务协调器负责协调多个资源管理器,以确保分布式事务的一致性和完整性。它主要负责以下任务:
- 协调各个资源管理器的操作
- 确保所有资源管理器成功执行 Try 操作后,才能执行 Confirm 操作
- 如果任何一个资源管理器的 Try 操作失败,则执行 Cancel 操作
三、示例
假设有一个分布式事务,需要在两个系统中分别扣减库存和扣减余额。以下是 TCC 模型的工作流程:
Try 阶段:
- 事务管理器(TM)调用库存系统的 Try 接口,预留库存。
- 事务管理器(TM)调用余额系统的 Try 接口,预留余额。
Confirm 阶段:
- 如果库存系统和余额系统的 Try 操作都成功,事务管理器(TM)调用库存系统的 Confirm 接口,正式扣减库存。
- 事务管理器(TM)调用余额系统的 Confirm 接口,正式扣减余额。
Cancel 阶段:
- 如果库存系统或余额系统的 Try 操作失败,事务管理器(TM)调用库存系统的 Cancel 接口,取消预留的库存。
- 事务管理器(TM)调用余额系统的 Cancel 接口,取消预留的余额。
Demo代码
1. 定义资源管理器(RM)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| package main
import ( "fmt" "sync" )
type RM interface { Try() error Confirm() error Cancel() error }
type InventoryManager struct { mu sync.Mutex stock int reserve int }
func NewInventoryManager(stock int) *InventoryManager { return &InventoryManager{stock: stock} }
func (im *InventoryManager) Try() error { im.mu.Lock() defer im.mu.Unlock() if im.stock > 0 { im.reserve++ im.stock-- fmt.Println("Inventory Try: reserved 1 item") return nil } return fmt.Errorf("Inventory Try: out of stock") }
func (im *InventoryManager) Confirm() error { im.mu.Lock() defer im.mu.Unlock() if im.reserve > 0 { im.reserve-- fmt.Println("Inventory Confirm: confirmed 1 item") return nil } return fmt.Errorf("Inventory Confirm: no item to confirm") }
func (im *InventoryManager) Cancel() error { im.mu.Lock() defer im.mu.Unlock() if im.reserve > 0 { im.reserve-- im.stock++ fmt.Println("Inventory Cancel: canceled 1 item") return nil } return fmt.Errorf("Inventory Cancel: no item to cancel") }
type BalanceManager struct { mu sync.Mutex balance int reserve int }
func NewBalanceManager(balance int) *BalanceManager { return &BalanceManager{balance: balance} }
func (bm *BalanceManager) Try() error { bm.mu.Lock() defer bm.mu.Unlock() if bm.balance > 0 { bm.reserve++ bm.balance-- fmt.Println("Balance Try: reserved 1 unit") return nil } return fmt.Errorf("Balance Try: insufficient balance") }
func (bm *BalanceManager) Confirm() error { bm.mu.Lock() defer bm.mu.Unlock() if bm.reserve > 0 { bm.reserve-- fmt.Println("Balance Confirm: confirmed 1 unit") return nil } return fmt.Errorf("Balance Confirm: no unit to confirm") }
func (bm *BalanceManager) Cancel() error { bm.mu.Lock() defer bm.mu.Unlock() if bm.reserve > 0 { bm.reserve-- bm.balance++ fmt.Println("Balance Cancel: canceled 1 unit") return nil } return fmt.Errorf("Balance Cancel: no unit to cancel") }
|
2. 定义事务管理器(TM)和事务协调器(TC)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| type TransactionManager struct { rms []RM }
func NewTransactionManager(rms []RM) *TransactionManager { return &TransactionManager{rms: rms} }
func (tm *TransactionManager) Execute() error { for _, rm := range tm.rms { if err := rm.Try(); err != nil { tm.Cancel() return fmt.Errorf("Transaction failed in Try phase: %v", err) } }
for _, rm := range tm.rms { if err := rm.Confirm(); err != nil { tm.Cancel() return fmt.Errorf("Transaction failed in Confirm phase: %v", err) } }
fmt.Println("Transaction succeeded") return nil }
func (tm *TransactionManager) Cancel() { for _, rm := range tm.rms { if err := rm.Cancel(); err != nil { fmt.Printf("Error during Cancel phase: %v\n", err) } } }
|
运行示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| func main() { inventoryManager := NewInventoryManager(10) balanceManager := NewBalanceManager(10)
rms := []RM{inventoryManager, balanceManager} transactionManager := NewTransactionManager(rms)
if err := transactionManager.Execute(); err != nil { fmt.Printf("Transaction failed: %v\n", err) } }
|
这个示例展示了一个简单的 TCC 模型实现,其中包括事务管理器(TM)、资源管理器(RM)和事务协调器(TC)。通过这种方式,可以确保分布式事务的一致性和完整性。