阿里面试题之服务调用过程中断电怎么办

490 阅读2分钟

前言

面试官就是想找事情,讲的好好的分布式事务方案,给你来断电,断电首先肯定去充电费啊。

场景

举一个电商常见的下单场景,伪代码如下


String createOrder(CreateOrderRequest request){
    
    try{
        transactionManger.execute((status)->{
            //锁定优惠券
        
            //校验,构造订单
            
            //同步订单中心
            
            //使用优惠券
            
            //同步支付中心
        })
        
    }catch(Exception ex){
        //回滚订单中心(重试)
        
        //解锁优惠券(先同步解锁优惠券,失败重试)
        
    }
}

上述代码,一旦try里面抛出异常,异常会自动回滚本地事务,因为使用的是编程式事务,我们捕获到异常,对第三方事务进行回滚。

这个方案看起来挺完美,能够保证最终一致性。

但是爱找事的面试官,问到,运行过程中断电了怎么办?

比如说,调用同步支付中心的时候断电了,但是订单中心和优惠中心的接口已经调用成功,现在存在的情况就是用户刷新订单列表能看到订单,但是支付不了。

解决方案

断电?我是不知道怎么解决的。

但是我们可以看看我们一些常见的中间件是如何解决这个问题的。

比如Mysql。

如果Mysql断电了,进行到一半的事务怎么回滚,还没刷盘的数据如何恢复。

它有undolog和redolog。

那么我们只需要在应用层创建自己的事务以及undolog就行了。

修改下上面的伪代码

String createOrder(CreateOrderRequest request){
    //开启应用级别事务
    
    try{
        transactionManger.execute((status)->{
            //开启应用级别事务
            //记录锁定优惠券 记录undolog
            //锁定优惠券
        
            //校验,构造订单
            
            //记录同步订单中心 记录undolog
            //同步订单中心
            
            //使用优惠券 记录undolog
            
            //同步支付中心 记录undolog
            
            //结束应用级别事务
        })
        
    //确认应用级别事务
    }catch(Exception ex){
        //回滚应用级别事务
    }
}

如果断电了,我们只需要后台一个线程去扫描那些超过一定期限没提交的事务,执行对应undolog的回滚逻辑。

总结

上面的方案纯属我自己的YY,在面试过程中,遇到这些变态的即兴问题,我觉得我这个方案回答的也还算可以。

即兴发挥才能考验你对自己学习的知识是否真的吸收,能否举一反三。