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、服务器宕机;

  • 相关阅读:
    requirejs按需加载angularjs文件
    Ricky_Huang的博客园网址二维码
    bootstrap双日历插件实例化
    angularjs ocLazyLoad分步加载js文件,angularjs ocLazyLoad按需加载js
    利用html5 canvas实现纯前端上传图片的裁剪
    <input type="file"> change事件异常处理办法
    react-native-http请求后navigator导航跳转
    js 将long型字符串转换成日期格式
    百度ueditor 实例化 Cannot set property 'innerHTML' of null 完美解决方案
    IDEA 创建Maven Web项目(图文版)
  • 原文地址:https://www.cnblogs.com/gendway/p/10497922.html
Copyright © 2011-2022 走看看