zoukankan      html  css  js  c++  java
  • redis分布式锁的具体应用

    1、关于redis分布式锁,有个setIfAbsent:

    即如果没有设置,会添加分布式锁,并返回true;

    2、redis分布式锁有个轮询过程:

     /
    
    * @param key redis键
    * @param expire 键过期时间(单位:毫秒)
    * @param timeout 超时时间(单位: 毫秒)
     * @return true表示加锁成功,false表示加锁失败
     */
    public boolean lock(String key, long expire, long timeout) {
    
        timeout *= 1000*1000; //一般用常量表示,进行毫秒与纳秒之间的转换
        long nanoTime = System.nanoTime();
    
        try {
    
            //在timeout的时间范围内不断轮询锁
            while (System.nanoTime() - nanoTime < timeout) {
    
                //锁不存在的话,设置锁并设置锁过期时间,即加锁
                Boolean isSuccess = redisTemplate.opsForValue().setIfAbsent(key, RedisLock.LOCKED);
                if (isSuccess) {
                    //设置锁过期时间是为了在没有释放锁的情况下锁过期后消失,不会造成永久阻塞
                    redisTemplate.expire(key, expire, TimeUnit.MILLISECONDS);
                    this.lock = true;
                    return true;
                }
    
                //短暂休眠,避免可能的活锁
                Thread.sleep(3, RANDOM.nextInt(30));
            }
        } catch (Exception e) {
            throw new RuntimeException("locking error",e);
        }
    
        return false;
    
    }
    

     3、设置分布式锁,一般而言,分布式锁只做判断,具体我们还要使用redis进行一个设置key的过程,这样也类似于另一把锁:

      为什么要使用另一把锁呢?其实分布式锁只是为了解决几个程序间同时操作的问题,它的时间非常不好控制,当我们有了另一把锁就可以轻易地去控制锁的时间,

                lockkey = RedisKeyConstants.LOCK_PREFIX + ":" + redisKey;
                redisLock.lock(lockkey, RedisKeyConstants.LOCK_ROUTE_GEN_EXPIRE_TIME, RedisKeyConstants.LOCK_ROUTE_GEN_TIMEOUT_TIME);
    
                //判断redis中是否有数据
                String redisValue = redisTemplate.opsForValue().get(redisKey);
                if (redisValue != null) {
                    return;
                }
                redisTemplate.opsForValue().set(redisKey, "1", RedisKeyConstants.ROUTE_TYPE_GEN_EXPIRE_TIME, TimeUnit.SECONDS);
    

     4、程序结束后一定要在finally代码块中释放锁,这样就好了; 

    finally {
                redisTemplate.delete(redisKey);
                redisLock.unlock(lockkey);
            }
    

     5、防止程序出现bug,所以我们设置另一把锁的失效时间为半个小时;

    需要考虑的问题:

    1、多台服务器的时间有误差;

    2、人工触发;

    3、服务器宕机;

  • 相关阅读:
    Leetcode题目322.零钱兑换(动态规划-中等)
    Leetcode题目292.Nim游戏(脑筋急转弯)
    Leetcode题目300.最长上升子序列(动态规划-中等)
    Leetcode题目287.寻找重复数(中等)
    Android学习笔记---初识eventbus
    Android学习笔记----实现卡牌翻转动画
    Android学习笔记----在Android使用ping来检测网络是否可用
    Android学习笔记----初体验ButterKnife框架
    Android 学习笔记---使用shell命令来关闭和开启ADB
    Android学习笔记--客户端上传图片到PHP服务器(带PHP端代码)
  • 原文地址:https://www.cnblogs.com/gendway/p/10497922.html
Copyright © 2011-2022 走看看