redis一些关于SessionCallback和事务要注意的地方

文章目录

          • 1. redisTemplate
          • 2. StringRedisTemplate
          • 3. 测试SessionCallBack
          • 4 . redis相关的同样适用lambda
          • 5.Redis SessionCallback和redis 事务的区别
          • 6. redis事务和MySQL事务的区别

1. redisTemplate
  1. redisTemplate默认使用的是JDK序列化,但是可以主动设置
  2. redisTemplate执行两条命令其实是在两个连接里完成的,因为redisTemplate执行完一个命令就会对其关闭,但是redisTemplate额外为什么提供了RedisCallback和SessionCallBack两个接口
2. StringRedisTemplate
  1. StringRedisTemplate继承RedisTemplate,只是提供字符串的操作,复杂的Java对象还要自行处理

RedisCallback和SessionCallBack:

  1. 作用: 让RedisTemplate进行回调,通过他们可以在同一条连接中执行多个redis命令
  2. SessionCalback提供了良好的封装,优先使用它,redisCallback太复杂还是不要使用为好
3. 测试SessionCallBack
@Api("redis")
@Controller
@RequestMapping("/redis/*")
public class RedisTestController {

@Autowired
    private RedisTemplate redisTemplate;    

@ApiOperation(value = "testSessionCallback", notes = "testSessionCallback")
    @RequestMapping(value = "/testSessionCallback", method = RequestMethod.GET)
    @ResponseBody
    public void testSessionCallback(
            @RequestParam("key") String value) {
        testSessionCallback(redisTemplate, value);
    }


    public void testSessionCallback(RedisTemplate redisTemplate, String value) {
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations redisOperations) throws DataAccessException {
                redisOperations.opsForValue().set("wanwan", value);
                String myValue = String.valueOf(redisOperations.opsForValue().get("wanwan"));
                System.out.println(myValue);
                return myValue;
            }
        });
    }
}
}
4 . redis相关的同样适用lambda
   @ApiOperation(value = "testSessionCallbackLambda", notes = "testSessionCallbackLambda")
    @RequestMapping(value = "/testSessionCallbackLambda", method = RequestMethod.GET)
    @ResponseBody
    public void testSessionCallbackLambda(
            @RequestParam("key") String value) {
        testSessionCallbackLambda(redisTemplate, value);
    }


    public void testSessionCallbackLambda(RedisTemplate redisTemplate, String value) {
        redisTemplate.execute((RedisOperations redisOperations) -> {
            redisOperations.opsForValue().set("wanwan", value);
            String myValue = String.valueOf(redisOperations.opsForValue().get("wanwan"));
            System.out.println(myValue);
             return myValue;
        });
    }
5.Redis SessionCallback和redis 事务的区别

redis事务时基于SessionCallback实现的,因为要在一个连接里执行命令,那我们看看具体的实现,如下:

     @ApiOperation(value = "multi测试接口", notes = "redis事务测试接口")
    @RequestMapping(value = "/multi", method = RequestMethod.GET)
    @ResponseBody
    public Map<String, Object> testmulti() {
        redisManager.setStr("wanwan", "wd小兔兔");
        List list = (List) redisTemplate.execute((RedisOperations res) ->
        {
            //设置监控key,在exec执行前如果这个key对应的值,发生了变化,事务bu执行
            //通常监控的key可以是ID,也可以是一个对象
            res.watch("wanwan");
            // 其实watch可以注释掉,或者设置成不监控
            res.unwatch();
            //开启事务,在exec执行前
            res.multi();
            res.opsForValue().increment("wanwan", 1);
            res.opsForValue().set("wanwan2", "我的小兔兔1");
            Object value2 = res.opsForValue().get("wanwan2");
            System.out.println("命令在队列,所以取值为空" + value2 + "----");
            res.opsForValue().set("wanwan3", "我的小兔兔3");
            Object value3 = res.opsForValue().get("wanwan3");
            System.out.println("命令在队列,所以取值为空" + value3 + "----");
            return res.exec();
        });
        System.out.println(list);
        Map<String, Object> map = new HashMap<>();
        map.put("success", true);
        System.out.println(";;;" + map.toString());
        return map;
    }

发现其实事务就是基于SessionCallback实现了一个watch如果被监控的键发生了变化就会取消事务,没有变化九执行事务(注意:即使被赋予了相同的值,同样视为发生变化,不予执行事务)

6. redis事务和MySQL事务的区别

可能你会对redis事务的watch有一个疑问?就是watch了几次?如果redis事务中要执行100条命令,那么watch会watch几次?

其实我的理解是:

在执行前一直在watch,但是执行过程中比如开始执行100条命令中的第一条后,
就不会watch了,因为redis时单线程的,你在执行过程中,别的命令根本无法执行
那你会说:如果这个事务要执行10分钟,我这这10分钟内通过手动更改一个键的值可以不,答案是不行
因为redis单线程,

redis的事务类似mysql的串行化隔离界别,执行期间不会乱入其他语句。redis在事务使用乐观锁。redis使用的是乐观锁方式,这种方式允许exec前修改,这时会触发异常通知。

redis通过watch来监测数据,在执行exec前,监测的数据被其他人更改会抛出错误,取消执行。而exec执行时,redis保证不会插入其他人语句来实现隔离。(可以预见到此机制如果事务中包裹过多的执行长指令,可能导致长时间阻塞其他人)

你可能感兴趣的:(redis)