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中,完成多個操作的方法:

  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); 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM