基于redis实现分布式锁

背景

一套代码部署在四个服务器上,代码逻辑是:检查当前表的总数据条数,满足一定条件后切换到下一个分表

四个同时都去切换表 + 1 的操作是不可以的,他们要先从 redis 获取一把锁,没有获取到锁的就直接退出,等待下一次定时任务的调度。拿到了锁的就去执行切换当前分表的操作

实现

获取锁 和 释放锁 的关键代码如下所示:

/**
     * Set the string value as value of the key. The string can't be longer than 1073741824 bytes (1
     * GB).
     * @param key
     * @param value
     * @param nxxx NX|XX, NX -- Only set the key if it does not already exist. XX -- Only set the key
     *          if it already exist.
     * @param expx EX|PX, expire time units: EX = seconds; PX = milliseconds
     * @param time expire time in the units of <code>expx</code>
     * @return Status code reply
     * @auther daleyzou
     */
    public boolean set(String key, String value, String nxxx, String expx,
            long time) {
        Jedis jedis = jedisPool.getResource();
        try {
            String result = jedis.set(key, value, nxxx, expx, time);
            if (!StringUtils.isNullOrEmpty(result) && "OK".equals(result)){
                return true;
            }else {
                return false;
            }
        } catch (Exception e) {
            dealWithJedisException(e);
        } finally {
            closeJedis(jedis);
        }
        return false;
    }

    /***
     * @Description: 解锁时比较值是否相等
     * @date: 22:33 2019/7/22
     * @param: key
     * @param: request value
     * @return: boolean
     */
    public  boolean unlock(String key,String request){
        Jedis jedis = jedisPool.getResource();
        try {
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            Object result = jedis.eval(script, Collections.singletonList(key), Collections.singletonList(request));

            Long UNLOCK_SUCCESS = 1L;
            if (UNLOCK_SUCCESS.equals(result)){
                return true;
            }else {
                return false;
            }
        } catch (Exception e) {
            dealWithJedisException(e);
        } finally {
            closeJedis(jedis);
        }
        return false;
    }

调用

private static final String SET_IF_NOT_EXIST = "NX";
private static final String SET_WITH_EXPIRE_TIME = "EX";

if (myJedisService.set(refreshMaxId, value, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime)){
    // 执行并发的相关操作
    。。。
    myJedisService.unlock(refreshMaxId, value);
    return;
}else {
    return;
}

参考

参考链接:https://crossoverjie.top/2018/03/29/distributed-lock/distributed-lock-redis/

posted @ 2019-11-19 21:28  DaleyZou  阅读(174)  评论(0编辑  收藏  举报