zoukankan      html  css  js  c++  java
  • RedisTemplate实现事物问题剖析和解决[转]

    一、问题描述

         Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,Redis对事物支持不会很复杂,当一个客服端连接Redis服务时,发出了MULTI命令时,这个连接会进入事物,在执行MULTI命令之后,执行所有的命令都不会执行,会先放到一个队列中,会提示正在Query,当最后执行EXEC命令之后,Redis会按照之前的进入队列的顺序,执行命令。

          Spring Data Redis 是对JRedis的客服端进行很好的封装, spring Data Redis的RedisTemplate提供了MULTI、EXEC命令进行封装,但RedisTemplate先执行调用MULTI方法,然后在执行其它的命令,最后执行EXEC方法时,会出现报错:Caused by:Redis.clents.jedis.exceptions.JedisDataException:ERR EXEC without MULTI问题。

    二、原因分析

         Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,我们需要重新添加数据,对原先的数据进行删除,在多个线程情况下数据会丢失,所以我们需要事务完成相应的效果。

          Spring Data Redis的RedisTemplate提供了MULTI、EXEC命令进行封装,远看可以解决问题时,代码实现:

         

    [java] view plain copy
     
    1. stringRedisTemplate.multi();  
    2. stringRedisTemplate.delete("test");  
    3. stringRedisTemplate.opsForValue().set("test","2");  
    4. stringRedisTemplate.exec();  

           结果保 错误:

             

           

                我们查询multi、delete等源代码,发现会执行RedisTemplate类中execute()方法进行跟踪发现 RedisCallback中doInRedis获取的RedisConnection每次都是新的,所以才导致该问题。

            分析Redis源代码:

                   我们查看multi实现

                     
                                    
                        跟踪发现RedisConnection conn每次都是新的,导致出现那个错误

    三、解决方案

           只能自己实现RedisCallBack底层,采用RedisTemplate的SesionCallback来完成在同一个Connection中,完成多个操作的方法:

      

    SessionCallback<Object>   sessionCallback=new SessionCallback<Object>(){  
      @Override  
       public Object execute(RedisOperations operations) throws DataAccessException{  
    operations.multi();  
    operations.delete("test");  
    operations.opsForValue.set("test","2");  
    Object val=operations.exec();  
    return val;  
    }  
    }  
    StringRedisTemplate.execute(sessionCallback);
  • 相关阅读:
    tomcat的安装以及环境配置
    MySQL日期/时间函数
    docker部署tomcat
    Lambda的高级查询
    Linq的使用
    多线程编程
    反射
    匿名类型
    委托和事件
    泛型特性
  • 原文地址:https://www.cnblogs.com/zjITgrow/p/8241785.html
Copyright © 2011-2022 走看看