Spring Data Redis 2: RedisTemplate realizes the analysis and solution of transaction problems Spring Data Redis 2: RedisTemplate realizes transaction problem analysis and solution

Spring Data Redis 2: RedisTemplate implements analysis and resolution of transaction problems

1. Problem description

     Redis is a single-process and single-threaded mode. The queue mode is used to turn concurrent access into serial access. Redis's support for things is not very complicated. When a client connects to the Redis service and issues a MULTI command, the connection will enter the transaction. After the MULTI command is executed, all the commands will not be executed. They will be placed in a queue first, and will be prompted to query. When the EXEC command is finally executed, Redis will execute the commands in the order in which they entered the queue.

      Spring  Data Redis is a good encapsulation of the client side of JRedis. The RedisTemplate of Spring Data Redis provides MULTI and EXEC commands for encapsulation, but RedisTemplate first executes the MULTI method, then executes other commands, and finally executes the EXEC method. An error will appear: Caused by: Redis.clents.jedis.exceptions.JedisDataException:ERR EXEC without MULTI problem .


Second, cause analysis

     Redis is a single-process and single-threaded mode. The queue mode is used to turn concurrent access into serial access. We need to re-add data and delete the original data. In the case of multiple threads, the data will be lost, so we need to complete the corresponding transaction. Effect.

      The RedisTemplate of Spring Data Redis provides MULTI and EXEC commands for encapsulation. When the problem can be solved from a distance, the code implementation:

     

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

       The result guarantees an error:

         

       

            We query the source code of multi, delete, etc., and find that the execute() method in the RedisTemplate class will be executed for tracking. It is found that the RedisConnection obtained by doInRedis in the RedisCallback is new every time, so this problem is caused.

        Analyze the Redis source code:

               We look at the multi implementation

                 
                                
                   Tracking found that RedisConnection conn is new every time, causing that error

3. Solutions

       You can only implement the bottom layer of RedisCallBack by yourself, and use the SesionCallback of RedisTemplate to complete the method of completing multiple operations in the same Connection:

             

[java] view plain copy
  1. SessionCallback<Object>   sessionCallback=new SessionCallback<Object>(){  
  2.   @Override  
  3.    public Object execute(RedisOperations operations) throws DataAccessException{  
  4. operations.multi();  
  5. operations.delete("test");  
  6. operations.opsForValue.set("test","2");  
  7. Object val=operations.exec();  
  8. return val;  
  9. }  
  10. }  
  11. StringRedisTemplate.execute(sessionCallback);  


4. Test results

     

          To simulate multiple thread calls, I used 3 threads for simulation testing:

Thread 3 =================Get key:test value: 1

Thread 2==================Get key:test value: 1

Thread 1==================Get key:test value: 1

Thread 3 =================Get key:test value: 1

Thread 2==================Get key:test value: 1

Thread 3 =================Get key:test value: 1

Thread 1 =================Get key:test value: 2

Thread 2 =================Get key:test value: 2

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325643933&siteId=291194637