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
原文地址:https://www.cnblogs.com/brant/p/12496331.html