zoukankan      html  css  js  c++  java
  • 基于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/

  • 相关阅读:
    js定时跳转
    MySQL跨表更新字段 工作记录
    windows下安装phpcms html/ 文件夹不可写的一种错误以及解决方法
    linux清理僵尸进程
    JQuery实现隔行变色和突出显示当前行 效果
    windows下配置lamp环境(4)---安装MySQL数据库5.6
    windows下配置lamp环境(5)---配置MySQL5.6
    windows下配置lamp环境(3)---配置PHP5.4
    windows下配置lamp环境(0)---软件获取
    windows下配置lamp环境(2)---配置Apache服务器2.2.25
  • 原文地址:https://www.cnblogs.com/daleyzou/p/concurrentLock.html
Copyright © 2011-2022 走看看