美文网首页
Redis分布式锁 基于redis.eval

Redis分布式锁 基于redis.eval

作者: label_916 | 来源:发表于2017-12-05 13:44 被阅读0次

    实现方法:使用redis的eval执行lua脚本

    EVAL script numkeys key [key ...] arg [arg ...]
    
    从 Redis 2.6.0 版本开始,通过内置的 Lua 解释器,可以使用 EVAL 命令对 Lua 脚本进行求值。
    

    Java代码

    package com.label.practice;
    
    import com.google.common.collect.Lists;
    import lombok.extern.log4j.Log4j2;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    
    import java.util.List;
    
    /**
     * Redis分布式锁
     *
     * @author libiao
     * @since 2017-12-05
     */
    @Log4j2
    public class RedisClient {
        private JedisPool jedisPool = null;
    
        public long del(String... keys) {
            try (Jedis jedis = jedisPool.getResource()) {
                return jedis.del(keys);
            }
        }
    
        public boolean set(String key, String value) {
            try (Jedis jedis = jedisPool.getResource()) {
                return StringUtils.equals(jedis.set(key, value), Constant.SET_SUCCESS);
            }
        }
    
        public boolean setNxEx(String key, String value, int seconds) {
            try (Jedis jedis = jedisPool.getResource()) {
                return StringUtils.equals(jedis.set(key, value, Constant.SET_IF_NOT_EXISTS, Constant.SET_WITH_EXPIRES, seconds), Constant.SET_SUCCESS);
            }
        }
    
        public String get(String key) {
            try (Jedis jedis = jedisPool.getResource()) {
                return jedis.get(key);
            }
        }
    
        public Object eval(String script, List<String> keyList, List<String> valueList) {
            try (Jedis jedis = jedisPool.getResource()) {
                return jedis.eval(script, keyList, valueList);
            }
    
        }
    
        public RedisLock getRedisLock() {
            return new RedisLock();
        }
    
        public class RedisLock {
            private static final String lockScript = "if (redis.call('exists',KEYS[1]) == 0 or redis.call('get',KEYS[1]) == ARGV[2]) then return redis.call('setex',KEYS[1],ARGV[1],ARGV[2]) else return -1 end";
            public static final String unlockScript = "if (redis.call('exists',KEYS[1]) == 0 or redis.call('get',KEYS[1]) == ARGV[1]) then return redis.call('del',KEYS[1]) else return -1 end";
    
            public boolean tryLock(String key, String requestId, int seconds) {
                try (Jedis jedis = jedisPool.getResource()) {
                    Object eval = jedis.eval(lockScript, Lists.newArrayList(key), Lists.newArrayList(String.valueOf(seconds), requestId));
                    log.info(eval);
                    if (null != eval && StringUtils.equals(Constant.SET_SUCCESS, String.valueOf(eval))) {
                        return true;
                    }
                }
                return false;
            }
    
            public boolean unLock(String key, String requestId) {
                try (Jedis jedis = jedisPool.getResource()) {
    
                    Object eval = jedis.eval(unlockScript, Lists.newArrayList(key), Lists.newArrayList(requestId));
                    log.info(eval);
                    if (null == eval) {
                        return false;
                    }
                    int affectedRows = Integer.parseInt(String.valueOf(eval));
                    if (1 == affectedRows || 0 == affectedRows) {
                        return true;
                    }
                }
                return false;
            }
        }
    
        public class Constant {
            public static final String SET_SUCCESS = "OK";
            public static final String SET_IF_NOT_EXISTS = "NX";
            public static final String SET_WITH_EXPIRES = "EX";
        }
    
        public static RedisClient getInstance() {
            return RedisClientPlaceHolder.redisClient;
        }
    
        private RedisClient() {
            GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
            poolConfig.setMaxIdle(10);
            poolConfig.setMaxTotal(50);
            poolConfig.setLifo(false);
            poolConfig.setTestOnBorrow(true);
            poolConfig.setTestWhileIdle(true);
            poolConfig.setMaxWaitMillis(5000);
    
    
            jedisPool = new JedisPool(poolConfig, "w10979.sit.wdds.redis.com", 10979);
        }
    
        private static class RedisClientPlaceHolder {
            private static RedisClient redisClient = new RedisClient();
        }
    }
    
    

    相关文章

      网友评论

          本文标题:Redis分布式锁 基于redis.eval

          本文链接:https://www.haomeiwen.com/subject/jpxcixtx.html