• redis实现分布式锁


    清理邮件的时候发现之前看的一篇关于redis分布式锁实现的文章有人回复- -当时随意扫了眼文章,为了防止发生死锁,思路是使用setnx设置value为本地时间,然后获取锁失败时读取value进行时间比对。。然后我回复了下。。多台应用服务器存在时间不同步的问题。。

    其实使用setnx时设置下redis过期时间简单方便,只是通常在应用程序内通过sdk做这项操作时由于赋值+设置过期不在同一原子性操作中。。所以很多人觉得不可行了。。那就直接使用lua脚本呗,简单方便,原子性操作,性能也OK。

    加锁:aquire_lock_with_timeout.lua

    if redis.call("exists",KEYS[1]) == 0 then
        local lockSrc = redis.call("setex",KEYS[1],unpack(ARGV))
        if lockSrc then
            return "1"
        end
            return "0"
    end
    return "-1"

    释放锁:release_lock.lua

    if redis.call("get",KEYS[1]) == ARGV[1] then
        local lockRelease = redis.call("del",KEYS[1])
            if lockRelease then
                return "1"
            end
                return "0"
    end
    return "-1"

    java为例,加载两个lua脚本,然后简单加锁,释放锁

      @Bean
        @Qualifier("lockScript")
        public RedisScript<Integer> acquireLockWithTimeout() {
            DefaultRedisScript redisScript = new DefaultRedisScript();
            redisScript.setLocation(new ClassPathResource("redis/acquire_lock_with_timeout.lua"));
            redisScript.setResultType(Integer.class);
            return redisScript;
        }
    
    
        @Bean
        @Qualifier("unLockScript")
        public RedisScript<Integer> releaseLock() {
            DefaultRedisScript redisScript = new DefaultRedisScript();
            redisScript.setLocation(new ClassPathResource("redis/release_lock.lua"));
            redisScript.setResultType(Integer.class);
            return redisScript;
        }
        private Integer acquireTimeout;//资源占有锁的时间 秒s
        private Integer acquireInterval;//尝试获取锁的时限 ms
        private Integer lockTime;//尝试获取锁的时间间隔 ms
        
        @Autowired
        private RedisTemplate redisTemplate;
        @Autowired
        @Qualifier("lockScript")
        private RedisScript<Integer> acquireLockWithTimeout;
        @Autowired
        @Qualifier("unLockScript")
        private RedisScript<Integer> releaseLock;
    
         
        public String tryLock(String lockKey) {
            String lockValue = UUID.randomUUID().toString();
            Long endTime = System.currentTimeMillis() + acquireTimeout;
            while (System.currentTimeMillis() < endTime) {
                Integer lockResult = (Integer) redisTemplate.execute(acquireLockWithTimeout, Collections.singletonList(lockKey), lockTime, lockValue);
                if (lockResult.equals(1)) {
                    return lockValue;
                } else {
                    try {
                        Thread.sleep(acquireInterval);
                    } catch (InterruptedException ex) {
                        continue;
                    }
                }
            }
            return "";
        }
     
        public boolean releaseLock(String lockKey, String lockValue) {
            Integer releaseResult = (Integer) redisTemplate.execute(releaseLock, Collections.singletonList(lockKey), lockValue);
            if (releaseResult.equals(1)) {
                return true;
            }
            return false;
        }

    当然java也有更复杂更丰富的组件 redisson

  • 相关阅读:
    Vue(三十三)国际化解决方案
    Vue(三十二)SSR服务端渲染Nuxt.js
    字符串与数组常用的属性和方法
    Vue(三十一)轮播组件
    Vue(三十)公共组件
    Vue(二十九)页面加载过慢问题
    Vue(二十八)el-cascader 动态加载
    Vue(二十七)当前GitHub上排名前十的热门Vue项目(转载)
    React(九)create-react-app创建项目 + 按需加载Ant Design
    React(八)样式及CSS模块化
  • 原文地址:https://www.cnblogs.com/ylsforever/p/8462716.html
Copyright © 2020-2023  润新知