高並發環境下,Redisson實現redis分布式鎖


原文:http://tlzl0526-gmail-com.iteye.com/blog/2378853

 

在一些高並發的場景中,比如秒殺,搶票,搶購這些場景,都存在對核心資源,商品庫存的爭奪,控制不好,庫存數量可能被減少到負數,出現超賣的情況,或者 產生唯一的一個遞增ID,由於web應用部署在多個機器上,簡單的同步加鎖是無法實現的,給數據庫加鎖的話,對於高並發,1000/s的並發,數據庫可能由行鎖變成表鎖,性能下降會厲害。那相對而言,redis的分布式鎖,相對而言,是個很好的選擇,redis官方推薦使用的Redisson就提供了分布式鎖和相關服務。 
下面介紹下如何使用Redisson。 

Xml代碼   收藏代碼
  1. <dependency>  
  2.         <groupId>org.redisson</groupId>  
  3.         <artifactId>redisson</artifactId>  
  4.          <version>2.7.0</version>   
  5.  </dependency>  


使用redisson,最好采用redis 2.6.0以上版本,因為redosson一些后台命令采用eval的命令 

Java代碼   收藏代碼
  1. import org.redisson.Redisson;  
  2. import org.redisson.api.RAtomicLong;  
  3. import org.redisson.config.Config;  
  4.   
  5. public class RedissonManager {  
  6.   
  7.     private static final String RAtomicName = "genId_";  
  8.   
  9.     private static Config config = new Config();  
  10.     private static Redisson redisson = null;  
  11.   
  12.    public static void init(String key,String value){  
  13.         try {  
  14. /*            config.useClusterServers() //這是用的集群server 
  15.                     .setScanInterval(2000) //設置集群狀態掃描時間 
  16.                     .setMasterConnectionPoolSize(10000) //設置連接數 
  17.                     .setSlaveConnectionPoolSize(10000) 
  18.                     .addNodeAddress("127.0.0.1:6379");*/  
  19.             if(key==null || "".equals(key)){  
  20.                 key=RAtomicName;  
  21.             }  
  22.             config.useSingleServer().setAddress("127.0.0.1:6379");  
  23.             redisson = (Redisson) Redisson.create(config);  
  24.             //清空自增的ID數字  
  25.             RAtomicLong atomicLong = redisson.getAtomicLong(key);  
  26.             long pValue=1;  
  27.             if(value!=null && !"".equals(value)){  
  28.                 pValue = Long.parseLong(value);  
  29.             }  
  30.             atomicLong.set(pValue);  
  31.         }catch (Exception e){  
  32.             e.printStackTrace();  
  33.         }  
  34.     }  
  35.   
  36.     public static Redisson getRedisson(){  
  37.         return redisson;  
  38.     }  
  39.   
  40.     /** 獲取redis中的原子ID */  
  41.     public static Long nextID(){  
  42.         RAtomicLong atomicLong = getRedisson().getAtomicLong(RAtomicName);  
  43.        //原子性的獲取下一個ID,遞增1   
  44.        atomicLong.incrementAndGet();  
  45.         return atomicLong.get();  
  46.     }  
  47. }  



加鎖和釋放鎖的方法,設置超時 

Java代碼   收藏代碼
  1. public class DistributedRedisLock {  
  2.     private static Redisson redisson = RedissonManager.getRedisson();  
  3.     private static final String LOCK_TITLE = "redisLock_";  
  4.   
  5.     public static boolean acquire(String lockName){  
  6.         String key = LOCK_TITLE + lockName;  
  7.         RLock mylock = redisson.getLock(key);  
  8.         mylock.lock(2, TimeUnit.MINUTES); //lock提供帶timeout參數,timeout結束強制解鎖,防止死鎖  
  9.         System.err.println("======lock======"+Thread.currentThread().getName());  
  10.         return  true;  
  11.     }  
  12.   
  13.     public static void release(String lockName){  
  14.         String key = LOCK_TITLE + lockName;  
  15.         RLock mylock = redisson.getLock(key);  
  16.         mylock.unlock();  
  17.         System.err.println("======unlock======"+Thread.currentThread().getName());  
  18.     }  
  19. }  



在web端,controller中 

Java代碼   收藏代碼
  1. @RequestMapping("/redder")  
  2. @ResponseBody  
  3. public String redder() throws IOException{  
  4.      String key = "test123";  
  5.        
  6.   DistributedRedisLock.acquire(key);  
  7.           
  8.            
  9.   Long result =  RedissonManager.nextID();    
  10.   
  11.     DistributedRedisLock.release(key);  
  12.     return ""+result;   
  13. }  



程序首先要設置 RedissonManager.init("","");  進行初始化,這樣的目的主要是可以根據實際情況,設置對應的信息,設置遞增的初始值。 

目前用jmeter的測試,1000的並發,確保ID設置為1001

 


免責聲明!

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



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