Redis的基础事务与ABA问题

Redis的基础事务与ABA问题

Bryce_Huang

文章目录

 

Redis的基础事务

一,Redis的事务命令

命令说明备注
multi使用该命令开启事务该命令后的操作指令会进入队列,并不会直接开始执行
watch key1 [key2……]监听某些键当被监听的键的事务执行前被修改,则事务发生回滚。使用乐观锁
unwatch key1 [key2……]取消监听某些键 
exec执行事务命令如果被监听的键没有被修改,就执行事务,否则发生回滚
discard回滚事务命令回滚进入队列的事务命令,之后就不能再用exec命令提交了

二,Redis事务的基本流程

2.1,没有添加监听的基本事务的执行流程

  • 1,开启事务。
  • 2,命令进入队列。
  • 3,执行事务

2.1.1 控制台的执行效果

在这里插入图片描述

2.1.2 代码实现简单事务流程

 public static void main(String[] args) {

        ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        final RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
        SessionCallback sessionCallback = new SessionCallback() {
            @Override
            public Object execute(RedisOperations ops) throws DataAccessException {
//                开启事务
                ops.multi();
//                存储set指令,该指令会将进入队列中,queued
                ops.boundValueOps("key1").set("value1");
                String value = (String) ops.boundValueOps("key1").get();
                System.out.println("在没有执行exec命名前是否执行存储操作:" + value);
//        执行事务,此时List会保存之前进入队列的所有命令执行的结果
                List list = ops.exec();
                value = (String) redisTemplate.opsForValue().get("key1");
                return value;
            }
        };
        String value = (String) redisTemplate.execute(sessionCallback);
        System.out.println(value);
    }
  •  

2.2,添加监听的事务的执行流程

2.2.1 执行流程图

在这里插入图片描述

2.2.2 添加监视的控制台实现

在这里插入图片描述

三,Redis不会产生ABA问题

3.1 redis参考了多线程中的CAS

Redis的事务操作参考了多线程中的CAS(比较与交换,Compare And Swap)去执行,这是一种乐观锁。
如:某些数据可能被多个业务所共享,当线程T1去执行业务逻辑时,其他共享的线程操作改数据,就可能导致多线程中数据的不一致情况。为了解决这一问题,线程在读取共享数据前,会对共享数据加上监视,保存到线程的副本中,这就是旧值。而在redis中使用了watch指令去实现这一功能,当事务执行时,去对比旧值,如果不一致就回滚。但是这种操作CAS在多线程中可能出现ABA问题

3.2 什么是ABA问题

时间线程1线程2操作
T1X=A-线程1加入监控X,此时共享数据X的值为A
T2执行复杂业务逻辑修改X=B线程2修改X为B
T3执行复杂业务逻辑执行业务逻辑线程二执行本身的简单业务逻辑
T4执行复杂业务逻辑修改X=A线程2修改X为A
T5执行复杂业务逻辑线程2退出此时X仍然为A
T6与旧值进行比较X=A,旧值未改变-CAS原理检查通过,旧值未发生变化

当执行到T6的时候,在T2—T5的时刻,线程2对于X的修改可能已经导致了线程1的业务运算发生了错误。但是CAS原理对于旧值的检查显示旧值未发生改变,因此仍然视作正确的。这就是CAS导致的ABA问题。
在redis的机制中不会出现ABA的问题
自己看到了两个答案,

  • Redis是单线程的。CAS出现于多线程中。(自己更认可该答案。)
  • 还有一种说法是:Redis执行事务时的watch命令,对比的是数据的版本号,而不是值,通过对比版本来判断值是否发生过变化。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值