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
  • 相关阅读:
    Haskell学习笔记--class/typeclass/show/read
    Haskell学习笔记--scanl/scanr
    Haskell学习笔记--foldl/flodr/高阶函数
    EasyUI 表单验证扩展(备忘录)
    基于FPGA的视频时序生成
    如何调用Altera FPGA的内嵌乘法器
    基于FPGA视频时序生成中的库文件
    基于FPGA的序列检测器10010
    NOIP2017游记
    【NOIP模拟赛】异象石
  • 原文地址:https://www.cnblogs.com/brant/p/12496331.html
Copyright © 2011-2022 走看看