zoukankan      html  css  js  c++  java
  • 高并发环境下,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

  • 相关阅读:
    echarts的整理
    socket.io做一个简单的聊天案例
    WebSocket通信随笔
    接口返回的二维码图片,如何处理显示(axios处理后台返回图片流格式数据)
    小程序封装request请求
    一站式解决Vue插件开发,上传Github,Npm包发布
    微信公众号链接处理问题
    git常用命令
    vscode 常用配置
    项目中报错Cannot read property 'getAttribute' of undefined解决
  • 原文地址:https://www.cnblogs.com/shihaiming/p/8535205.html
Copyright © 2011-2022 走看看