Redis分布式锁 基于redis.eval

2017-12-05  本文已影响0人  label_916

实现方法:使用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();
    }
}

上一篇 下一篇

猜你喜欢

热点阅读