IT源码网

基于redis实现分布式锁

flyfish 2021年02月13日 编程语言 396 0

背景

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

四个同时都去切换表 + 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/

评论关闭
IT源码网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

一些有用的链接