基于重试机制的分布式事务方法论

0 来张图

总体

1 首先定义远程服务提供的服务

1.1 定义接口

/**
 * Created by haoran_10 on 2017/8/6.
 * 远程服务
 */
public interface RpcService {

    /**
     * 执行服务
     * @param inParam
     * @return
     */
    public Result<T> execute(ContextDTO contextDTO);

    /**
     * 取消服务
     * @param contextDTO
     * @return
     */
    public Result<T> cancel(ContextDTO contextDTO);
}

1.2 返回结果

  • 成功结果
  • 业务类型错误结果
  • 不可预知系统错误结果

1.3 远程服务要求

  • 执行服务&取消服务 都要求幂等性

2.调用远程服务

public boolean doDistributedTransaction(ContextDTO contextDTO){
    try{
        //1.执行本地服务
        callLocalService(contextDTO);

        //2.执行远程服务A
        try{
            //2.1 调用远程服务
            Result rpcA = rpcServiceA.execute(contextDTO);

            //2.1.1 业务结果错误,直接返回
            if(rpcA.businessError()){
                log.error("call rpc execute business error,rpcA:{}",rpcA);
                //抛出回滚
                throw RollbackException(contextDTO);
            }

            //2.1.2 系统结果错误,加入重试任务
            if(rpcA.systemError()){
                log.error("call rpc execute system error,rpcA:{}",rpcA);
                saveRetryTask(contextDTO);
            }

            //2.1.3  调用成功,继续下面的远程调用
            if(rpcA.success()){
                
            }
        }catch(Exception rpcAException){
            //2.1.4 捕获异常,执行重试
            log.error("call rpc execute is error,{}",rpcAException);
            saveRetryTask(contextDTO);
        }

        //3. 执行远程服务B
        Result rpcB = rpcServiceB.confirm(contextDTO);
        //....

        //n. 执行远方服务N
        //...

    }catch(Exception e){
        //记录错误日志
        log.error("doDistributedTransaction is error,contextDTO:{};e:{}",contextDTO,e);

        //如果回滚异常,回滚服务
        if(e instanceof  RollbackException){
            rollBack(contextDTO);
        }else{
            saveRetryTask(contextDTO);
        }
    }
}
  • 要求请求远程服务时,由调用方生成唯一key,确保业务唯一性

3.回滚服务

public boolean rollBack(ContextDTO contextDTO){
    rpcServiceA.cancel(contextDTO);
    rpcServiceB.cancel(contextDTO);
    rpcServiceN.cancel(contextDTO);
}
  • 这里要求取消必定成功,如果不成功,可以加入重试任务服务重试回滚

4.重试服务

//异步式执行重试任务
public void retryTaskCenter(){
    int defineRetryTimes = 3;//定义重试次数
    while(true){
        //查询出需要重试任务的数据
        List<RetryTask> list = queryRetryTask(queryParam);
        for(RetryTask retryTask:list){
            ContextDTO contextDTO = buildContextDTOFromRetryTask(retryTask);
            int retryTimes = 0;

            while(retryTimes<defineRetryTimes){
                //继续执行远程服务
                //这里可根据状态定位到执行调用哪一个远程服务,避免每次重复调用
                doDistributedTransaction(contextDTO);
                retryTimes++;
            }
        }
    }
}

5.使用场景

  • 调用链路较短
  • 要求分布式强一致性

如果时调用链路非常长,则非常推荐使用一致性消息机制

6.end,enjoy

转载于:https://my.oschina.net/haoran100/blog/1503607

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值