主题
面试速答(先看这里)
**一句话结论:**所谓TCC,就是把一个操作拆分成Try\Confirm\Cancel三个步骤,并且这三个动作已经不是一个事务了,而是三个不同的事务。
60秒标准回答:
这是一个比较典型的场景题,考察对TCC的理解
我们先来回顾一下TCC
所谓TCC,就是把一个操作拆分成Try\Confirm\Cancel三个步骤,并且这三个动作已经不是一个事务了,而是三个不同的事务
**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点
回答主线:
- **要点1:**这是一个比较典型的场景题,考察对TCC的理解。
- **要点2:**Try\Confirm\Cancel分别是三个不同的方法,站在事务参与者的角度,在代码中,每一次调用Try或者Confirm或者Cancel的时候,都会单独开启一个数据库事务(如果数据库支持的话),这就是2PC比较大的区别,2PC从头到尾就一个事务。
- **要点3:**那么TCC如何拆呢?
- **要点4:**那么回到问题上,针对库存扣减,如何拆解成TCC呢?
- **要点5:**所以,你在回过头来看前面说TCC是三个事务的说法,是不是就理解,三个不同的SQL,每一个都是单独事务执行的。
**记忆锚点:**Confirm → Try → TCC → Cancel → update → where
关键取舍:
- 其实再看下TCC的定义: Try阶段 :执行业务检查,预留资源 Confirm阶段 :若所有Try成功,提交资源 Cancel阶段 :若任一Try失败,释放预留资源 那么回到问题上,针对库存扣减,如何拆解成TCC呢?
- Try阶段 :执行业务检查,预留资源 update inventory_table set frozen_inventory = frozen_inventory + #{count} where id = xxx 冻结库存 + 1,用户看到的 可用库存 = 剩余库存 - 冻结库存 ,那么,这就起到了资源预留的作用。
- Confirm阶段 :若所有Try成功,提交资源 update inventory_table set frozen_inventory = frozen_inventory - #{count},saleable_inventory = saleable_inventory - #{count} where id = xxx 冻结库存 - 1, 剩余库存…
易错提醒:
- 其实再看下TCC的定义: Try阶段 :执行业务检查,预留资源 Confirm阶段 :若所有Try成功,提交资源 Cancel阶段 :若任一Try失败,释放预留资源 那么回到问题上,针对库存扣减,如何拆解成TCC呢?
- Cancel阶段 :若任一Try/Confirm失败,释放预留资源 update inventory_table set frozen_inventory = frozen_inventory - #{count} where id = xxx 冻结库存 - 1, 即释预留资源 Cancel阶段 :若Confirm成功,但是其他参与者失败,需要回滚Confi…
加分表达:
- 这是一个比较典型的场景题,考察对TCC的理解。
- Try\Confirm\Cancel分别是三个不同的方法,站在事务参与者的角度,在代码中,每一次调用Try或者Confirm或者Cancel的时候,都会单独开启一个数据库事务(如果数据库支持的话),这就是2PC比较大的区别,2PC从头到尾就一个事务。
- PS:这个TCC在我的 项目课中有落地实践 ,代码+视频+文档。
追问准备:
- 怎么理解上面这句话呢?
- 那么TCC如何拆呢?
- 其实再看下TCC的定义: Try阶段 :执行业务检查,预留资源 Confirm阶段 :若所有Try成功,提交资源 Cancel阶段 :若任一Try失败,释放预留资源 那么回到问题上,针对库存扣减,如何拆解成TCC呢?
- 针对订单创建,如何拆解成TCC呢?
典型回答
这是一个比较典型的场景题,考察对TCC的理解。
我们先来回顾一下TCC。
所谓TCC,就是把一个操作拆分成Try\Confirm\Cancel三个步骤,并且这三个动作已经不是一个事务了,而是三个不同的事务。
怎么理解上面这句话呢?
Try\Confirm\Cancel分别是三个不同的方法,站在事务参与者的角度,在代码中,每一次调用Try或者Confirm或者Cancel的时候,都会单独开启一个数据库事务(如果数据库支持的话),这就是2PC比较大的区别,2PC从头到尾就一个事务。
那么TCC如何拆呢?其实再看下TCC的定义:
- Try阶段:执行业务检查,预留资源
- Confirm阶段:若所有Try成功,提交资源
- Cancel阶段:若任一Try失败,释放预留资源
那么回到问题上,针对库存扣减,如何拆解成TCC呢?
Try阶段:执行业务检查,预留资源
冻结库存
update inventory_table set frozen_inventory = frozen_inventory + #{count} where id = xxx冻结库存+ 1,用户看到的可用库存=剩余库存-冻结库存,那么,这就起到了资源预留的作用。Confirm阶段:若所有Try成功,提交资源
解冻并扣减库存
update inventory_table set frozen_inventory = frozen_inventory - #{count},saleable_inventory = saleable_inventory - #{count} where id = xxx冻结库存- 1,剩余库存- 1,即真正做库存扣减。Cancel阶段:若任一Try/Confirm失败,释放预留资源
解冻库存
update inventory_table set frozen_inventory = frozen_inventory - #{count} where id = xxx冻结库存- 1, 即释预留资源Cancel阶段:若Confirm成功,但是其他参与者失败,需要回滚Confirm操作
回退库存
update inventory_table set saleable_inventory = saleable_inventory + #{count} where id = xxx剩余库存+ 1,即回退库存扣减操作。
针对订单创建,如何拆解成TCC呢?
Try阶段:执行业务检查,预留资源
创建订单,但是订单用户不可见,无法支付
insert into order(id,time,order_id,state) value(1,now(),12345,"INIT")创建一个INIT状态的订单,这个状态用户不感知
Confirm阶段:若所有Try成功,提交资源
update order set state = 'TO_PAY' where id = xxx订单状态推荐到待支付状态,这时候用户就能看到这个订单了。可以去做支付了
Cancel阶段:若任一Try/Confirm失败,释放预留资源
update order set state = 'DISCARD' where id = xxx订单废弃掉,废弃的订单无法查看,也无法操作,可以定期清理掉。
Cancel阶段:若Confirm成功,但是其他参与者失败,需要回滚Confirm操作
update order set state = 'DISCARD' where id = xxx订单废弃掉,废弃的订单无法查看,也无法操作,可以定期清理掉。
所以,你在回过头来看前面说TCC是三个事务的说法,是不是就理解,三个不同的SQL,每一个都是单独事务执行的。
PS:这个TCC在我的项目课中有落地实践,代码+视频+文档。有需要的可以了解下。