• 使用栈处理回滚


    简述:项目中回滚的方法很多种,目前我用到的一种是事务回滚。一种是是手动回滚。

    事务回滚就是让代码包在一个事务里面,然后所有的代码成功执行后,最后有一个提交的操作。 

    手动回滚,就是自己写代码处理回滚。

    写博客背景:

    我在公司负责的支付那块,开始用的事务回滚,将所有的支付逻辑都包在了一个大的事务里面,这样就会导致当有并发的时候,总是发生锁表问题。  然后采取的方案就是把大事务拆分成很多小事务,每个事务里面包含一个唯一的数据库操作逻辑。提交后外面代码写上对上步的回滚操作并放在栈里面,这样当有异常时,就会按照后进先出原则依次回滚。经过测试,成功解决了并发支付问题。 (PS:但是还有一个问题是,对于同一个数据,两个人同时支付会同时走支付代码,这块还没处理好业务并发,之前考虑加锁,但是这样系统就又变成了单线程执行,后面再考虑方案。)

    用控制台简单写了一个Demo,计算了一个累加的操作,然后每一步都记录了回滚,每一步异常都会回滚到最初的数据10上面。 

     目录结构如下:

    Program.cs 

      private static Stack<IRollBack> _rollBack = new Stack<IRollBack>();
            private static int Sum = 10;
            static void Main(string[] args)
            {
    
                try
                {
                  
                    int Num1 = 3;
                    int Num2 = 5;              
                    //定义一个元数据是Sum=10,Num1=3,Num2=5
                    //第一步: Sum=Sum+Num1   Sum=10+3=13  
                    //第一步回滚: Sum=Sum-Num1  Sum=13-3=10
                    Sum = Sum + Num1;
                    IRollBack r1 = new Num1RollBack(Sum, Num1);
                    _rollBack.Push(r1);
                   
                    //第二步: Sum=Sum+Num2  Sum=13+5=18
                    //第二步回滚: Sum=Sum-Num2  Sum=18-5=13
                    Sum = Sum + Num2;
                    IRollBack r2 = new Num1RollBack(Sum, Num2);
                    _rollBack.Push(r2);
                    Console.WriteLine(Sum);
    
                    //throw new Exception("测试回滚");
                    Console.WriteLine("zj...");
                    Console.ReadKey();
    
                }
                catch (Exception ex)
                {
                    RollBack();             
                }
    
                Console.ReadKey();
    
            }
    
            public static void RollBack()
            {
                IRollBack rollBack = null;
                while (_rollBack.Count>0)
                {
                    rollBack = _rollBack.Pop();
                    Sum=rollBack.RollBack();
                }
                Console.WriteLine(Sum);
            }

    IRollBack.cs

     public interface IRollBack
        {
            int RollBack();
        }

    Num1RollBack.cs

        public class Num1RollBack : IRollBack
        {
            private int _sum, _num1;
            public Num1RollBack(int sum,int num1)
            {
                _sum = sum;
                _num1 = num1;
            }
            public int RollBack()
            {
                return _sum - _num1;
            }
        }

    Num2RollBack.cs

        public class Num2RollBack : IRollBack
        {
            private int _sum, _num2;
            public Num2RollBack(int sum, int num2)
            {
                _sum = sum;
                _num2 = num2;
            }
            public int RollBack()
            {
                return _sum - _num2;
            }
        }

     一般情况下我们在web中都是操作的数据库,所以回滚接口定义成void即可,然后每个回滚实现接口处理回滚操作。

  • 相关阅读:
    MATLAB简易验证码识别程序介绍
    [Java面试三]JavaWeb基础知识总结.
    [Java面试十二]数据库概念相关
    [Java面试十一]数据库总结.
    [Java面试十]浏览器跨域问题.
    [Java面试九]脚本语言知识总结.
    [Java面试八]Hibernate总结以及在面试中的一些问题.
    [Java面试七]Mybatis总结以及在面试中的一些问题.
    [Java面试六]SpringMVC总结以及在面试中的一些问题.
    [Java面试五]Spring总结以及在面试中的一些问题.
  • 原文地址:https://www.cnblogs.com/shuai7boy/p/10185361.html
Copyright © 2020-2023  润新知