Redis 数据类型 和 spring-data-redis使用实例

一、redis数据类型

Redis目前支持5种数据类型,分别是:

String(字符串)
List(列表)
Hash(字典)
Set(集合)
Sorted Set(有序集合)

1.String

Redis 数据类型 和 spring-data-redis使用实例_第1张图片
image.png

Redis中的字符串是一个字节序列。Redis中的字符串是二进制安全的,这意味着它们的长度不由任何特殊的终止字符决定。因此,可以在一个字符串中存储高达512兆字节的任何内容。

2.List

Redis 数据类型 和 spring-data-redis使用实例_第2张图片
image.png

Redis列表只是字符串列表,按插入顺序排序。您可以向Redis列表的头部或尾部添加元素。
其实,我觉得这个更像我们java的queue,一样的是先进先出的的原理,线程安全的。很多时候我们在不使用消息中间件的时候,也可以使用列表类型来代替,而且比较轻量

3.Hash

Redis 数据类型 和 spring-data-redis使用实例_第3张图片
image.png

Redis散列/哈希(Hashes)是键值对的集合。Redis散列/哈希是字符串字段和字符串值之间的映射。因此,它们用于表示对象。

哈希这个就跟我们java的hashMap很像了,将一个对象当做一个hashMap。对象的属性是key值,属性值是value值。我们可以通过这个数据类型很快的拿出指定的某一属性值,而不是一次将有用和无用的属性全部拿出

4.Set

Redis 数据类型 和 spring-data-redis使用实例_第4张图片
image.png

Redis集合是字符串的无序集合。在Redis中,您可以添加,删除和测试成员存在的时间O(1)复杂性。
这个数据类型,我个人觉得就真的仅仅是一个容器而已。他不需要排序,只需要知道数据是否存在。与List的最大区别应该就是有序和无序

5.Sorted Set

Redis 数据类型 和 spring-data-redis使用实例_第5张图片
image.png

Redis可排序集合类似于Redis集合,是不重复的字符集合。 不同之处在于,排序集合的每个成员都与分数相关联,这个分数用于按最小分数到最大分数来排序的排序集合。虽然成员是唯一的,但分数值可以重复。

抱歉这里数据是不齐全的,但是这真的是个很有用的数据类型。这个数据类型让我们可以根据score达到自己期望的排序。更关键的是,我们可以利用这个机制在redis中进行分页查询,这个我在后面会给出实例。

二、spring-data-redis

spring-data-redis就是spring在jedis的基础上封装的工具,总的来说感觉比jedis更加易用,而且在都是使用spring生态环境的的情况下,用spring自家的东西总是好的。
至于具体的怎么安装,搭建环境。这么简单的事情,我想就不用在这里废话了。主要是给出几个spring-data-redis 写的比较好的使用实例。
首先,我们在写redis的key值命名时推荐按照"业务名称:唯一值"这种格式来命名。其中 “:” 的作用就是用于分组的,不仅是为了让key业务属性更加清晰,而且在某些视图工具下,工具可以根据分号给你自动分组,更加易于查看,例如:

Redis 数据类型 和 spring-data-redis使用实例_第6张图片
image.png

![Uploading image_984753.png . . .]

我的key全名是 “TXN_NUM_GENERATOR:DCORF” 但是我有一组string数据都是TXN_NUM_GENERATOR前缀,工具就会自动给我归类分组。这样我们查看起来会清晰不少。试想每个key都是并列的,当有10W个key,我们需要查找时那是多么恐怖的情况。

然后代码使用。可以使用一个枚举类将5种类型定义,如下

Redis 数据类型 和 spring-data-redis使用实例_第7张图片
image.png

然后,可以根据业务属性建立对应的keyName

   public enum CacheName {

    /**
     * 缓存类型
     */
    private CacheType type;

    /**
     * 缓存前缀
     */
    private String prefix;

    /**
     * 缓存匹配器
     */
    private String regex;

    /**
     * 过期时间
     */
    private long expiration;

    CacheName(CacheType cacheType, long expiration) {
        this.type = cacheType;
        this.expiration = expiration;
        this.prefix = this.name().concat(":");
        this.regex = prefix.concat("*");
    }

    public long getExpiration() {
        return expiration;
    }

    public String getPrefix() {
        return prefix;
    }

    public String getRegex() {
        return regex;
    }

    public CacheType getType() {
        return type;
    }
    
    /**
     * 1天,拍卖中的拍品 key:IN_AUCTION_LOT:lotId value:LotRedisDto TODO 检查生产没有后删除
     */
    //IN_AUCTION_LOT(CacheType.V, 86400),

    /**
     * 5秒,竞价锁
     */
    IN_AUCTION_LOT_BID_LOCK(CacheType.S, 5),

    /**
     * 5秒,竞价订单锁
     */
    IN_AUCTION_LOT_ORDER_LOCK(CacheType.S, 5),

    /**
     * 5秒,竞拍中拍品时间锁
     */
    IN_AUCTION_LOT_TIME_LOCK(CacheType.S, 5) ;
}

在定义一个key的时候,我们就可以将其的数据类型和过期时间通过构造器定义。

以下是spring-data-redis 提供的五种数据类型的service

Redis 数据类型 和 spring-data-redis使用实例_第8张图片
image.png

以下,附上部分使用代码

public interface RedisService {

/**
 * 从redis获取String类型数据
 *
 * @param cacheName 缓存名称
 * @param key       组成key的变量
 * @return key对应value
 */
Object vGet(CacheUtils.CacheName cacheName, String key);



/**
 * 获取指定缓存名称的String类型数据
 *
 * @param cacheName  缓存名称
 * @param isRedisKey 是否是redis中的key true:是 false:否
 * @param keys       组成key的变量
 * @return value列表
 */
List vMultiGet(CacheUtils.CacheName cacheName, boolean isRedisKey, String... keys);

/**
 * 往redis中存入String类型数据
 *
 * @param cacheName 缓存名称
 * @param key       组成key的变量
 * @param value     要存入的数据
 */
void vPut(CacheUtils.CacheName cacheName, String key, Object value);


/**
 * 往redis中存入Set类型数据
 *
 * @param cacheName 缓存名称
 * @param key       组成key的变量
 * @param values    要存入的数据
 * @return 添加成功的数量
 */
Long sPut(CacheUtils.CacheName cacheName, String key, Object... values);

/**
 * 查询redis的Set类型中是否有指定对象
 *
 * @param cacheName 缓存名称
 * @param key       组成key的变量
 * @return true 存在,false不存在
 */
Boolean sExist(CacheUtils.CacheName cacheName, String key, Object value);

/**
 * 从redis的Set类型中删除数据
 *
 * @param cacheName 缓存名称
 * @param key       组成key的变量
 * @param values    要删除的数据
 * @return 删除成功的数量
 */
Long sRemove(CacheUtils.CacheName cacheName, String key, Object... values);

/**
 * 查询redis的Set类型中所有数据
 *
 * @param cacheName 缓存名称
 * @param key       组成key的变量
 * @return 数据列表
 */
Set sGetAll(CacheUtils.CacheName cacheName, String key);

/**
 * 无条件分页查询SortedSet中的全部数据
 *
 * @param cacheName 缓存名称
 * @param key       组成key的变量
 * @param pageable  分页参数
 * @param isAsc     true:升序 false:降序
 * @return 成员列表
 */
Set zGet(CacheUtils.CacheName cacheName, String key, Pageable pageable, boolean isAsc);

/**
 * 按照分数条件分页查询SortedSet中的数据
 *
 * @param cacheName 缓存名称
 * @param key       组成key的变量
 * @param includeMin  是否包含最小值
 * @param minScore    最小值
 * @param includeMax  是否包含最大值
 * @param maxScore    最大值
 * @param pageable  分页参数
 * @param isAsc     true:升序 false:降序
 * @return 成员列表
 */
Set zGetByScore(CacheUtils.CacheName cacheName, String key, boolean includeMin, Double minScore, boolean includeMax, Double maxScore, Pageable pageable, boolean isAsc); }

实现类:

 @Service("redisService")
 public class RedisServiceImpl implements RedisService {

@Resource
private RedisTemplate redisTemplate;

/**
 * String(字符串)操作类
 */
@Resource(name = "redisTemplate")
private ValueOperations valueOps;

/**
 * List(列表)操作类
 */
@Resource(name = "redisTemplate")
private ListOperations listOps;

/**
 * Set(集合)操作类
 */
@Resource(name = "redisTemplate")
private SetOperations setOps;

/**
 * SortedSet(有序集合)操作类
 */
@Resource(name = "redisTemplate")
private ZSetOperations zSetOps;

/**
 * Hash(哈希表)操作类
 */
@Resource(name = "redisTemplate")
private HashOperations hashOps;

@Override
public Object vGet(CacheUtils.CacheName cacheName, String key) {
    if (cacheName.getType() != CacheUtils.CacheType.V) {
        return null;
    }
    return valueOps.get(cacheName.getPrefix().concat(key));
}


@Override
public List vMultiGet(CacheUtils.CacheName cacheName, boolean isRedisKey, String... keys) {
    if (cacheName.getType() != CacheUtils.CacheType.V) {
        return null;
    }
    if (CollectionUtilPlus.isNullOrEmptyArray(keys)) {
        return null;
    }
    Set cacheKeys = new HashSet<>();
    for (String key : keys) {
        if (isRedisKey) { //redis中的key
            cacheKeys.add(key);
        } else { //组成key的变量
            cacheKeys.add(cacheName.getPrefix().concat(key));
        }
    }
    List result = valueOps.multiGet(cacheKeys);
    return result;
}

@Override
public void vPut(CacheUtils.CacheName cacheName, String key, Object value) {
    if (cacheName.getType() != CacheUtils.CacheType.V) {
        return;
    }
    if (cacheName.getExpiration() > 0) {
        valueOps.set(cacheName.getPrefix().concat(key), value, cacheName.getExpiration(), TimeUnit.SECONDS);
    } else {
        valueOps.set(cacheName.getPrefix().concat(key), value);
    }
}




@Override
public Long sPut(CacheUtils.CacheName cacheName, String key, Object... values) {
    if (cacheName.getType() != CacheUtils.CacheType.S) {
        return 0L;
    }
    if (CollectionUtilPlus.isNullOrEmptyArray(values)) {
        return 0L;
    }
    String cacheKey = cacheName.getPrefix().concat(key);
    Long result = setOps.add(cacheKey, values);
    if (cacheName.getExpiration() > 0) {
        redisTemplate.expire(cacheKey, cacheName.getExpiration(), TimeUnit.SECONDS);
    }
    return result;
}

@Override
public Boolean sExist(CacheUtils.CacheName cacheName, String key, Object value) {
    if (cacheName.getType() != CacheUtils.CacheType.S) {
        return false;
    }
    String cacheKey = cacheName.getPrefix().concat(key);
    return setOps.isMember(cacheKey, value);
}

@Override
public Long sRemove(CacheUtils.CacheName cacheName, String key, Object... values) {
    if (cacheName.getType() != CacheUtils.CacheType.S) {
        return null;
    }
    if (CollectionUtilPlus.isNullOrEmptyArray(values)) {
        return null;
    }
    String cacheKey = cacheName.getPrefix().concat(key);
    Long result = setOps.remove(cacheKey, values);
    if (cacheName.getExpiration() > 0) {
        redisTemplate.expire(cacheKey, cacheName.getExpiration(), TimeUnit.SECONDS);
    }
    return result;
}


@Override
public Set sGetAll(CacheUtils.CacheName cacheName, String key) {
    if (cacheName.getType() != CacheUtils.CacheType.S) {
        return null;
    }
    String cacheKey = cacheName.getPrefix().concat(key);
    return setOps.members(cacheKey);
}

@Override
public Set zGet(CacheUtils.CacheName cacheName, String key, Pageable pageable, boolean isAsc) {
    if (cacheName.getType() != CacheUtils.CacheType.Z) {
        return null;
    }
    long start = pageable.getOffset();
    long end = pageable.getOffset() + pageable.getPageSize() - 1;
    if (isAsc) {
        return zSetOps.range(cacheName.getPrefix().concat(key), start, end);
    } else {
        return zSetOps.reverseRange(cacheName.getPrefix().concat(key), start, end);
    }
}

@Override
@SuppressWarnings("unchecked")
public Set zGetByScore(CacheUtils.CacheName cacheName, String key, boolean includeMin, Double minScore, boolean includeMax, Double maxScore, Pageable pageable, boolean isAsc) {
    if (cacheName.getType() != CacheUtils.CacheType.Z) {
        return null;
    }

    RedisZSetCommands.Range range = RedisZSetCommands.Range.range();
    if(minScore != null){
        if(includeMin){
            range.gte(minScore);
        }else{
            range.gt(minScore);
        }
    }

    if(maxScore != null){
        if(includeMax){
            range.lte(maxScore);
        }else{
            range.lt(maxScore);
        }
    }

    RedisZSetCommands.Limit limit = RedisZSetCommands.Limit.limit();
    limit.offset(pageable.getOffset());
    limit.count(pageable.getPageSize());

    RedisSerializer keySerializer = redisTemplate.getKeySerializer();
    byte[] rawKey = keySerializer.serialize(cacheName.getPrefix().concat(key));
    Set rawValues;
    if (isAsc) {
        rawValues = redisTemplate.execute(new RedisCallback>() {
            public Set doInRedis(RedisConnection connection) {
                return connection.zRangeByScore(rawKey, range, limit);
            }
        }, true);
    } else {
        rawValues = redisTemplate.execute(new RedisCallback>() {
            public Set doInRedis(RedisConnection connection) {
                return connection.zRevRangeByScore(rawKey, range, limit);
            }
        }, true);
    }
    RedisSerializer valueSerialize = redisTemplate.getValueSerializer();
    return SerializationUtils.deserialize(rawValues, valueSerialize);
}



@Override
public Boolean zPut(CacheUtils.CacheName cacheName, String key, Object value, double score) {
    if (cacheName.getType() != CacheUtils.CacheType.Z) {
        return Boolean.FALSE;
    }
    String cacheKey = cacheName.getPrefix().concat(key);
    Boolean result = zSetOps.add(cacheKey, value, score);
    if (cacheName.getExpiration() > 0) {
        redisTemplate.expire(cacheKey, cacheName.getExpiration(), TimeUnit.SECONDS);
    }
    return result;
}


@Override
public Long lRightPush(CacheUtils.CacheName cacheName, String key, Object... values) {
    if (CacheUtils.CacheType.L != cacheName.getType()) {
        return 0L;
    }
    if (CollectionUtilPlus.isNullOrEmptyArray(values)) {
        return 0L;
    }
    String cacheKey = cacheName.getPrefix().concat(key);
    Long result = listOps.rightPushAll(cacheKey, values);
    if (cacheName.getExpiration() > 0) {
        redisTemplate.expire(cacheKey, cacheName.getExpiration(), TimeUnit.SECONDS);
    }
    return result;
}

@Override
public Long lLeftPush(CacheUtils.CacheName cacheName, String key, Object... values) {
    if (CacheUtils.CacheType.L != cacheName.getType()) {
        return 0L;
    }
    if (CollectionUtilPlus.isNullOrEmptyArray(values)) {
        return 0L;
    }
    String cacheKey = cacheName.getPrefix().concat(key);
    Long result = listOps.leftPushAll(cacheKey, values);
    if (cacheName.getExpiration() > 0) {
        redisTemplate.expire(cacheKey, cacheName.getExpiration(), TimeUnit.SECONDS);
    }
    return result;
}

@Override
public void lRemove(CacheUtils.CacheName cacheName, String key, Object... values) {
    if (CacheUtils.CacheType.L != cacheName.getType()) {
        return;
    }
    if (CollectionUtilPlus.isNullOrEmptyArray(values)) {
        return;
    }

    String cacheKey = cacheName.getPrefix().concat(key);
    for (Object value : values) {
        listOps.remove(cacheKey, 0, value);
    }
    if (cacheName.getExpiration() > 0) {
        redisTemplate.expire(cacheKey, cacheName.getExpiration(), TimeUnit.SECONDS);
    }
}

@Override
public Object lLeftBlockPop(CacheUtils.CacheName cacheName, String key, long timeout, TimeUnit unit) {
    if (cacheName.getType() != CacheUtils.CacheType.L) {
        return null;
    }
    String cacheKey = cacheName.getPrefix().concat(key);
    Object obj = listOps.leftPop(cacheKey, timeout, unit);
    return obj;
}

@Override
public Object lLeftPop(CacheUtils.CacheName cacheName, String key) {
    String cacheKey = cacheName.getPrefix().concat(key);
    Object value = listOps.leftPop(cacheKey);
    return value;
}


@Override
public void removeKey(CacheUtils.CacheName cacheName, String... keys) {
    List cacheKeys = new ArrayList<>();
    for (String key : keys) {
        cacheKeys.add(cacheName.getPrefix().concat(key));
    }
    redisTemplate.delete(cacheKeys);
}


@Override
public Boolean existsKey(CacheUtils.CacheName cacheName, String key) {
    String cacheKey = cacheName.getPrefix().concat(key);
    Boolean result = redisTemplate.hasKey(cacheKey);
    return result;
}


@Override
public Object hGet(CacheUtils.CacheName cacheName, String key, String field) {
    if (cacheName.getType() != CacheUtils.CacheType.H) {
        return null;
    }
    return hashOps.get(cacheName.getPrefix().concat(key), field);
}

@Override
public void hPut(CacheUtils.CacheName cacheName, String key, String field, Object value) {
    if (cacheName.getType() != CacheUtils.CacheType.H) {
        return;
    }
    String cacheKey = cacheName.getPrefix().concat(key);
    hashOps.put(cacheKey, field, value);
    if (cacheName.getExpiration() > 0) {
        redisTemplate.expire(cacheKey, cacheName.getExpiration(), TimeUnit.SECONDS);
    }
}}

还有许多spring-data-redis的实现方法,暂时未贴出。但是大概的使用方式,及思路都是一样的。可以按照现在的方式去自己实现想要的接口。

你可能感兴趣的:(Redis 数据类型 和 spring-data-redis使用实例)