|  | @@ -0,0 +1,934 @@
 | 
	
		
			
				|  |  | +package com.tzld.crawler.etl.util;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import org.apache.ibatis.cache.CacheException;
 | 
	
		
			
				|  |  | +import org.springframework.beans.factory.annotation.Autowired;
 | 
	
		
			
				|  |  | +import org.springframework.beans.factory.annotation.Qualifier;
 | 
	
		
			
				|  |  | +import org.springframework.data.redis.core.Cursor;
 | 
	
		
			
				|  |  | +import org.springframework.data.redis.core.RedisCallback;
 | 
	
		
			
				|  |  | +import org.springframework.data.redis.core.RedisTemplate;
 | 
	
		
			
				|  |  | +import org.springframework.data.redis.core.ScanOptions;
 | 
	
		
			
				|  |  | +import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
 | 
	
		
			
				|  |  | +import org.springframework.data.redis.core.script.DefaultRedisScript;
 | 
	
		
			
				|  |  | +import org.springframework.scripting.support.StaticScriptSource;
 | 
	
		
			
				|  |  | +import org.springframework.stereotype.Component;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import java.util.*;
 | 
	
		
			
				|  |  | +import java.util.concurrent.TimeUnit;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * redis 操作
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * @author supeng
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +@Component
 | 
	
		
			
				|  |  | +public class RedisUtil {
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 锁前缀
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private static final String LOCK_PREFIX = "LOCK_";
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 默认重试次数
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private static final Integer DEFAULT_RETRIES = 1;
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 默认 10毫秒
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private static final Long DEFAULT_INTERVAL = 10L;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 加锁lua脚本
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private static final String LOCK = "if (redis.call('exists', KEYS[1]) == 0) then " +
 | 
	
		
			
				|  |  | +            "redis.call('hset', KEYS[1], ARGV[2], 1); " +
 | 
	
		
			
				|  |  | +            "redis.call('pexpire', KEYS[1], ARGV[1]); " +
 | 
	
		
			
				|  |  | +            "return 1; " +
 | 
	
		
			
				|  |  | +            "end; " +
 | 
	
		
			
				|  |  | +            "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +
 | 
	
		
			
				|  |  | +            "redis.call('hincrby', KEYS[1], ARGV[2], 1); " +
 | 
	
		
			
				|  |  | +            "redis.call('pexpire', KEYS[1], ARGV[1]); " +
 | 
	
		
			
				|  |  | +            "return 1; " +
 | 
	
		
			
				|  |  | +            "end; " +
 | 
	
		
			
				|  |  | +            "return 0;";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 解锁 lua 脚本
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public static final String UNLOCK = "if (redis.call('hexists', KEYS[1], ARGV[1]) == 0) then " +
 | 
	
		
			
				|  |  | +            "return nil; " +
 | 
	
		
			
				|  |  | +            "end; " +
 | 
	
		
			
				|  |  | +            "local counter = redis.call('hincrby', KEYS[1], ARGV[1], -1); " +
 | 
	
		
			
				|  |  | +            "if (counter > 0) then " +
 | 
	
		
			
				|  |  | +            "return 0; " +
 | 
	
		
			
				|  |  | +            "else " +
 | 
	
		
			
				|  |  | +            "redis.call('del', KEYS[1]); " +
 | 
	
		
			
				|  |  | +            "return 1; " +
 | 
	
		
			
				|  |  | +            "end; " +
 | 
	
		
			
				|  |  | +            "return nil;";
 | 
	
		
			
				|  |  | +    @Qualifier("redisTemplate")
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    RedisTemplate<String, String> redisTemplate;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /** ================Key相关操作================ */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 是否存在key
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Boolean hasKey(String key) {
 | 
	
		
			
				|  |  | +        return redisTemplate.hasKey(key);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * scan
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param matchKey
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Set<String> scan(String matchKey) {
 | 
	
		
			
				|  |  | +        Set<String> keys = redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
 | 
	
		
			
				|  |  | +            Set<String> keysTmp = new HashSet<>();
 | 
	
		
			
				|  |  | +            Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match("*" + matchKey + "*").count(1000).build());
 | 
	
		
			
				|  |  | +            while (cursor.hasNext()) {
 | 
	
		
			
				|  |  | +                keysTmp.add(new String(cursor.next()));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            return keysTmp;
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        return keys;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 删除 key
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Boolean deleteKey(String key) {
 | 
	
		
			
				|  |  | +        return redisTemplate.delete(key);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 删除多个key
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param keys
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long deleteKeys(Collection<String> keys) {
 | 
	
		
			
				|  |  | +        return redisTemplate.delete(keys);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 设置key的过期时间
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param timeout
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Boolean expire(String key, long timeout) {
 | 
	
		
			
				|  |  | +        if (timeout < 0) {
 | 
	
		
			
				|  |  | +            return false;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 获取key剩余的过期时间,秒
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return key不存在,返回-2,key存在并且没有设置过期时间(永久有效),返回 -1
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long getExpire(String key) {
 | 
	
		
			
				|  |  | +        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /** ================String相关操作================ */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 获取 值
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public String get(String key) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForValue().get(key);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 获取多个值
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param keys
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public List<String> multiGet(Collection<String> keys) {
 | 
	
		
			
				|  |  | +        if (keys != null && keys.size() > 200) {
 | 
	
		
			
				|  |  | +            throw new CacheException("too many keys, max 200");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForValue().multiGet(keys);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * set 值
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param value
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public void set(String key, String value) {
 | 
	
		
			
				|  |  | +        redisTemplate.opsForValue().set(key, value);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * set 值并指定过期时间
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param value
 | 
	
		
			
				|  |  | +     * @param timeout
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public void set(String key, String value, long timeout) {
 | 
	
		
			
				|  |  | +        redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 设置String缓存值,只有key不存在时才能设置成功
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param value
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Boolean setNx(String key, String value) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForValue().setIfAbsent(key, value);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 设置String缓存值并指定过期时间,只有key不存在时才能设置成功
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param value
 | 
	
		
			
				|  |  | +     * @param timeout
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Boolean setNx(String key, String value, long timeout) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForValue().setIfAbsent(key, value, timeout, TimeUnit.SECONDS);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * getAndSet 值
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param value
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public String getAndSet(String key, String value) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForValue().getAndSet(key, value);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * key的值 +1
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     * @version 1.0
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long incr(String key) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForValue().increment(key);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * key的值 +delta
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param delta
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     * @version 1.0
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long incrBy(String key, long delta) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForValue().increment(key, delta);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public Long incrBy(String key, long delta, long timeout) {
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            Long result = redisTemplate.opsForValue().increment(key, delta);
 | 
	
		
			
				|  |  | +            redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
 | 
	
		
			
				|  |  | +            return result;
 | 
	
		
			
				|  |  | +        } catch (Exception e) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return null;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * key的值 -1
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     * @version 1.0
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long decr(String key) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForValue().decrement(key);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * key的值 -delta
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param delta
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     * @version 1.0
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long desrBy(String key, long delta) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForValue().decrement(key, delta);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /** ================Hashes相关操作================ */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 是否存在 hashkey
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param hashKey
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public boolean hasHashKey(String key, String hashKey) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForHash().hasKey(key, hashKey);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 获取hash某个字段的值
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param hashKey
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Object hget(String key, String hashKey) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForHash().get(key, hashKey);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 获取hash所有键值(hashkey超过200个时禁止使用)
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Map<Object, Object> hgetAll(String key) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForHash().entries(key);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 获取hash对应多个字段的值
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param hashKeys
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public List<Object> hmget(String key, List<Object> hashKeys) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForHash().multiGet(key, hashKeys);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 设置hash中某个字段的值,如果不存在将创建
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param hashKey
 | 
	
		
			
				|  |  | +     * @param value
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public void hset(String key, String hashKey, String value) {
 | 
	
		
			
				|  |  | +        redisTemplate.opsForHash().put(key, hashKey, value);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 设置hash中某个字段的值并指定key的过期时间,如果不存在将创建
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param hashKey
 | 
	
		
			
				|  |  | +     * @param value
 | 
	
		
			
				|  |  | +     * @param timeout 单位:秒
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public void hset(String key, String hashKey, String value, long timeout) {
 | 
	
		
			
				|  |  | +        redisTemplate.opsForHash().put(key, hashKey, value);
 | 
	
		
			
				|  |  | +        expire(key, timeout);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 设置hash中某个字段的值,只有当这个字段不存在时才能设置成功
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param hashKey
 | 
	
		
			
				|  |  | +     * @param value
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Boolean hsetNx(String key, String hashKey, String value) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForHash().putIfAbsent(key, hashKey, value);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 删除hash中的多个字段
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param hashKey
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public void hdel(String key, Object... hashKey) {
 | 
	
		
			
				|  |  | +        redisTemplate.opsForHash().delete(key, hashKey);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 将hash中的某个字段值增加delta
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param hashKey
 | 
	
		
			
				|  |  | +     * @param delta
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long hincrBy(String key, String hashKey, long delta) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForHash().increment(key, hashKey, delta);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public Long hincrBy(String key, String hashKey, long delta, long timeout) {
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            Long result = redisTemplate.opsForHash().increment(key, hashKey, delta);
 | 
	
		
			
				|  |  | +            redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
 | 
	
		
			
				|  |  | +            return result;
 | 
	
		
			
				|  |  | +        } catch (Exception e){
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return null;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /** ================Lists相关操作================ */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 返回list中指定范围的元素,第一个元素为0,最后一个元素为-1,倒数第二个为-2,以此类推。
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param start
 | 
	
		
			
				|  |  | +     * @param end
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public List<String> lrange(String key, long start, long end) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForList().range(key, start, end);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 获取list的长度
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long llen(String key) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForList().size(key);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 获取list中index索引的元素
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public String lindex(String key, long index) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForList().index(key, index);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 向list的尾部插入指定的元素
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param value
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long rpush(String key, String value) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForList().rightPush(key, value);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 向list的尾部插入多个元素
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param values
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long rpushAll(String key, Collection<String> values) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForList().rightPushAll(key, values);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 移除并返回list尾部的元素
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public String rpop(String key) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForList().rightPop(key);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 向list的头部插入指定的元素
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param value
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long lpush(String key, String value) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForList().leftPush(key, value);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 向list的头部插入多个元素
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param values
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long lpushAll(String key, Collection<String> values) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForList().leftPushAll(key, values);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 移除并返回list头部的元素
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public String lpop(String key) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForList().leftPop(key);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 修改list中index索引对应元素的值
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param index
 | 
	
		
			
				|  |  | +     * @param value
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public void lset(String key, long index, String value) {
 | 
	
		
			
				|  |  | +        redisTemplate.opsForList().set(key, index, value);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 从list中移除前count个出现值为value的元素
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param count count > 0: 从头往尾移除值为 value 的元素。</br>
 | 
	
		
			
				|  |  | +     *              count < 0: 从尾往头移除值为 value 的元素。</br>
 | 
	
		
			
				|  |  | +     *              count = 0: 移除所有值为 value 的元素。
 | 
	
		
			
				|  |  | +     * @param value
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long lrem(String key, long count, String value) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForList().remove(key, count, value);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * lpop多个数据
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param count
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public List<Object> lpopMutil(String key, long count) {
 | 
	
		
			
				|  |  | +        List<Object> result = redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
 | 
	
		
			
				|  |  | +            connection.lRange(key.getBytes(), 0, count - 1);
 | 
	
		
			
				|  |  | +            connection.lTrim(key.getBytes(), count, -1);
 | 
	
		
			
				|  |  | +            return null;
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * rpop多个数据
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param start 起始位置  end=-1
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public List<Object> rpopMutil(String key, long start) {
 | 
	
		
			
				|  |  | +        List<Object> result = redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
 | 
	
		
			
				|  |  | +            connection.lRange(key.getBytes(), start, -1);
 | 
	
		
			
				|  |  | +            connection.lTrim(key.getBytes(), 0, start - 1);
 | 
	
		
			
				|  |  | +            return null;
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 从右取多个值
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param count 个数
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public List<Object> rpopMutil(String key, int count) {
 | 
	
		
			
				|  |  | +        List<Object> result = redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
 | 
	
		
			
				|  |  | +            connection.lRange(key.getBytes(), 0 - count, -1);
 | 
	
		
			
				|  |  | +            connection.lTrim(key.getBytes(), 0, -1 - count);
 | 
	
		
			
				|  |  | +            return null;
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /** ================Sets相关操作================ */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * set集合中是否存在值为value的元素
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param value
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public boolean sIsMember(String key, String value) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForSet().isMember(key, value);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 返回set集合所有元素,禁止直接使用members,通过scan获取
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Set<String> sscan(String key) {
 | 
	
		
			
				|  |  | +        Set<String> result = new HashSet<>();
 | 
	
		
			
				|  |  | +        Cursor<String> cursor = redisTemplate.opsForSet().scan(key, ScanOptions.NONE);
 | 
	
		
			
				|  |  | +        while (cursor != null && cursor.hasNext()) {
 | 
	
		
			
				|  |  | +            result.add(cursor.next());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 向set集合添加多个元素
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param values
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long sadd(String key, String... values) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForSet().add(key, values);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 返回set集合的元素个数
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long scard(String key) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForSet().size(key);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 从set中移除值为value的元素
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param values
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long srem(String key, Object... values) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForSet().remove(key, values);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /** ================Sorted Sets相关操作================ */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 向zset集合添加一个元素,或者更新已存在元素的分数
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param vaule
 | 
	
		
			
				|  |  | +     * @param score
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public void zadd(String key, String vaule, double score) {
 | 
	
		
			
				|  |  | +        redisTemplate.opsForZSet().add(key, vaule, score);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 向zset集合添加一个元素,或者更新已存在元素的分数,并更新key的过期时间
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param vaule
 | 
	
		
			
				|  |  | +     * @param score
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public void zadd(String key, String vaule, double score, long timeout) {
 | 
	
		
			
				|  |  | +        redisTemplate.opsForZSet().add(key, vaule, score);
 | 
	
		
			
				|  |  | +        expire(key, timeout);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 获取某个元素的分数
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param value
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Double zscore(String key, String value) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForZSet().score(key, value);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 获取zset集合的元素数量
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long zcard(String key) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForZSet().zCard(key);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * zset 范围内元素个数
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param min
 | 
	
		
			
				|  |  | +     * @param max
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Long zcount(String key, double min, double max) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForZSet().count(key, min, max);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 通过索引区间返回zset集合成指定区间内的元素,分数从小到大排序
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param start
 | 
	
		
			
				|  |  | +     * @param end
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Set<String> zrange(String key, long start, long end) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForZSet().range(key, start, end);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 通过索引区间返回zset集合成指定区间内的元素,分数从大到小排序
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param start
 | 
	
		
			
				|  |  | +     * @param end
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Set<String> zreverseRange(String key, long start, long end) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForZSet().reverseRange(key, start, end);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 通过索引区间返回zset集合成指定区间内的元素及分数
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param start
 | 
	
		
			
				|  |  | +     * @param end
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public List<Map<String, Double>> zrangeWithScores(String key, long start, long end) {
 | 
	
		
			
				|  |  | +        List<Map<String, Double>> result = new ArrayList<>();
 | 
	
		
			
				|  |  | +        Set<TypedTuple<String>> cursor = redisTemplate.opsForZSet().rangeWithScores(key, start, end);
 | 
	
		
			
				|  |  | +        for (Iterator<TypedTuple<String>> it = cursor.iterator(); it.hasNext(); ) {
 | 
	
		
			
				|  |  | +            TypedTuple<String> item = it.next();
 | 
	
		
			
				|  |  | +            Map<String, Double> map = new HashMap<>();
 | 
	
		
			
				|  |  | +            map.put(item.getValue(), item.getScore());
 | 
	
		
			
				|  |  | +            result.add(map);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 通过索引区间返回zset集合成指定区间内的元素及分数
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param start
 | 
	
		
			
				|  |  | +     * @param end
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public List<Map<String, Object>> zrangeWithScoresToList(String key, long start, long end) {
 | 
	
		
			
				|  |  | +        List<Map<String, Object>> result = new ArrayList<>();
 | 
	
		
			
				|  |  | +        Set<TypedTuple<String>> cursor = redisTemplate.opsForZSet().rangeWithScores(key, start, end);
 | 
	
		
			
				|  |  | +        for (Iterator<TypedTuple<String>> it = cursor.iterator(); it.hasNext(); ) {
 | 
	
		
			
				|  |  | +            TypedTuple<String> item = it.next();
 | 
	
		
			
				|  |  | +            Map<String, Object> map = new HashMap<>();
 | 
	
		
			
				|  |  | +            map.put("value", item.getValue());
 | 
	
		
			
				|  |  | +            map.put("score", item.getScore());
 | 
	
		
			
				|  |  | +            result.add(map);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 通过索引区间返回zset集合成指定区间内的元素及分数
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param start
 | 
	
		
			
				|  |  | +     * @param end
 | 
	
		
			
				|  |  | +     * @return map
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Map<String, Double> zrangeWithScoresToMap(String key, long start, long end) {
 | 
	
		
			
				|  |  | +        Map<String, Double> result = new HashMap<>();
 | 
	
		
			
				|  |  | +        Set<TypedTuple<String>> cursor = redisTemplate.opsForZSet().rangeWithScores(key, start, end);
 | 
	
		
			
				|  |  | +        for (Iterator<TypedTuple<String>> it = cursor.iterator(); it.hasNext(); ) {
 | 
	
		
			
				|  |  | +            TypedTuple<String> item = it.next();
 | 
	
		
			
				|  |  | +            result.put(item.getValue(), item.getScore());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 迭代zset集合中的元素(只包括元素成员)
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Set<String> zscanValues(String key) {
 | 
	
		
			
				|  |  | +        Set<String> result = new HashSet<>();
 | 
	
		
			
				|  |  | +        Cursor<TypedTuple<String>> cursor = redisTemplate.opsForZSet().scan(key, ScanOptions.NONE);
 | 
	
		
			
				|  |  | +        while (cursor.hasNext()) {
 | 
	
		
			
				|  |  | +            TypedTuple<String> item = cursor.next();
 | 
	
		
			
				|  |  | +            result.add(item.getValue());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 迭代zset集合中的元素(包括元素和分数)
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public List<Map<String, Double>> zscan(String key) {
 | 
	
		
			
				|  |  | +        List<Map<String, Double>> result = new ArrayList<Map<String, Double>>();
 | 
	
		
			
				|  |  | +        Cursor<TypedTuple<String>> cursor = redisTemplate.opsForZSet().scan(key, ScanOptions.NONE);
 | 
	
		
			
				|  |  | +        while (cursor.hasNext()) {
 | 
	
		
			
				|  |  | +            TypedTuple<String> item = cursor.next();
 | 
	
		
			
				|  |  | +            Map<String, Double> map = new HashMap<String, Double>();
 | 
	
		
			
				|  |  | +            map.put(item.getValue(), item.getScore());
 | 
	
		
			
				|  |  | +            result.add(map);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 移除zset集合中的元素
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param values
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public void zRemove(String key, Object... values) {
 | 
	
		
			
				|  |  | +        redisTemplate.opsForZSet().remove(key, values);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 移除zset集合指定范围数据
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param start
 | 
	
		
			
				|  |  | +     * @param end
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public void zRemRange(String key, long start, long end) {
 | 
	
		
			
				|  |  | +        redisTemplate.opsForZSet().removeRange(key, start, end);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 删除
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param min
 | 
	
		
			
				|  |  | +     * @param max
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public void zRemRangeByScore(String key, double min, double max) {
 | 
	
		
			
				|  |  | +        redisTemplate.opsForZSet().removeRangeByScore(key, min, max);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 加锁 不可重入
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @param timeout 毫秒
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Boolean lock(String key, long timeout) {
 | 
	
		
			
				|  |  | +        return redisTemplate.opsForValue().setIfAbsent(LOCK_PREFIX + key, "1", timeout, TimeUnit.MILLISECONDS);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 解锁 不可重入
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Boolean unlock(String key) {
 | 
	
		
			
				|  |  | +        return redisTemplate.delete(LOCK_PREFIX + key);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 加锁
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key         key
 | 
	
		
			
				|  |  | +     * @param reentrantId 重入Id
 | 
	
		
			
				|  |  | +     * @param timeout     超时时间 毫秒ms
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Boolean lock(String key, String reentrantId, long timeout) {
 | 
	
		
			
				|  |  | +        return lock(key, reentrantId, timeout, DEFAULT_RETRIES);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 加锁
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key         key
 | 
	
		
			
				|  |  | +     * @param reentrantId 重入Id
 | 
	
		
			
				|  |  | +     * @param timeout     超时时间 毫秒ms
 | 
	
		
			
				|  |  | +     * @param retries     重试次数
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Boolean lock(String key, String reentrantId, long timeout, int retries) {
 | 
	
		
			
				|  |  | +        return lock(key, reentrantId, timeout, retries, DEFAULT_INTERVAL);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 加锁
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key         key
 | 
	
		
			
				|  |  | +     * @param reentrantId 重入Id
 | 
	
		
			
				|  |  | +     * @param timeout     超时时间 毫秒ms
 | 
	
		
			
				|  |  | +     * @param retries     重试次数
 | 
	
		
			
				|  |  | +     * @param interval    每次重试间隔时间 毫秒
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Boolean lock(String key, String reentrantId, long timeout, int retries, long interval) {
 | 
	
		
			
				|  |  | +        String lockKey = LOCK_PREFIX + key;
 | 
	
		
			
				|  |  | +        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
 | 
	
		
			
				|  |  | +        script.setResultType(Long.class);
 | 
	
		
			
				|  |  | +        script.setScriptSource(new StaticScriptSource(LOCK));
 | 
	
		
			
				|  |  | +        for (int i = 0; i < retries; i++) {
 | 
	
		
			
				|  |  | +            Object result = redisTemplate.execute(script, Arrays.asList(lockKey), String.valueOf(timeout), reentrantId);
 | 
	
		
			
				|  |  | +            if (Objects.nonNull(result) && Objects.equals(1L, Long.valueOf(result.toString()))) {
 | 
	
		
			
				|  |  | +                return true;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            try {
 | 
	
		
			
				|  |  | +                TimeUnit.MILLISECONDS.sleep(interval);
 | 
	
		
			
				|  |  | +            } catch (InterruptedException e) {
 | 
	
		
			
				|  |  | +                e.printStackTrace();
 | 
	
		
			
				|  |  | +                return null;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 解锁
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param key         key
 | 
	
		
			
				|  |  | +     * @param reentrantId 重入ID
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public Boolean unlock(String key, String reentrantId) {
 | 
	
		
			
				|  |  | +        String lockKey = LOCK_PREFIX + key;
 | 
	
		
			
				|  |  | +        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
 | 
	
		
			
				|  |  | +        script.setResultType(Long.class);
 | 
	
		
			
				|  |  | +        script.setScriptSource(new StaticScriptSource(UNLOCK));
 | 
	
		
			
				|  |  | +        Object result = redisTemplate.execute(script, Arrays.asList(lockKey), reentrantId);
 | 
	
		
			
				|  |  | +        if (Objects.isNull(result)) {
 | 
	
		
			
				|  |  | +            return null;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (Objects.equals(1L, Long.valueOf(result.toString()))) {
 | 
	
		
			
				|  |  | +            return true;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +}
 |