Redis实现分布式锁3-使用LUA脚本实现分布式锁,解决原子性问题

    private static final Long SUCCESS = 1L;
    private static String script1 = "if redis.call('setNx',KEYS[1],ARGV[1])  then " +
            "   if redis.call('get',KEYS[1])==ARGV[1] then " +
            "      return redis.call('expire',KEYS[1],ARGV[2]) " +
            "   else " +
            "      return 0 " +
            "   end " +
            "end";
    private RedisScript<String> lockRedisScript1 = new DefaultRedisScript<>(script1, String.class);
    private static String script2 = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
    private RedisScript<String> unLockRedisScript = new DefaultRedisScript<>(script2, String.class);
    /**
     * 获取锁
     *
     * @param lockKey       redis的key
     * @param value         redis的value要求是随机串,防止释放其他请求的锁
     * @param expireTime    redis的key 的过期时间  单位(秒) 防止死锁,导致其他请求无法正常执行业务
     * @return
     */
    @Override
    public  boolean lock(String lockKey, String value, long expireTime) {
        //对非string类型的序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        Object result = redisTemplate.execute(lockRedisScript1, Collections.singletonList(lockKey), value, String.valueOf(expireTime));

        return SUCCESS.equals(result);

    }

    /**
     * 释放锁
     *
     * @param lockKey   redis的key
     * @param value     redis的value  只有value比对一致,才能确定是本请求 加的锁 才能正常释放
     * @return
     */
    @Override
    public  boolean unlock(String lockKey, String value) {
        try {
            Object result = redisTemplate.execute(unLockRedisScript, Collections.singletonList(lockKey), value);
            if (SUCCESS.equals(result)) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

  

posted @ 2020-03-21 13:51  陈小兵  阅读(891)  评论(0编辑  收藏  举报