Coder Social home page Coder Social logo

tcc-transaction's Introduction

TCC-TRANSACTION

TCC-TRANSACTION是什么

TCC-TRANSACTION是一款开源的微服务架构下的TCC型分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。

  • Try: 尝试执行业务,完成所有业务检查(一致性),预留必须业务资源(准隔离性)
  • Confirm: 确认执行业务,不作任何业务检查,只使用Try阶段预留的业务资源,满足幂等性
  • Cancel: 取消执行业务,释放Try阶段预留的业务资源,满足幂等性

微服务架构中分布式事务问题

随着传统的单体架的构微服务化,原本单体架构中不同模块,被拆分为若干个功能简单、松耦合的服务。
系统微服务化后,内部可能需要调用多个服务并操作多个数据库实现,服务调用的分布式事务问题变的非常突出。

比如支付退款场景需要从各分账方退回平台收益户(退分账),再退还给付款方。其中退分账阶段, 涉及从多个分账方(商家1收益户,商家2收益户,商家3收益户,平台手续费账户)扣款,这些账户分布在不同数据库, 比如商家3收益户扣款失败,其他成功扣款需要回滚,这里需要分布式事务保证一致性。 支付退款流程

如何解决

如何解决上面退分账中分布式事务问题呢? 选择使用tcc-transaction框架,执行流程如下:

  • Try:
    商家1收益户->冻结分账金额
    商家2收益户->冻结分账金额
    商家3收益户->冻结分账金额
    平台手续费->冻结手续费
  • Try成功 => Confirm:
    商家1收益户->扣除分账金额
    商家2收益户->扣除分账金额
    商家3收益户->扣除分账金额
    平台手续费->扣除手续费
    平台收益户-> 增加金额(总分账金额+手续费)
  • Try失败 => Cancel:
    商家1收益户->解冻分账金额
    商家2收益户->解冻分账金额
    商家3收益户->解冻分账金额
    平台手续费->解冻手续费

工作原理

TCC原理

第一阶段:主业务服务分别调用所有从业务的 try 操作,并在活动管理器中登记所有从业务服务。当所有从业务服务的 try 操作都调用成功或者某个从业务服务的 try 操作失败,进入第二阶段。
第二阶段:活动管理器根据第一阶段的执行结果来执行 confirm 或 cancel 操作。
如果第一阶段所有 try 操作都成功,则活动管理器调用所有从业务活动的 confirm操作。否则调用所有从业务服务的 cancel 操作。
需要注意的是第二阶段 confirm 或 cancel 操作本身也是满足最终一致性的过程,在调用 confirm 或 cancel 的时候也可能因为某种原因(比如网络)导致调用失败,所以需要活动管理支持重试的能力,同时这也就要求 confirm 和 cancel 操作具有幂等性。

快速开始

官网
快速开始
最新可用版本2.x

常见问题

常见问题

讨论群

钉钉扫码入群

钉钉扫码入群

tcc-transaction's People

Contributors

changmingxie avatar code1986 avatar cyrilfeng avatar guanminwei avatar itonyli avatar nervose avatar neumann789 avatar recklessmo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tcc-transaction's Issues

分布式环境运行下内存潜在错误

如果有两个User RPC 应用 。 try,和confirm和rollback可能不会落在同一台服务器上
关于 transaction 的本地jvm缓存可能无法清除,长期后果,是否可能导致内存溢出
google的cache 组件,是否能保障内存不会溢出
如果User实例增多,缓存穿透会愈加明显,是否可考虑分布式缓存

实现原理没看懂,谁能解答下

1.为什么执行
String result = capitalTradeOrderService.record(null, buildCapitalTradeOrderDto(order));
是先被TccTransactionContextAspect拦截的,他的order值比较大,不应该是TccCompensableAspect先拦截嘛?

2.异常的时候具体是哪段代码会去调用cancel的方法

急!基于soa的事务管理疑问

按照您的代码实现来看,请问如何解决下面这个场景的问题:
1、一个事务下有两个参与者service1、service2,service1 转账100元给service2
2、try 阶段,service1 - 100 ,成功。service2 + 100 ,失败。
3、cancel阶段,service1、service2都执行cancel方法,service1 + 100,service2 - 100
4、 结果就是 service1、 service2 回滚到未转账之前的状态,一切看起来很完美!

但是, service2虽然失败了,但一定需要cancel吗?

比如 service2中的方法是这样写的:

public void transferTo(TransactionContext transactionContext, long accountId, int amount) {
       throw new Exception("我故意抛异常"); // 方法立即抛异常
       accoutDao.addBalanceAmount(accountId,amount);// service2 加了100元 
}

然后在cancel 阶段 ,service1+100、service2-100
但是service2之前根本没有加过100
结果就是service1 金额正确,service2 金额被无缘无故的减了100

问题就在于:基于服务而不是基于数据库资源的事务管理,在不能判断抛异常是由于其他业务逻辑造成还是因为数据库操作失败造成的情况下就进行回滚是存在问题的

关于性能问题讨论

从我实际联系中,发现使用JDK序列化后,Transaction对象产生的byte[]会达到几K,每次commit,cancel都要update content字段,是否存在性能隐患?

KryoTransactionSerializer 进行序列化,反序列化,在处理List participants时出错。

新版本独立事务库问题

不建议采用独立事务库
1:大压力下,独立事务库性能是否会成为瓶颈
2:独立事务库,会给系统带来额外的不确定性。本身它不属于业务库,但它出现问题,会导致整个系统无法运行

分布式事务发起问题

在demo#PlaceOrderServiceImpl类中,调用两个RPC接口,没有发现有相关的分布式事务发起的动作。在具体配置中也没有具体的说明!望解答!

分布式环境运行下job运行潜在错误

如果有多个项目共用一个数据库。如 user,order。并且,user和order启动了多个实例。是否会出现以下情况
1:user和order 的各个实例中的自动job,会重复处理数据库中的异常root事务
2:由于user和order 引入的jar不同,会导致在confirm或rollback阶段,无法从applicationContext中取得对应处理类

Confirm异常问题

如果在Confirm中抛出异常,异常会抛给服务调用方吗?
如果Confirm抛出异常,是否所有事务步骤中的都会调用cancel接口?

更新到1.1.2版报错,感觉是新增的序列化有问题

[ERROR][20160723 23:38:06,215][TransactionManager:102] compensable transaction confirm failed.
org.mengyun.tcctransaction.SystemException: java.lang.reflect.InvocationTargetException
at org.mengyun.tcctransaction.Terminator.invoke(Terminator.java:89)
at org.mengyun.tcctransaction.Terminator.commit(Terminator.java:49)
at org.mengyun.tcctransaction.Participant.commit(Participant.java:46)
at org.mengyun.tcctransaction.Transaction.commit(Transaction.java:136)
at org.mengyun.tcctransaction.TransactionManager.commit(TransactionManager.java:99)
at org.mengyun.tcctransaction.interceptor.CompensableTransactionInterceptor.rootMethodProceed(CompensableTransactionInterceptor.java:86)
at org.mengyun.tcctransaction.interceptor.CompensableTransactionInterceptor.interceptCompensableMethod(CompensableTransactionInterceptor.java:51)
at org.mengyun.tcctransaction.spring.TccCompensableAspect.interceptCompensableMethod(TccCompensableAspect.java:49)
at sun.reflect.GeneratedMethodAccessor231.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:633)
at com.xxx.service.trade.impl.PaymentManagerImpl$$EnhancerBySpringCGLIB$$603ab65b.completeOrder()
at com.xxx.service.trade.aip.impl.PaymentManagerServiceImpl.completePay(PaymentManagerServiceImpl.java:267)
at com.xxx.service.trade.aip.impl.PaymentManagerServiceImpl$$FastClassBySpringCGLIB$$abb72538.invoke()
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:700)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:633)
at com.xxx.service.trade.aip.impl.PaymentManagerServiceImpl$$EnhancerBySpringCGLIB$$dfa1887b.completePay()
at com.alibaba.dubbo.common.bytecode.Wrapper7.invokeMethod(Wrapper7.java)
at com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:46)
at com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:72)
at com.alibaba.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:53)
at com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:64)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:42)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:75)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:78)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:60)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:112)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:38)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:108)
at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:84)
at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:170)
at com.alibaba.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:52)
at com.alibaba.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:82)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor234.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.mengyun.tcctransaction.Terminator.invoke(Terminator.java:86)
... 57 more
Caused by: java.lang.RuntimeException: org.mengyun.tcctransaction.repository.TransactionIOException: java.lang.IndexOutOfBoundsException: Index: 186, Size: 38
org.mengyun.tcctransaction.repository.TransactionIOException: java.lang.IndexOutOfBoundsException: Index: 186, Size: 38
at org.mengyun.tcctransaction.repository.JdbcTransactionRepository.doFind(JdbcTransactionRepository.java:245)
at org.mengyun.tcctransaction.repository.JdbcTransactionRepository.doFindOne(JdbcTransactionRepository.java:153)
at org.mengyun.tcctransaction.repository.CachableTransactionRepository.findByXid(CachableTransactionRepository.java:77)
at org.mengyun.tcctransaction.TransactionManager.propagationExistBegin(TransactionManager.java:72)
at org.mengyun.tcctransaction.interceptor.CompensableTransactionInterceptor.providerMethodProceed(CompensableTransactionInterceptor.java:109)
at org.mengyun.tcctransaction.interceptor.CompensableTransactionInterceptor.interceptCompensableMethod(CompensableTransactionInterceptor.java:54)
at org.mengyun.tcctransaction.spring.TccCompensableAspect.interceptCompensableMethod(TccCompensableAspect.java:49)
at sun.reflect.GeneratedMethodAccessor28.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:633)
at com.xxx.service.point.aip.impl.AccountServiceImpl$$EnhancerBySpringCGLIB$$95cd7c66.creditToPointAccountTcc()
at com.alibaba.dubbo.common.bytecode.Wrapper0.invokeMethod(Wrapper0.java)
at com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:46)
at com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:72)
at com.alibaba.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:53)
at com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:64)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:42)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:75)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:78)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:60)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:112)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:38)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:108)
at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:84)
at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:170)
at com.alibaba.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:52)
at com.alibaba.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:82)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.IndexOutOfBoundsException: Index: 186, Size: 38
at java.util.ArrayList.rangeCheck(ArrayList.java:635)
at java.util.ArrayList.get(ArrayList.java:411)
at com.esotericsoftware.kryo.util.MapReferenceResolver.getReadObject(MapReferenceResolver.java:60)
at com.esotericsoftware.kryo.Kryo.readReferenceOrNull(Kryo.java:857)
at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:707)
at org.mengyun.tcctransaction.serializer.KryoTransactionSerializer.deserialize(KryoTransactionSerializer.java:44)
at org.mengyun.tcctransaction.serializer.KryoTransactionSerializer.deserialize(KryoTransactionSerializer.java:17)
at org.mengyun.tcctransaction.repository.JdbcTransactionRepository.doFind(JdbcTransactionRepository.java:241)
... 43 more

    at com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:108)
    ... 23 more

maven构建总是失败

build完tcc-transaction-api,再build tcc-transaction-core 报错,找不到tcc-transaction-api,其它工程构建也报错,请问是什么问题?

ResourceCoordinatorInterceptor代码疑问

如标题中的类,以下代码是什么意思,consumer和provider是什么
MethodType methodType = CompensableMethodUtils.calculateMethodType(transactionContext, compensable != null ? true : false);

        switch (methodType) {
            case ROOT:
                generateAndEnlistRootParticipant(pjp);
                break;
            case CONSUMER:
                generateAndEnlistConsumerParticipant(pjp);
                break;
            case PROVIDER:
                generateAndEnlistProviderParticipant(pjp);
                break;
        }

Consumer和Provider

在看了源码之后,关于Consumer和Provider不是很明白?和事务本身有什么关系呢?
public static MethodType calculateMethodType( TransactionContext transactionContext, boolean isCompensable) {
if (transactionContext == null && isCompensable) {
//isRootTransactionMethod
return MethodType.ROOT;
} else if (transactionContext == null && !isCompensable) {
//isSoaConsumer
return MethodType.CONSUMER;//
} else if (transactionContext != null && isCompensable) {
//isSoaProvider
return MethodType.PROVIDER;
} else {
return MethodType.NORMAL;
}
}
1、对于ROOT,Consumer,Provider的定义是如何的呢?能否以transferTo方法来说明下呢?
2、Consumer,Provider消费的内容是什么呢?Transaction么?
也可以通过QQ交流:475726357

tcc-transaction-server中的分页问题

tcc-transaction-server中的分页问题。
TransactionController.java中的 modelAndView.addObject("urlWithoutPaging", tccDomain + "/manager/domain/" + domain); 应改为 modelAndView.addObject("urlWithoutPaging", tccDomain + "/management/domain/" + domain);

关于事务绑定方法的返回值

为了捕捉try方法中的校验不通过信息,给事务绑定的方法添加了返回值,但在调用赋值时一直只能获取到null值,请问是我调用的方法不对吗?

调用大概如下,参数与具体逻辑省略了:

CommonResponse response = paymentService.makePayment();

@Compensable(confirmMethod = "confirmMakePayment",cancelMethod = "cancelMakePayment")
public CommonResponse makePayment(){
}
public CommonResponse confirmMakePayment(){
}
public CommonResponse cancelMakePayment(){
}

create_db_ord.sql

create_db_ord.sql中的INSERT INTO ORD_SHOP (SHOP_ID,OWNER_USER_ID) VALUES (1,10000);其中的10000要改成1000才对,要不然,跟账户中的用户ID对不上。

tcc移植到现有项目 通不过

这一块不太熟。
现有项目不是用maven搭建的;用的是spring 4.0.4,
我现在引入tcc-transaction-spring-1.1.2.jar、tcc-transaction-core-1.1.2.jar、tcc-transaction-api-1.1.2.jar(spring 4.0.4下编译的)以及其他依赖jar包, 按照说明加tcc-transaction.xml, 启动的时候提示
Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tccCompensableAspect' defined in class path resource [tcc-transaction.xml]: Cannot resolve reference to bean 'compensableTransactionInterceptor' while setting bean property 'compensableTransactionInterceptor'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'compensableTransactionInterceptor' defined in class path resource [tcc-transaction.xml]: Cannot resolve reference to bean 'tccTransactionConfigurator' while setting bean property 'transactionConfigurator'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tccTransactionConfigurator': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.mengyun.tcctransaction.TransactionRepository org.mengyun.tcctransaction.spring.support.TccTransactionConfigurator.transactionRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.mengyun.tcctransaction.TransactionRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)};

关于datasource注入问题

您好,参考您这个tcc项目,感觉质量还是非常高的。遇到一个问题:JdbcTransactionRepository这个类里面datasource没有注入成功,我是通过直接初始化实现的,求解。
另;FileSystemTransactionRepository、RedisTransactionRepository、ZooKeeperTransactionRepository这几个数据源是怎么应用的呢?感谢!

TCC过程中Try阶段失败,应该不用执行当前过程的Cancel

例如A调用B ,A执行完Try过程,B执行Try失败。
我理解由于B的Try是本地事务遇到Exception已经rollback了,所以不需要执行cancel流程,只需要执行A的cancel即可。但是目前的框架还是会同时执行B的cancel和A的cancel,是不是控制上不太对?

非XA协议的数据库支持吗

你好。我在本地测试过使用mysql作为db来测试demo,是可以正常跑的。但是我们看到你在api包里里写了TransactionXid集成了xa包下的Xid,那么意味着你这里的事务其实是要数据库支持XA的。如果我使用了不支持XA事务的数据库,例如PostgreSQL 这样的数据库。是否还可以用该框架呢。我需要作什么样的调整呢

发现了几个问题 请教一下

  1. dubbo使用注解的方式无效 ResourceCoordinatorInterceptor 的interceptTransactionContextMethod这个方法,methodType永远为root
    2.http方式请求的时候也是一样的

try失败后,cancel给账户加了余额

在跑demo的时候,发现账户用户的账户余额为0的时候,跑了一下流程
order try make payment called
java.lang.RuntimeException: not enough balance!
capital try record called
java.lang.RuntimeException: not enough balance!
order cancel make payment called
capital cancel record called
用户的账户余额多出了50块钱。。。是理解不对还是程序bug?

tccdemo中TCC的根confirm没有触发。

tcc-transaction-dubbo-sample 实例 order ,cap,red中下订单时,ord try方法调用cap,red的try方法后,order的confirm没有调用,cap,red的confirm方法调用,但是订单的状态还是PAYING状态,confirm方法会异常?这应该不可能呀,这个只是改order的状态。后台也没有出现异常栈。那这样的话是不是就没有起到tcc的事务控制功能。
makePayment try

capital try record called
capital confirm record called

red packet try record called
red packet confirm record called

Confirm问题

1、远程的confirm方法(如sample中的capital服务中的Confirm),是由远程服务自己调用,还是由发起方(order)调用
2、如果capital的confirm成功,order的confirm失败后,怎么办

调用一次失败后 启动Dubbo服务,定时任务每次调用都失败,使用的是redis持久化

[recoverScheduler_Worker-1]-[ERROR] 2016-08-11 14:01:00.119 com.haiyunx.tcc.core.order.biz.OrderBiz ========= orderbiz cancelRecord :null
[recoverScheduler_Worker-1]-[WARN] 2016-08-11 14:01:00.139 TransactionRecovery recover failed, txid:b080c88a-9b94-3d58-a3d9-d001a75bc247|7116ea1a-ae1c-3a25-9af8-8383cc053655, status:3,retried count:18
org.mengyun.tcctransaction.SystemException: java.lang.reflect.InvocationTargetException
at org.mengyun.tcctransaction.Terminator.invoke(Terminator.java:55)
at org.mengyun.tcctransaction.Terminator.rollback(Terminator.java:34)
at org.mengyun.tcctransaction.Participant.rollback(Participant.java:27)
at org.mengyun.tcctransaction.Transaction.rollback(Transaction.java:91)
at org.mengyun.tcctransaction.recover.TransactionRecovery.recoverErrorTransactions(TransactionRecovery.java:78)
at org.mengyun.tcctransaction.recover.TransactionRecovery.startRecover(TransactionRecovery.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:273)
at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:311)
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:113)
at org.quartz.core.JobRunShell.run(JobRunShell.java:223)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.mengyun.tcctransaction.Terminator.invoke(Terminator.java:52)
... 14 more
Caused by: com.alibaba.dubbo.rpc.RpcException: Failed to invoke the method record in the service com.haiyunx.tcc.facade.account.service.AccountFacade. No provider available for the service com.haiyunx.tcc.facade.account.service.AccountFacade from registry localhost:2181 on the consumer 192.168.0.189 using the dubbo version 2.4.10. Please check if the providers have been started and registered.
at com.alibaba.dubbo.rpc.cluster.support.AbstractClusterInvoker.checkInvokers(AbstractClusterInvoker.java:245)
at com.alibaba.dubbo.rpc.cluster.support.FailoverClusterInvoker.doInvoke(FailoverClusterInvoker.java:55)
at com.alibaba.dubbo.rpc.cluster.support.AbstractClusterInvoker.invoke(AbstractClusterInvoker.java:226)
at com.alibaba.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker.invoke(MockClusterInvoker.java:72)
at com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler.invoke(InvokerInvocationHandler.java:52)
at com.alibaba.dubbo.common.bytecode.proxy0.record(proxy0.java)
at com.alibaba.dubbo.common.bytecode.proxy0$$FastClassByCGLIB$$8a5e27.invoke()
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:91)
at org.mengyun.tcctransaction.interceptor.ResourceCoordinatorInterceptor.interceptTransactionContextMethod(ResourceCoordinatorInterceptor.java:53)
at org.mengyun.tcctransaction.spring.TccTransactionContextAspect.interceptTransactionContextMethod(TccTransactionContextAspect.java:29)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
at com.alibaba.dubbo.common.bytecode.proxy0$$EnhancerByCGLIB$$4c4f39f6.record()
... 19 more

帐户在record阶段的操作是否需要加锁?

CapitalTradeOrderServiceImpl {
record () {
capitalAccountRepository.findByUserId() // 读取账户余额
// 判断余额是否足够
capitalAccountRepository.save() // 保存账户余额 - 花费
}
读取账户余额的时候是否需要加锁?
还是有其他机制保证操作的原子性

请教下调用逻辑

请教下, order中调用 capitalTradeOrderServiceImpl.record后,如果record try时失败,order怎么会知道record和try失败了呢 看了源码不太理解这个是怎么处理的,进入这些方法的时候aop处理了transcation表 这个倒是清楚的

异常崩溃情况下,有些未完成的事务会一直处于Trying阶段无法继续下去,造成事务不一致

分析代码发现TransactionManager代码中的commit和rollback方法中,如果在更新数据库记录变更事务状态前,虚拟机被kill了,之前Trying阶段的事务会一直处于Trying阶段,无法继续处理下去,TransactionRecoveryJob不处理这中情况,造成事务不一致。是否可以考虑加上事务超时机制,后台定时扫描超时Trying阶段事务,使得这中情况下可以保证事务一致性。

public void rollback() {

        Transaction transaction = getCurrentTransaction();

        transaction.changeStatus(TransactionStatus.CANCELLING);

        /**********************************************************************************/
        /**在这个位置JVM崩溃了,事务将会一直处于Trying阶段***/
        /**********************************************************************************/

        try {
            transactionConfigurator.getTransactionRepository().update(transaction);
            transaction.rollback();
            transactionConfigurator.getTransactionRepository().delete(transaction);
        } catch (Throwable rollbackException) {
            if (transaction.getTransactionType().equals(TransactionType.ROOT)) {
                transactionConfigurator.getTransactionRepository().addErrorTransaction(transaction);
            }
            throw new RuntimeException(rollbackException);
        }

    }

事务恢复代码疑问

private List<Transaction> loadErrorTransactions() {

    TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository();

    long currentTimeInMillis = Calendar.getInstance().getTimeInMillis();

    List<Transaction> transactions = transactionRepository.findAllUnmodifiedSince(new Date(currentTimeInMillis - transactionConfigurator.getRecoverConfig().getRecoverDuration() * 1000));

    List<Transaction> recoverTransactions = new ArrayList<Transaction>();

    for (Transaction transaction : transactions) {

        int result = transactionRepository.update(transaction);

        if (result > 0) {
            recoverTransactions.add(transaction);
        }
    }

    return transactions;
}

返回的对像为什么不是 recoverTransactions

异常

在流程完成后,程序会调用在tcc-transaction-core的org.mengyun.tcctransaction.invoke方法中调用org.mengyun.tcctransaction.sample.dubbo.capital.api.CapitalTradeOrderService的record会出现InvocationTargetException 请问是怎么回事啊

capital confirm record called
[sample-dubbo-capital]2016-09-29 17:36:33,226 ERROR [TransactionManager] compensable transaction confirm failed.
org.mengyun.tcctransaction.SystemException: java.lang.reflect.InvocationTargetException
at org.mengyun.tcctransaction.Terminator.invoke(Terminator.java:55)
at org.mengyun.tcctransaction.Terminator.commit(Terminator.java:30)
at org.mengyun.tcctransaction.Participant.commit(Participant.java:31)
at org.mengyun.tcctransaction.Transaction.commit(Transaction.java:85)
at org.mengyun.tcctransaction.TransactionManager.commit(TransactionManager.java:62)
at org.mengyun.tcctransaction.interceptor.CompensableTransactionInterceptor.providerMethodProceed(CompensableTransactionInterceptor.java:78)
at org.mengyun.tcctransaction.interceptor.CompensableTransactionInterceptor.interceptCompensableMethod(CompensableTransactionInterceptor.java:43)
at org.mengyun.tcctransaction.spring.TccCompensableAspect.interceptCompensableMethod(TccCompensableAspect.java:29)
at sun.reflect.GeneratedMethodAccessor35.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)

order try make payment called
order confirm make payment called
[sample-dubbo-order]2016-09-29 17:28:18,942 ERROR [TransactionManager] compensable transaction confirm failed.
org.mengyun.tcctransaction.SystemException: java.lang.reflect.InvocationTargetException
at org.mengyun.tcctransaction.Terminator.invoke(Terminator.java:55)
at org.mengyun.tcctransaction.Terminator.commit(Terminator.java:30)
at org.mengyun.tcctransaction.Participant.commit(Participant.java:31)
at org.mengyun.tcctransaction.Transaction.commit(Transaction.java:85)
at org.mengyun.tcctransaction.TransactionManager.commit(TransactionManager.java:62)
at org.mengyun.tcctransaction.interceptor.CompensableTransactionInterceptor.rootMethodProceed(CompensableTransactionInterceptor.java:64)
at org.mengyun.tcctransaction.interceptor.CompensableTransactionInterceptor.interceptCompensableMethod(CompensableTransactionInterceptor.java:41)
at org.mengyun.tcctransaction.spring.TccCompensableAspect.interceptCompensableMethod(TccCompensableAspect.java:29)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.