Jedis常用封装及Lua脚本实现setnx原子操作

代码如下:


/**
 * redis相关的操作助手
 */
@SuppressWarnings("SpellCheckingInspection")
public class RedisHelper {
    private static CommonLog log = CommonLog.getInstance(LoggerFactory.getLogger(RedisHelper.class));
    /**
     * SetNx luava脚本原子命令,Redis分布式锁setnx后setexpire因某种问题导致没执行,导致锁一直被占的问题
     */
    public final static String SET_NX_SCRIPT = "" +
            "local rs=redis.call('setnx',KEYS[1],ARGV[1]);" +
            "if(rs<1) then return 'F';end;" +
            "redis.call('expire',KEYS[1],tonumber(ARGV[2]));" +
            "return 'S';";

    private static JedisPool jedisPool = null;

    static {
        try {
            // 数据库链接池配置
            JedisPoolConfig config = new JedisPoolConfig();
            //最大连接数, 应用自己评估,不要超过Redis每个实例最大的连接数 10000
            config.setMaxTotal(9000);
            //最大空闲连接数, 应用自己评估,不要超过Redis每个实例最大的连接数
            config.setMaxIdle(50);
            //最小能够保持Idle状态的对象数
            config.setMinIdle(20);
            //当池内没有返回对象时,最大等待时间
            config.setMaxWaitMillis(6 * 1000);
            config.setTestOnBorrow(false);
            config.setTestOnReturn(false);
            String path = PathConstant.CONFIG_PATH + "redis-anxuan.properties";
            PropertiesHelper helper = new PropertiesHelper(path);
            jedisPool = new JedisPool(config, helper.getString("host"), helper.getInt("port"), 3000, helper.getString("password"));
        } catch (Exception e) {
            log.error("", "JedisPool startup error", "JedisPool初始化异常:{}", e.getMessage(), e);
        }
    }

    public static Jedis getJedis() {
        if (jedisPool != null) {
            return jedisPool.getResource();
        }
        throw new IllegalStateException("JedisPool has not successfully initialized!");
    }

    public static void set(String key, String value) {
        Jedis jedis = getJedis();
        try {
            if (StringUtils.isNotBlank(key)) {
                jedis.set(key, value);
            }
        } catch (Exception e) {
            log.error("", "RedisHelper-set-exception", "异常:{}", e.getMessage(), e);
        } finally {
            releaseResource(jedis);
        }
    }

    /**
     * 写入值
     *
     * @param key        key
     * @param value      value
     * @param ttlSeconds 过期时长(秒)
     */
    public static void setex(String key, String value, int ttlSeconds) {
        Jedis jedis = getJedis();
        try {
            if (StringUtils.isNotBlank(key)) {
                jedis.setex(key, ttlSeconds, value);
            }
        } catch (Exception e) {
            log.error("", "RedisHelper-setex-exception", "异常:{}", e.getMessage(), e);
        } finally {
            releaseResource(jedis);
        }
    }

    public static String get(String key) {
        Jedis jedis = getJedis();
        try {
            if (StringUtils.isNotBlank(key) && jedis.exists(key)) {
                return jedis.get(key);
            }
        } catch (Exception e) {
            log.error("", "RedisHelper-get-exception", "异常:{}", e.getMessage(), e);
        } finally {
            releaseResource(jedis);
        }
        return null;
    }

    /**
     * 判断Key是否存在
     *
     * @return boolean
     */
    public static boolean exists(String key) {
        Jedis jedis = getJedis();
        try {
            if (StringUtils.isNotBlank(key)) {
                return jedis.exists(key);
            }
        } catch (Exception e) {
            log.error("", "RedisHelper-exists-exception", "异常:{}", e.getMessage(), e);
        } finally {
            releaseResource(jedis);
        }
        return false;
    }

    /**
     * 释放Jedis连接
     *
     * @param jedis jedis
     */
    public static void releaseResource(Jedis jedis) {
        try {
            if (jedis != null && jedis.isConnected()) {
                jedis.close();
            }
        } catch (Exception e) {
            log.error("", "RedisHelper-releaseResource-exception", "异常:{}", e.getMessage(), e);
        }
    }

    /**
     * 定时任务分布式锁(通过luava脚本实现)
     *
     * @param lockKey    分布式锁的Key
     * @param ttlSeconds 过期时长(单位:秒)
     */
    public static boolean tryTimingTaskLock(String lockKey, int ttlSeconds) {
        if (ttlSeconds <= 0) {
            throw new IllegalArgumentException("定时任务分布式锁的过期时长[ttlSeconds]必须为正整数!");
        }
        Jedis jedis = getJedis();
        try {
            Object result = jedis.eval(SET_NX_SCRIPT, Collections.singletonList(lockKey), Arrays.asList("1", String.valueOf(ttlSeconds)));
            return "S".equals(result);
            // 已存在返回0;不存在写入成功返回1(这种写法,有的情况下会出现问题,jedis.expire操作失败,导致锁一直被占用);
           /* if (jedis != null && jedis.setnx(lockKey, "1") == 1) {
                jedis.expire(lockKey, ttlSeconds);
                return true;
            }*/
        } catch (Exception e) {
            log.error("RedisHelper-tryLock-exception:{}", e.getMessage(), e);
        } finally {
            releaseResource(jedis);
        }
        return false;
    }
}

参考文章:https://blog.csdn.net/cts529269539/article/details/82901314

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值