rainCat事物框架核心原理解析

 

StartTxTransactionHandler

 

这里参与者(消费端)自己的事物最后提交需要等待

  final Boolean commit = txManagerMessageService.preCommmitTxTransaction(groupId); ---netty阻塞等待 所有参与者的事物正常提交,之后提交自己的事物

整个事物连中有一个事物异常发起者通知这个消息事物的提交回滚--发起者调用参与者

 //通知tm整个事务组失败,需要回滚,(回滚那些正常提交的模块,他们正在等待通知。。。。)

txManagerMessageService.rollBackTxTransaction(groupId);

 

 

  ActorTxTransactionHandler  提供方提交事物

 

 

 

大致的思路都是用了自定义的锁

final BlockTask task = BlockTaskHelper.getInstance().getTask(taskKey);

 

 

主线程等待,一个定时线程池轮询协调者状态可以就向下执行,提交---这就是阻塞等待的原理

 

 

//线程轮询

 transactionThreadPool

                .newFixedThreadPool()

                .execute(() -> {

                    final String waitKey = IdWorkerUtils.getInstance().createTaskKey();

                    final BlockTask waitTask = BlockTaskHelper.getInstance().getTask(waitKey);

                    DefaultTransactionDefinition def = new DefaultTransactionDefinition();

                    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);

                    TransactionStatus transactionStatus = platformTransactionManager.getTransaction(def);

                      /*

                      1 设置返回数据res

                      2 唤醒主线程

                      3  向TxManager 发送提交整个事务组请求

                      4 自身进入阻塞,等待TxManager通知是否提交 超时会唤醒  我觉得这里应该是继续提交

                      5 TxManager 发送提交通知,唤醒线程, 进行提交

                      6 提交完成后,想txManager 发送事务已经完成的通知

                     */

                    try {

 

                        //添加事务组信息

                        final Boolean success = txManagerMessageService.addTxTransaction(info.getTxGroupId(),

                                build(waitKey, info));

                        if (success) {

                            //发起调用

                            final Object res = point.proceed();

 

                            //设置返回数据,并唤醒之前等待的主线程

                            task.setAsyncCall(objects -> res);

                            task.signal();

 

                            //调用成功 保存本地补偿信息

                            String compensateId = txCompensationCommand.saveTxCompensation(info.getInvocation(),

                                    info.getTxGroupId(), waitKey);

 

                            /*

                             *

                             *等待txManager通知(提交或者回滚) 此线程唤醒(txManager通知客户端,然后唤醒)

                             * 如果此时TxManager down机或者网络通信异常 需要再开一个调度线程来唤醒

                             */

                            final ScheduledFuture scheduledFuture = transactionThreadPool.multiScheduled(() -> {

                                LogUtil.info(LOGGER, "事务组id:{},自动超时处理", info::getTxGroupId);

                                final BlockTask blockTask = BlockTaskHelper.getInstance().getTask(waitKey);

                                if (!blockTask.isNotify()) {

                                    //如果获取通知超时了,那么就去获取事务组的状态

                                    final int transactionGroupStatus = txManagerMessageService.findTransactionGroupStatus(info.getTxGroupId());

                                    if (TransactionStatusEnum.PRE_COMMIT.getCode() == transactionGroupStatus ||

                                            TransactionStatusEnum.COMMIT.getCode() == transactionGroupStatus) {

                                        //如果事务组是预提交,或者是提交状态

                                        //表明事务组是成功的,这时候就算超时也应该去提交

                                        waitTask.setAsyncCall(objects -> TransactionStatusEnum.COMMIT.getCode());

                                        waitTask.signal();

 

                                    } else {

                                        LogUtil.info(LOGGER, "事务组id:{},自动超时进行回滚!", info::getTxGroupId);

                                        waitTask.setAsyncCall(objects -> NettyResultEnum.TIME_OUT.getCode());

                                        waitTask.signal();

                                    }

                                    LOGGER.error("============通过定时任务来唤醒线程!事务状态为:{}", transactionGroupStatus);

                                    return true;

                                } else {

                                    return false;

                                }

 

                            }, info.getWaitMaxTime());

 

                            waitTask.await();

 

                            LogUtil.info(LOGGER, "已经成功接收txManager指令,并执行!{}",

                                    () -> info.getTxGroupId() + ":" + waitKey);

                            try {

 

                                //如果已经被唤醒,就不需要去执行调度线程了 ,关闭上面的调度线程池中的任务

                                if (!scheduledFuture.isDone()) {

                                    scheduledFuture.cancel(false);

                                }

                                final Integer status = (Integer) waitTask.getAsyncCall().callBack();

                                if (TransactionStatusEnum.COMMIT.getCode() == status) {

 

                                    //提交事务

                                    platformTransactionManager.commit(transactionStatus);

 

                                    //通知tm 自身事务提交

                                    asyncComplete(info.getTxGroupId(), waitKey,

                                            TransactionStatusEnum.COMMIT.getCode(), res);

 

                                } else {

                                    //回滚当前事务

                                    platformTransactionManager.rollback(transactionStatus);

 

 

                                    //通知tm 自身事务回滚

                                    asyncComplete(info.getTxGroupId(), waitKey,

                                            TransactionStatusEnum.ROLLBACK.getCode(), res);

 

                                }

                            } catch (Throwable throwable) {

                                platformTransactionManager.rollback(transactionStatus);

                                throwable.printStackTrace();

                            } finally {

                                BlockTaskHelper.getInstance().removeByKey(waitKey);

                                //删除本地补偿信息

                                txCompensationCommand.removeTxCompensation(compensateId);

                            }

 

                        } else {

                            platformTransactionManager.rollback(transactionStatus);

                        }

 

                    } catch (final Throwable throwable) {

                        throwable.printStackTrace();

                        //如果有异常 当前项目事务进行回滚

                        platformTransactionManager.rollback(transactionStatus);

                        //通知tm 自身事务失败

                        asyncComplete(info.getTxGroupId(),

                                waitKey, TransactionStatusEnum.FAILURE.getCode(), throwable.getMessage());

 

                        task.setAsyncCall(objects -> {

                            throw throwable;

                        });

                        task.signal();

 

                    }

 

                });

 

 

//主线程等待

 

        task.await();

 

 

 

 

 

 

 

回滚(也用消息日志中的信息回滚),提交成功,同时也删除消息事物日志  txCompensationCommand.removeTxCompensation(compensateId);

补偿回滚(也用消息日志中的信息提交)----宕机

//调用成功 保存本地补偿信息

                            String compensateId = txCompensationCommand.saveTxCompensation(info.getInvocation(),

                                    info.getTxGroupId(), waitKey);

专门有一个线程不断轮询queue中的补偿信息,只要状态对,就执行补偿

StartCompensationHandler:补偿就是哪个事物回滚就去除这个事物消息组中的补偿信息(根据状态)(TxCompensationServiceImpl)

检查补偿队列补偿信息(根据状态)就进入补偿处理器:再一次执行业务代码,提交事物

@Service

public class TxTransactionFactoryServiceImpl implements TxTransactionFactoryService {

    @Override

    public Class factoryOf(TxTransactionInfo info) throws Throwable {

        if (StringUtils.isNoneBlank(info.getCompensationId())) {

            return StartCompensationHandler.class;

        }

        if (StringUtils.isBlank(info.getTxGroupId())) {

            return StartTxTransactionHandler.class;

        } else {

            if (Objects.equals(CommonConstant.COMPENSATE_ID, info.getTxGroupId())) {

                return InsideCompensationHandler.class;

            }

            return ActorTxTransactionHandler.class;

        }

    }

}

补偿处理器再次处理业务方法,提交一次

 final Object proceed = point.proceed();

            platformTransactionManager.commit(transactionStatus);

最后删除整个补偿信息

 TxTransactionLocal.getInstance().removeTxGroupId();

            CompensationLocal.getInstance().removeCompensationId();

    

 

猜你喜欢

转载自yuhuiblog6338999322098842.iteye.com/blog/2419431
今日推荐