zoukankan      html  css  js  c++  java
  • Jedis分布式锁实际应用笔记

    前几日做了一个类似论坛的功能实现,话不多说,上代码

    工具类 JedisUtil

    @Component
    public class JedisUtil {
    
        private static JedisPool jedisPool;
        private static String prefix = "";
        private static String redisHost;
        private static Integer redisPort;
        private static final String LOCK_SUCCESS = "OK";
        private static final Long RELEASE_SUCCESS = 1L;
    
        @Value("${jedisPrefix}")
        public void setJedisClusterPrefix(String jedisClusterPrefix) {
            if (ToolUtil.isNotEmpty(jedisClusterPrefix)) {
                prefix = jedisClusterPrefix + "_";
            }
        }
    
        @Value("${jedisHostList}")
        private void initRedisHostInfo(String hosts) {
            String[] split = hosts.split(":");
            redisHost = split[0];
            redisPort = Convert.toInt(split[1]);
            redisPoolFactory();
        }
    
        /**
         * Jedis初始化
         *
         * @since 2020-02-26
         */
        public static void redisPoolFactory() {
            //连接超时
            //读取数据超时
            Integer timeout = 10000;
            //最大连接数
            Integer maxTotal = 50;
            //连接阻塞时间-1为无限等待
            Long maxWait = -1L;
            //最大空闲连接
            Integer maxIdle = 10;
            //最小空闲连接
            Integer minIdle = 5;
            JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
            jedisPoolConfig.setMaxIdle(maxIdle);
            jedisPoolConfig.setMaxWaitMillis(maxWait);
            jedisPoolConfig.setMaxTotal(maxTotal);
            jedisPoolConfig.setMinIdle(minIdle);
            jedisPool = new JedisPool(jedisPoolConfig, redisHost, redisPort, timeout, pwd);
        }
    
        /**
         * 获取字符串
         *
         * @since 202-02-26
         */
        public static String getString(String key, int... second) {
            Jedis jedis = jedisPool.getResource();
            String res = "";
            key = prefix + key;
            try {
                res = jedis.get(key);
                expireInside(jedis, key, second);
                return res;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            } finally {
                jedis.close();
            }
        }
    
        /**
         * 写入字符串
         *
         * @since 2020-02-26
         */
        public static void setString(String key, String data, int... second) {
            Jedis jedis = jedisPool.getResource();
            try {
                key = prefix + key;
                jedis.set(key, data);
                expireInside(jedis, key, second);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                jedis.close();
            }
        }
    
        /**
         * 设置key的时间
         *
         * @since 2020-02-26
         */
        public static Long expire(String key, Integer second) {
            Jedis jedis = jedisPool.getResource();
            key = prefix + key;
            try {
                return jedis.expire(key, second);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            } finally {
                jedis.close();
            }
        }
    
    
    
        /**
         * Redis分布式锁判定
         *
         * @since 2020-02-26
         */
        public static Object eval(String key, List<String> keys, List<String> args) {
            Jedis jedis = jedisPool.getResource();
            key = prefix + key;
            try {
                return jedis.eval(key, keys, args);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            } finally {
                jedis.close();
            }
        }
    
        /**
         * 延长key的时间
         *
         * @since 2020-02-26
         */
        private static void expireInside(Jedis jedis, String key, int... second) {
            if (ToolUtil.isNotEmpty(key) && second.length > 0) {
                Integer temp = 1800;
                temp = second[0];
                jedis.expire(key, (int) (temp + Math.random() * (temp * 2)));
            }
        }
    
        /**
         * 尝试获取分布式锁
         *
         * @param lockKey    锁
         * @param requestId  请求标识
         * @param expireTime 超期时间
         * @return 是否获取成功
         */
        public static boolean tryGetLock(String lockKey, String requestId, int expireTime) {
            Jedis jedis = jedisPool.getResource();
            try {
                lockKey = prefix + lockKey;
                SetParams setParams = new SetParams();
                String result = jedis.set(lockKey, requestId, setParams.nx().px(expireTime));
                if (LOCK_SUCCESS.equals(result)) {
                    return true;
                }
                return false;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            } finally {
                jedis.close();
            }
        }
    
        /**
         * 释放分布式锁
         *
         * @param lockKey   锁
         * @param requestId 请求标识
         * @return 是否释放成功
         */
        public static boolean releaseLock(String lockKey, String requestId) {
            Jedis jedis = jedisPool.getResource();
            try {
                lockKey = prefix + lockKey;
                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(lockKey), Collections.singletonList
                        (requestId));
                if (RELEASE_SUCCESS.equals(result)) {
                    return true;
                } else {
                    return false;
                }
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            } finally {
                jedis.close();
            }
        }
    }

    实际代码调用

            //uuid
            String requestId = UuidUtils.getUUID();
            //分布式锁
            String topicLock = "topicLock_" + topicId;
            boolean flag = true;
            if (条件) {
                //循环获取锁  次数自己定义
                for (int i = 0; i < 3; i++) {
                    //传入参数   key  uuid   存活时间
                    boolean keySuccess = JedisUtil.tryGetLock(topicLock, requestId, 10);
                    //如果获取到锁
                    if (keySuccess) {
                        //进行逻辑操作
                          xxxzzzzxxxxx
                        //释放锁  或者超过10秒自己释放
                        JedisUtil.releaseLock(topicLock, requestId);
                        break;
                    }
                    Thread.sleep(300L);
                }
            }

    这是在jedis基础上自己封装的分布式锁,跟redistemplate分布式锁一样存在集群中锁异常关闭导致重复获取锁的问题,简单业务可以应用,如果业务庞大且服务器不稳定,建议选择zk做分布式锁

  • 相关阅读:
    js-link下载文件
    sql-优化建议
    Studio-环境变量设置
    Studio
    Docker下安装ElasticSearch和Kibana
    sklearn 中的 r2_score
    R语言将所有列数据正交化/缩放
    R语言 random forests out-of-bag prediction
    R语言 coalesce 函数
    R语言 case_when 函数
  • 原文地址:https://www.cnblogs.com/innocenter/p/13503392.html
Copyright © 2011-2022 走看看