首页 > 数据库 >redis一些关于SessionCallback和事务要注意的地方

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

时间:2022-10-04 16:23:17浏览次数:79  
标签:SessionCallback redis watch 事务 value res redisTemplate

 

文章目录

 

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保证不会插入其他人语句来实现隔离。(可以预见到此机制如果事务中包裹过多的执行长指令,可能导致长时间阻塞其他人)

 

标签:SessionCallback,redis,watch,事务,value,res,redisTemplate
From: https://www.cnblogs.com/Jonkidi/p/16753946.html

相关文章

  • Spring事务(二)-事务传播行为
    在Spring里,一个事务方法被另外一个事务方法调用时,两个方法的事务应该如何进行,说白话一点,就是说当出现异常需要回滚时,各个方法的数据操作是否要全部回滚,事务传播行为就......
  • Spring事务(四)-事务隔离级别
    Spring @Transactional注解isolation属性@Transactional注解通过isolation属性设置事务隔离级别。如下:@Transactional(isolation=Isolation.DEFAULT)publicvoid......
  • Spring事务(一)-事务配置
      事务是数据库操作最基本的单元,是逻辑上的一组操作,这一组操作在同一个会话中要么都执行成功,要么都失败,这也是事务的最基本特性--原子性。事务的作用是为了保证系统数据......
  • Redis核心设计原理(深入底层C源码)
    Redis基本特性1.非关系型的键值对数据库,可以根据键以O(1)的时间复杂度取出或插入关联值2.Redis的数据是存在内存中的3.键值对中键的类型可以是字符串,整......
  • 003-Redis 中的 BitMaps
    1.BitMap1.1bitcount1.1.1基本信息BITCOUNTkey[startend]summary:Countsetbitsinastringsince:2.6.0Countthenumberofsetbits(populationcounti......
  • Redis学习目录
     目录持续更新...​​Redis简介​​​​Redis安装及基本配置​​​​Redis持久化​​​​Redis开发及管理实战​​​​Redis高可用及集群​​​​Redis多API开发​​ ......
  • Docker 启动 Redis 就停止解决方案(2022-3)
    启动命令如下:dockerrun-itd\-p6379:6379\--namemyredis\-v/home/redis/redis.conf:/etc/redis/redis.conf\-v/home/redis/data:/data\redis:latest\re......
  • 002-Redis的 String 使用
    Redis命令十分丰富,包括的命令组有Cluster、Connection、Geo、Hashes、HyperLogLog、Keys、Lists、Pub/Sub、Scripting、Server、Sets、SortedSets、Strings、Transactions......
  • redis 允许远程访问
    1.取消绑定本地地址找到redis配置文件,redis.conf,注释掉指定的bind,当不指定时表示允许所有访问。   2.关闭保护模式在redis服务器上使用redis-cli,执行命令C......
  • Redis高性能怎么做到的?
    Redis的高性能怎么做到的?Redis这个NOSQL数据库在计算机界可谓是无人不知,无人不晓。只要涉及到数据那么就需要数据库,数据库类型很多,但是NOSQL的kv内存数据库也很多,redis作为......