8000 Home · chinaccj/tcc-transaction Wiki · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
chinaccj edited this page Nov 17, 2017 · 51 revisions

项目背景

本框架是为了解决金融/电商系统的分布式最终一致性而设计。比传统的XA的两阶段提交,和1pc(1阶段最大努力型)有明显的优势,但是使用起来有一定的门槛,并不是所有的公司都适用。关于xa 两阶段,1pc,tcc的介绍文章 分布式事务典型处理方式

通过一个账号充值例子,对比1pc和tcc的区别


一阶段最大努力型: 虽然一阶段有提交,也有回滚。跟tcc 还是有本质的区别。 以账户系统为例,给张三充值: 一阶段最大努力型:update set account = acount +x, 回滚操作 Update set account = account -x . 这里有问题风险:先充值成功,后面才回滚,存在两个风险。1 充值的钱被提现。 2 回滚存在失败的情况。 这种情况在高危的金融领域是不允许的。

**Tcc ** 预留必要的资源:以给张三充值为例。Try:往充值的流水的预处理表插入一条记录。 在confirm 阶段,才将该记录插入到流水表,并且账户表加钱。 Cancel 阶段将删除充值的流水的预处理表的记录。 而且confirm阶段如果失败,会不停的重复提交,直到成功。只需要一个事务id(uuid)保证幂等性即可。因为在插入的时候,通过唯一性索引保持,不需要使用额外的uuid表。

项目特点

本框架的核心思想源自支付宝的tcc框架。以xid(分布式事务id)贯穿整个tcc的try,commit,rollback. 使用这种设计的优点

  1. xid由业务自定义生成,可以在xid生成的时候加入业务分库分表的等属性,方便后续业务横向扩展。
  2. commit/rollback方法参数非常简单,简单到只需要一个xid参数。考虑到框架未来的扩展性,增加了TccContext作为commit/rollback的第二个参数. 提升序列化的性能。

项目模块介绍

tcc-demo

通过一个简单的电商例子作为tcc框架的使用demo。

demo-itemcenter 商品中心。服务启动:demo-itemcenter/demo-itemcenter.deploy com.touna.tcc.demo.itemcenter.deploy.Bootstrap
demo-pay 支付中心。服务启动:demo-pay/demo-pay.deploy com.touna.tcc.demo.pay.deploy.Bootstrap demo-trading 交易中心.
db/tcc.sql tcc框架初始化sql。
db/demo.sql tcc框架demo初始化sql。

测试用例:src/test/com/touna/tcc/demo/trading/service  
OrderServiceTest (模拟下单,商品库存减1,账号余额减1)  
PerformanceTest (100线程并发测试,验证框架多线程线程安全处理)  
ToleranceTest (容错测试,模拟5组常见异常)  
运行测试用例之前,1 需要初始化数据库(tcc-demo/db/tcc.sql tcc框架自带表,tcc-demo/db/demo.sql tcc运行demo程序需要的表),2 启动demo-pay服务,demo-itemcenter服务。

tcc-core

tcc框架核心包。核心包定义了抽象的接口,抽象类,方便业务定制和扩展。
TccTransactionInterceptor tcc分布式事务拦截器
AbstractTransactionManager 事务管理器抽象类。
log包 事务序列化

tcc-dubbo

tcc dubbo 框架适配器。
DubboTransactionManager dubbo 事务管理器(extends AbstractTransactionManager)
TccTransactionFilter dubbo consumer 过滤器

tcc-admin (v1.0未上线)

tcc 事务补偿程序。

tcc 框架用法

  1. sql初始化(tcc-demo/db/tcc.sql)
  2. 项目maven pom需要依赖tcc的jar(可以将github源码下载,部署到私服)
<dependency>
 <groupId>com.touna</groupId>
  <artifactId>tcc-dubbo</artifactId>
  <version>1.0-SNAPSHOT</version>
</dependency> 

spring 需要定义tcc的bean

<bean id="tccTransactionInterceptor" class="com.touna.tcc.core.interceptor.TccTransactionInterceptor" >
    <property name="txLogService" ref="txLogService"></property>
    <property name="transactionManagerBeanName" value="tccTransaction"/>
</bean>

<!--bean id tccTransaction 不能更改-->
<bean id="tccTransaction" class="com.touna.tcc.dubbo.transaction.DubboTransactionManager">
    <!--tcc commit/rollback 方法序列化分配空间(字节数)。分配大小依据TccContext的大小。
    如果TccContext都没用上,设置128足够-->
    <constructor-arg value="1024"/>
    <property name="txLogService" ref="txLogService"></property>
    <property name="txChildLogService" ref="txChildLogService"></property>
</bean>
<import resource="classpath:config/tcc-core-service.xml"/>

3 dubbo consumer配置。业务节点的资源文件配置 resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter 配置(参考 tcc-demo/demo-pay)
4. 代码嵌入tcc注解
4.1 dubbo facade(api) 定义。 一个tcc的try方法,需要带一个commit方法和rollback方法。commit和rollback方法名在try方法的@TwoPhaseBusinessAction注解里面定义。 > @TwoPhaseBusinessAction(commitMethod="payCommit",rollbackMethod="payRollback") > void pay(String xid,@Attachment(key="accountId") String accountId,Double amount);

>  Boolean payCommit(String xid,TccContext tccContext);

>  Boolean payRollback(String xid,TccContext tccContext);  

使用规范: 1 try方法,第一个参数需要xid,如果需要将try的参数传递到TccContext,通过@Attachment实现(扩展功能)。
2 commit/rollback 方法必须是2个参数,第一个参数是xid,第二个参数是TccContext tccContext
3 commit/rollback 方法返回值必须是Boolean, 返回true表示执行成功,返回false,表示执行失败。 4 主程序调用facade(try阶段) 如果发现facade返回业务异常,需要抛exception

4.2 分布式事务使用tcc @Resource AccountFacade accountFacade;

@Resource
ItemFacade itemFacade;

@Override
@TccTransactional(xidIndex = 0)
@Transactional()
public void placeOrder(String xid,String accountId,String productId,Double price) {
    accountFacade.pay(xid, accountId, price);
    itemFacade.sell(xid, productId, 1);
}

使用规范:1.xid(分布式事务id)由用户生成,传递给方法体。2.需要在方法体上加上 @TccTransactional(xidIndex = 0) ,其中xidIndex = 0表示,xid为方法体的第n个参数。
单元测试

@Test
public void testPlaceOrder(){
String xid = XidGenerator.getNewXid("OD");
orderService.placeOrder(xid, "1", "1", 1.00);
}
#测试tcc框架 tcc-demo里面有各种测试用例。方便了解tcc框架执行结果。测试用例的时候,可以通过tcc_tx,tcc_tx_child 查看事务的状态。
tcc事务状态:0 :begin,1:finish,2:try success,3 try fail,4:confirm fail,5:rollback fail。 参考com.touna.tcc.core.transaction.XaState定义

Clone this wiki locally
0