zoukankan      html  css  js  c++  java
  • Redis分布式缓存&分布式锁

    1.背景

             由于业务需求最近准备将系统中原有的memcached改造为Redis,实现多数据类型的分布式缓存。

    2.分布式缓存:

      

    3.集成改造

    1)       Pom依赖 vcsp-genericProfessionServerpom.xml

    <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-pool2</artifactId>
       <version>2.4.2</version>
    </dependency>
    <dependency>
       <groupId>org.springframework.data</groupId>
       <artifactId>spring-data-redis</artifactId>
       <version>1.7.10.RELEASE</version>
    </dependency>
    <dependency>
       <groupId>redis.clients</groupId>
       <artifactId>jedis</artifactId>
       <version>2.8.1</version>
    </dependency>
    View Code

    2)       application-*.properties

    #redis配置*********************
    spring.redis.hostName=192.168.1.123
    spring.redis.port=6739
    # REDIS (RedisProperties)
    # Redis数据库索引(默认为0)
    spring.redis.database=0
    # Redis服务器连接密码(默认为空)
    spring.redis.password=2123
    # 连接池最大连接数(使用负值表示没有限制)
    # 连接超时时间(毫秒)
    spring.redis.timeout=5000
    spring.redis.pool.max-active= 3000
    # 连接池最大阻塞等待时间(使用负值表示没有限制)
    spring.redis.pool.max-wait=5000
    # 连接池中的最大空闲连接
    spring.redis.pool.max-idle=1000
    # 连接池中的最小空闲连接
    spring.redis.pool.min-idle=200
    spring.session.store-type=none
    #redis配置*********************
    View Code

    3)       RedisConfiguration 

    @Configuration
    public class RedisConfiguration{
        @Value("${spring.redis.hostName}")
        private String host;
    
        @Value("${spring.redis.port}")
        private int port;
    
        @Value("${spring.redis.timeout}")
        private int timeout;
    
        @Value("${spring.redis.pool.max-idle}")
        private int maxIdle;
    
        @Value("${spring.redis.pool.max-wait}")
        private long maxWaitMillis;
    
        @Value("${spring.redis.pool.max-active}")
        private int maxActive;
    
        @Value("${spring.redis.password}")
        private String password;
    。。。。。。。。
    View Code

    4)       MyRedisPool

    @Component
    public class MyRedisPool {
    
        private static final Logger LOGGER = Logger.getLogger(MyRedisPool.class);
    
        private static String host;
    
        private static int port;
    
        private static int timeout;
    
        private static int maxIdle;
    
        private static long maxWaitMillis;
    
        private static int maxActive;
    
        private static String password;
    
        @Autowired
        RedisConfiguration redisConfiguration;
    
        //@PostConstruct
        public void iniProperties(){
            sm4ScretKey= sm4ScretKeyUtils.getSm4ScretKey(redisConfiguration.getFileServerIntranetHost());
            host=redisConfiguration.getHost();
            port=redisConfiguration.getPort();
            timeout=redisConfiguration.getTimeout();
            maxIdle=redisConfiguration.getMaxIdle();
            maxWaitMillis=redisConfiguration.getMaxWaitMillis();
            maxActive=redisConfiguration.getMaxActive();
            password=redisConfiguration.getPassword();
    
            if(jedisPool==null){
                initJedisPool();
            }
            LOGGER.warn("初始化 jedisPool................");
        }
    
        private static JedisPool jedisPool = null;
    
        public static void initJedisPool(){
            try{
                JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
                jedisPoolConfig.setMaxIdle(maxIdle);//最大空闲连接数
                jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);//最大等待时间
                jedisPoolConfig.setMaxTotal(maxActive);//最大活动线程数
                LOGGER.error("初始化redis线程池工厂....................host:"+host+";port:"+port+";password:"+password+";maxActive:"+maxActive);
                jedisPool = new JedisPool(jedisPoolConfig,host,port,timeout,password);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        /**
         * 获取Jedis实例
         *
         * @return
         */
        public synchronized static Jedis getJedis() {
            try {
                if(jedisPool==null){
                    initJedisPool();
                }
                return jedisPool.getResource();
            } catch (Exception e) {
                jedisPool.close();
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 释放jedis资源
         *
         * @param jedis
         */
        public static void returnResource(final Jedis jedis) {
            if (jedis != null) {
                jedisPool.returnResourceObject(jedis);
            }
        }
    
        /**
         * 销毁jedis连接
         *
         * @param jedis
         */
        public static void returnBrokenResource(final Jedis jedis) {
            if (jedis != null) {
                jedisPool.returnBrokenResource(jedis);
            }
        }
    }
    View Code

    5)       RedisClient

    /**
     * @author
     */
    public class RedisClient {
    
        private volatile static RedisClient instance;
        private static final Logger LOGGER = Logger.getLogger(RedisClient.class);
    
        private RedisClient() {
        }
    
        public static RedisClient getInstance() {
            if (instance == null) {
                synchronized (RedisClient.class) {
                    if (instance == null) {
                        instance = new RedisClient();
                    }
                }
            }
            return instance;
        }
    
        /**
         * 自定义设置key
         *
         * @param key      键
         * @param value    值
         * @param exits    NX/XX 值只能取NX或者XX,如果取NX,则只有当key不存在是才进行set,如果取XX,则只有当key已经存在时才进行set
         * @param expx     EX/PX   值只能取EX或者PX,代表数据过期时间的单位,EX代表秒,PX代表毫秒
         * @param interval 过期时间,单位是expx所代表的单位。
         * @return SET 在设置操作成功完成时,才返回 OK 。
         * 如果设置了 NX 或者 XX ,但因为条件没达到而造成设置操作未执行,那么命令返回空批量回复(NULL Bulk Reply)
         */
        public String set(String key, Object value, String exits, String expx, long interval) {
            Jedis jedis = MyRedisPool.getJedis();
            String result = "";
            try {
                result = jedis.set(key, String.valueOf(value), exits, expx, interval);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 设置key
         * 需要传入key是否已经存在
         *
         * @param key      键
         * @param value    值
         * @param expx     EX/PX   值只能取EX或者PX,代表数据过期时间的单位,EX代表秒,PX代表毫秒
         * @param interval 过期时间,单位是expx所代表的单位。
         * @return SET 在设置操作成功完成时,才返回 OK 。
         * 如果设置了 NX 或者 XX ,但因为条件没达到而造成设置操作未执行,那么命令返回空批量回复(NULL Bulk Reply)
         */
        public String setXX(String key, Object value, String expx, long interval) {
            Jedis jedis = MyRedisPool.getJedis();
            String result = "";
            try {
                result = jedis.set(key, String.valueOf(value), "XX", expx, interval);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 设置key
         * 需要传入key是否不存存在
         *
         * @param key      键
         * @param value    值
         * @param expx     EX/PX   值只能取EX或者PX,代表数据过期时间的单位,EX代表秒,PX代表毫秒
         * @param interval 过期时间,单位是expx所代表的单位。
         * @return SET 在设置操作成功完成时,才返回 OK 。
         * 如果设置了 NX 或者 XX ,但因为条件没达到而造成设置操作未执行,那么命令返回空批量回复(NULL Bulk Reply)
         */
        public String setNX(String key, Object value, String expx, long interval) {
            Jedis jedis = MyRedisPool.getJedis();
            String result = "";
            try {
                result = jedis.set(key, String.valueOf(value), "NX", expx, interval);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 设将字符串值 value 关联到 key 。
         * 如果 key 已经持有其他值, SET 就覆写旧值,无视类型。
         *
         * @param key   键
         * @param value 值
         * @return SET 在设置操作成功完成时,才返回 OK 。
         */
        public String set(String key, Object value) {
            Jedis jedis = MyRedisPool.getJedis();
            String result = "";
            try {
                result = jedis.set(key, String.valueOf(value));
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 设将字符串值 value 关联到 key 。
         * 如果 key 已经持有其他值, SET 就覆写旧值,无视类型。
         *
         * @param key   键
         * @param value 值
         * @return SET 在设置操作成功完成时,才返回 OK 。
         */
        public String set(String key, Object value, int interval) {
            Jedis jedis = MyRedisPool.getJedis();
            String result = "";
            try {
                result = jedis.set(key, String.valueOf(value));
                expire(key, interval);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 返回 key 所关联的字符串值
         * 如果 key 不存在那么返回特殊值 nil 。
         *
         * @param key
         * @return 当 key 不存在时,返回 nil ,否则,返回 key 的值。
         * 如果 key 不是字符串类型,那么返回一个错误。
         */
        public Object get(String key) {
            Jedis jedis = MyRedisPool.getJedis();
            Object o = null;
            try {
                o = jedis.get(key);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return o;
        }
    
        public List<Map<String,String>> getListBykey(String key) {
            Jedis jedis = MyRedisPool.getJedis();
            List<Map<String,String>> list=new ArrayList<>();
            try {
                Set<String> set  = jedis.keys(key+"*");
                for (String key1 : set){
                    String value1 =String.valueOf(jedis.get(key1));
                    Map<String,String> map=new HashMap<>();
                    map.put(key1,value1);
                    list.add(map);
                }
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return list;
        }
    
        /**
         * 检查给定 key 是否存在。
         *
         * @param key 键
         * @return 若 key 存在,返回 true ,否则返回 false
         */
        public boolean exists(String key) {
            Jedis jedis = MyRedisPool.getJedis();
            boolean flag = false;
            try {
                flag = jedis.exists(key);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return flag;
        }
    
        /**
         * 判断是否存在,存在则返回对象,不存在返回null
         *
         * @param key
         * @return 若 key 存在,返回 1 ,否则返回 0 。
         */
        public Object retExists(String key) {
            Jedis jedis = MyRedisPool.getJedis();
            Object o = null;
            try {
                if (jedis.exists(key)) {
                    o = jedis.get(key);
                }
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return o;
        }
    
        /**
         * 为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。
         * 可以对一个已经带有生存时间的 key 执行 EXPIRE 命令,新指定的生存时间会取代旧的生存时间。
         *
         * @param key
         * @return 设置成功返回 1 。
         * 当 key 不存在或者不能为 key 设置生存时间时(比如在低于 2.1.3 版本的 Redis 中你尝试更新 key 的生存时间),返回 0 。
         */
        public Long expire(String key) {
            Jedis jedis = MyRedisPool.getJedis();
            Long result = 0L;
            try {
                result = jedis.expire(key, -1);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。
         * 可以对一个已经带有生存时间的 key 执行 EXPIRE 命令,新指定的生存时间会取代旧的生存时间。
         *
         * @param key
         * @param interval
         * @return 设置成功返回 1 。
         * 当 key 不存在或者不能为 key 设置生存时间时(比如在低于 2.1.3 版本的 Redis 中你尝试更新 key 的生存时间),返回 0 。
         */
        public Long expire(String key, int interval) {
            Jedis jedis = MyRedisPool.getJedis();
            Long result = 0L;
            try {
                result = jedis.expire(key, interval);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 移除给定 key 的生存时间,将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )。
         *
         * @param key
         * @return 当生存时间移除成功时,返回 1 .
         * 如果 key 不存在或 key 没有设置生存时间,返回 0 。
         */
        public Long persist(String key) {
            Jedis jedis = MyRedisPool.getJedis();
            Long result = 0L;
            try {
                result = jedis.persist(key);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 删除给定的一个或多个 key 。
         * 不存在的 key 会被忽略。
         *
         * @param key 键
         * @return 被删除 key 的数量。
         */
        public Long delete(String key) {
            Jedis jedis = MyRedisPool.getJedis();
            Long result = 0L;
            try {
                result = jedis.del(key);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 将一个或多个 member 元素及其 score 值加入到有序集 key 当中。
         * 如果某个 member 已经是有序集的成员,那么更新这个 member 的 score 值,并通过重新插入这个 member 元素,来保证该 member 在正确的位置上。
         *
         * @param key    键
         * @param score  分数
         * @param member 值
         * @return 被成功添加的新成员的数量,不包括那些被更新的、已经存在的成员。
         */
        public Long zadd(String key, double score, String member) {
            Jedis jedis = MyRedisPool.getJedis();
            Long result = 0L;
            try {
                result = jedis.zadd(key, score, member);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 将一个或多个 member 元素及其 score 值加入到有序集 key 当中。
         * 如果某个 member 已经是有序集的成员,那么更新这个 member 的 score 值,并通过重新插入这个 member 元素,来保证该 member 在正确的位置上。
         *
         * @param key    键
         * @param member 值
         * @return 被成功添加的新成员的数量,不包括那些被更新的、已经存在的成员。
         */
        public Long zadd(String key, String member) {
            Jedis jedis = MyRedisPool.getJedis();
            Long result = 0L;
            try {
                result = jedis.zadd(key, System.currentTimeMillis(), member);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 获取该key总数(全部)
         *
         * @param key
         * @return score 值在 min 和 max 之间的成员的数量
         */
        public Long zcount(String key) {
            Jedis jedis = MyRedisPool.getJedis();
            Long count = 0L;
            try {
                count = jedis.zcount(key, "-inf", "+inf");
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return count;
        }
    
        /**
         * 返回有序集 key 中, score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量。
         *
         * @param key 键
         * @param min 最小值
         * @param max 最大值
         * @return score 值在 min 和 max 之间的成员的数量
         */
        public Long zcount(String key, double min, double max) {
            Jedis jedis = MyRedisPool.getJedis();
            Long count = 0L;
            try {
                count = jedis.zcount(key, min, max);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return count;
        }
    
        /**
         * 返回有序集 key 中,指定区间内的成员。
         * 其中成员的位置按 score 值递增(从小到大)来排序。
         * 超出范围的下标并不会引起错误。
         *
         * @param key   键
         * @param start 开始分数
         * @param end   结束分数
         * @return 指定区间内,带有 score 值(可选)的有序集成员的列表。
         */
        public Set<String> zrange(String key, long start, long end) {
            Jedis jedis = MyRedisPool.getJedis();
            Set<String> list = null;
            try {
                list = jedis.zrange(key, start, end);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return list;
        }
    
        /**
         * 设置 key 指定的哈希集中指定字段的值。
         * 如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联。
         * 如果字段在哈希集中存在,它将被重写。
         *
         * @param key
         * @param field
         * @param value
         * @return 如果 field 是哈希表中的一个新建域,并且值设置成功,返回 1 。
         * 如果哈希表中域 field 已经存在且旧值已被新值覆盖,返回 0 。
         */
        public Long hset(String key, String field, String value) {
            Jedis jedis = MyRedisPool.getJedis();
            Long result = 0L;
            try {
                result = jedis.hset(key, field, value);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 设置 key 指定的哈希集中指定字段的值。该命令将重写所有在哈希集中存在的字段。
         * 如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联
         *
         * @param key
         * @param maps
         * @return 如果命令执行成功,返回 OK 。
         * 当 key 不是哈希表(hash)类型时,返回一个错误。
         */
        public String hmset(String key, Map<String, String> maps) {
            Jedis jedis = MyRedisPool.getJedis();
            String result = "";
            try {
                if (maps == null) {
                    throw new NullPointerException("maps为空!");
                }
                if (!maps.isEmpty()) {
                    result = jedis.hmset(key, maps);
                }
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 返回 key 指定的哈希集中所有的字段和值。
         *
         * @param key
         * @return 以列表形式返回哈希表的域和域的值。
         * 若 key 不存在,返回空列表。
         */
        public Map<String, String> hgetAll(String key) {
            Jedis jedis = MyRedisPool.getJedis();
            Map<String, String> map = null;
            try {
                map = jedis.hgetAll(key);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return map;
        }
    
        /**
         * 对存储在指定key的数值执行原子的加1操作。
         * 如果指定的key不存在,那么在执行incr操作之前,会先将它的值设定为0。
         *
         * @param key
         * @return 执行 INCR 命令之后 key 的值
         */
        public Long incr(String key) {
            Jedis jedis = MyRedisPool.getJedis();
            Long result = 0L;
            try {
                result = jedis.incr(key);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 对key对应的数字做减1操作。如果key不存在,那么在操作之前,这个key对应的值会被置为0。
         * 如果key有一个错误类型的value或者是一个不能表示成数字的字符串,就返回错误。
         *
         * @param key
         * @return 执行 DECR 命令之后 key 的值。
         */
        public Long decr(String key) {
            Jedis jedis = MyRedisPool.getJedis();
            Long result = 0L;
            try {
                result = jedis.decr(key);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。
         * 假如 key 不存在,则创建一个只包含 member 元素作成员的集合。
         * 当 key 不是集合类型时,返回一个错误。
         *
         * @param key
         * @param members
         * @return 被添加到集合中的新元素的数量,不包括被忽略的元素
         */
        public Long sadd(String key, String members) {
            Jedis jedis = MyRedisPool.getJedis();
            Long result = 0L;
            try {
                result = jedis.sadd(key, members);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 返回集合 key 的基数(集合中元素的数量)。
         *
         * @param key
         * @return 集合的基数。当 key 不存在时,返回 0 。
         */
        public Long scard(String key) {
            Jedis jedis = MyRedisPool.getJedis();
            Long result = 0L;
            try {
                result = jedis.scard(key);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 返回集合 key 中的所有成员。不存在的 key 被视为空集合。
         *
         * @param key
         * @return 集合中的所有成员。
         */
        public Set<String> smembers(String key) {
            Jedis jedis = MyRedisPool.getJedis();
            Set<String> set = null;
            try {
                set = jedis.smembers(key);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return set;
        }
    
        /**
         * 判断 member 元素是否集合 key 的成员。
         *
         * @param key
         * @return 如果 member 元素是集合的成员,返回 1 。
         * 如果 member 元素不是集合的成员,或 key 不存在,返回 0 。
         */
        public Boolean sismember(String key, String members) {
            Jedis jedis = MyRedisPool.getJedis();
            Boolean result = false;
            try {
                result = jedis.sismember(key, members);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略。
         *
         * @param key
         * @return 被成功移除的元素的数量,不包括被忽略的元素。
         */
        public Long srem(String key, String members) {
            Jedis jedis = MyRedisPool.getJedis();
            Long result = 0L;
            try {
                result = jedis.srem(key, members);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 返回一个集合的全部成员,该集合是所有给定集合之间的差集。不存在的 key 被视为空集。
         * 但它将结果保存到 destination 集合,而不是简单地返回结果集。如果 destination 集合已经存在,则将其覆盖。
         *
         * @param dstkey
         * @param key
         * @return 结果集中的元素数量。
         */
        public Long sdiffstore(String dstkey, String key) {
            Jedis jedis = MyRedisPool.getJedis();
            Long result = 0L;
            try {
                result = jedis.sdiffstore(dstkey, key);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
        //从队列中左侧进入一个元素
        public Long lpush(String key, String value) {
            Jedis jedis = MyRedisPool.getJedis();
            Long result = 0L;
            try {
                result = jedis.lpush(key,value);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
        //从队列中右侧出一个元素
        public String rpop(String key) {
            Jedis jedis = MyRedisPool.getJedis();
            String result = null;
            try {
                result = jedis.rpop(key);
                MyRedisPool.returnResource(jedis);
            } catch (Exception e) {
                MyRedisPool.returnBrokenResource(jedis);
                e.printStackTrace();
            }
            return result;
        }
    
    
    
    
    
    
        /*******************分布式锁******************/
        public boolean lock(String key, int exprie) {
            try {
                exprie = exprie <= 0 ? 60 : exprie;
                String value = JsonUtil2.obj2String(createMeta(exprie));
                String lockKey = this.getLockKeyPrev() + key;
                String result=this.setNX(lockKey, value,"EX",exprie);
                if (result!=null && result.equals("OK")) {
                    LOGGER.info("Get redis lock success, key =" + lockKey);
                    return true;
                }
                Object obj = this.get(lockKey);
                if (obj==null) {
                    this.delete(lockKey);
                    LOGGER.info("Redis unlock success ,key = " + lockKey);
                    Thread.sleep(1000);
                    value = JsonUtil2.obj2String(createMeta(exprie));
                    String result1=this.setNX(lockKey, value,"EX",exprie);
                    if (result1!=null && result1.equals("OK")) {
                        this.expire(lockKey, exprie);
                        LOGGER.info("Get redis lock success, key =" + lockKey);
                        return true;
                    } else {
                        LOGGER.warn("Get redis lock fail, key =" + lockKey);
                        return false;
                    }
                }
                value = (String)obj;
                LockModel model = JsonUtil2.getObjectMapper().readValue(value, LockModel.class);
                if (model.isLose()) {// 已经超时
                    this.delete(lockKey);
                    value = JsonUtil2.obj2String(createMeta(exprie));
                    String result2=this.setNX(lockKey, value,"EX",exprie);
                    if (result2!=null && result2.equals("OK")) {
                        this.expire(lockKey, exprie);
                        LOGGER.info("Get redis lock success, key =" + lockKey);
                        return true;
                    } else {
                        LOGGER.warn("Get redis lock fail, key =" + lockKey);
                        return false;
                    }
                }
                LOGGER.warn("Get redis lock fail, key =" + lockKey);
                return false;
            } catch (Exception ex) {
                ex.printStackTrace();
                LOGGER.error(ex.getMessage());
                return true;
            }
        }
    
        public void unlock(String key) {
            String lockKey = this.getLockKeyPrev() + key;
            try {
                delete(lockKey);
            } catch (Exception ex) {
                LOGGER.error(ex.getMessage());
            }
            LOGGER.info("Redis unlock success ,key = " + lockKey);
        }
    
        private LockModel createMeta(int exprie) {
            LockModel meta = new LockModel();
            meta.setExpireTime(exprie);
            meta.setLockTime(System.currentTimeMillis());
            return meta;
        }
    
        public String getLockKeyPrev() {
            return "lock:";
        }
        /*******************分布式锁******************/
    View Code

    4.Redis分布式锁

    1.基于redis的setnx 命令实现分布式锁

    2.lua脚本结合redis命令可以实现原子性(Redis 服务器会单线程原子性执行 lua 脚本,保证 lua 脚本在处理的过程中不会被任意其它请求打断)

    代码使用样例:

     try {
            boolean isLock= RedisClient.getInstance().lock(TASK_NAME,30);
            if (!isLock){
                return;
            }
            handle();
        } catch (Exception e) {
            log.error("error: e=" + e.getMessage());
        } finally {
            RedisClient.getInstance().unlock(TASK_NAME);
        }
    View Code
  • 相关阅读:
    Jmeter之http性能测试实战 非GUI模式压测 NON-GUI模式 结果解析TPS——干货(十一)
    UI Recorder 自动化测试 回归原理(九)
    UI Recorder 自动化测试 录制原理(八)
    UI Recorder 自动化测试 整体架构(七)
    UI Recorder 自动化测试 配置项(六)
    UI Recorder 自动化测试 工具栏使用(五)
    UI Recorder 自动化测试 回归测试(四)
    UI Recorder 自动化测试 录制(三)
    UI Recorder 自动化测试工具安装问题疑难杂症解决(二)
    UI Recorder 自动化测试安装教程(一)
  • 原文地址:https://www.cnblogs.com/brant/p/12496331.html
Copyright © 2011-2022 走看看