暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

redisTemplate分别存取redis的string/list/set/zset/hash等数据类型

DevHome 2021-01-31
445

01

前言

在springboot项目中我们经常使用redisTemplate来操作Redis,完成对数据的保存与查询。接下来将分别展示对redis的5种数据类型string/list/set/zset/hash的数据的操作。并且对这些数据类型的使用场景作简单分析。欢迎大家留言交流探讨

02

redisTemplate的基本配置

application.yml文件中配置Redis的连接地址:

spring:
## redis 配置
redis:
host: 192.168.28.200
port: 6379
复制

使用redisTemplate需要首先在spring容器中初始化该配置类,配置主要是对key和value序列化的方式进行设定,这里的key和value分别采用string,object的数据类型,key使用string序列化方式,value使用json序列化方式,这样可以基本满足绝大部分的使用场景。配置类如下:

@Configuration
public class RedisTemplateConfig {
@Bean
@Primary
public RedisTemplate<String,Object> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory){
RedisTemplate<String,Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
// key 的序列化方式为 string 序列化方式
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer);
template.setDefaultSerializer(fastJsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
复制

再使用时通过@Autowired 注入redisTemplate 即可;

 @Autowired
private RedisTemplate<String,Object> redisTemplate;
复制

03

不同数据类型的保存与获取

1)

string

Redis最基本的数据类型,是一个单独的字符串,设定key value即可,比如key是“country” value是 “中华人民共和国”。使用redisTemplate.opsForValue() 使用set(key,value) get(key)即可。我们来看下java代码:

redisTemplate.opsForValue().set(RedisConstantKey.MY_REDIS_VALUE.key,"中华人民共和国");
Object o = redisTemplate.opsForValue().get(RedisConstantKey.MY_REDIS_VALUE.key);
if(Objects.nonNull(o)){
System.out.println(o.toString());
}
复制

2)

List

类似Java中的list列表,可以完成对一个数组数据的存储,获取时也可以根据索引获取

比如我们的key为编程语言language,value为  {"java","c++","python","js"}等一些列具体的编程语言,类似这样的数据结构就非常适合用list来存储,我们来看下用redisTemplate如何操作:

 public void setRedisList(){
List<Object> language = Lists.newArrayList("java","c++","python","js");
redisTemplate.opsForList().leftPushAll(RedisConstantKey.MY_REDIS_LIST.key,language);
}
public void getRedisList(){
List<Object> languageList = redisTemplate.opsForList().range(RedisConstantKey.MY_REDIS_LIST.key, 0, -1);
// 可以直接转换成string
if(CollectionUtils.isNotEmpty(languageList)){
List<String> languageStrs = languageList.stream().map(String::valueOf).collect(Collectors.toList());
System.out.println("遍历输出到表中!");
languageStrs.forEach(System.out::println);
}
}


遍历输出到表中!
js
python
c++
java
复制

使用opsForList这个api操作list,入库的时候可以leftPush 也可以rightPush,取出的时候使用range(),后面的索引0 为从最左边开始的索引,-1 为最右边开始的索引,0,-1 代表取出列表中的所有数据。从左边插入过程如下所示:-> java;  ->  c++ -> java;   -> python  ->  c++ -> java;    js -> python  ->  c++ -> java;   所以最后的列表就是:  js -> python  ->  c++ -> java。那么取出来之后就是上述结果。

3)

set

set集合类似数学中的集合,是不能有重复数据的,这和Java中的Set数据结构也是一致的,如果后面插入了和前面相同的数据,则会自动去重。我们来看下redisTemplate的操作示例,这里使用的是redisTemplate.opsForSet(), 取出数据时,可以直接使用members()取出所有的数据 ,通过输出打印,我们发现存入的两个aa 输出时只有一个了,已经被自动去重了。

/**
* 无序集合,不可重复
*/
public void setRedisSet(){
redisTemplate.opsForSet().add(RedisConstantKey.MY_REDIS_SET.key,"aa");
redisTemplate.opsForSet().add(RedisConstantKey.MY_REDIS_SET.key,"bb");
redisTemplate.opsForSet().add(RedisConstantKey.MY_REDIS_SET.key,"cc");
// 这里加入一个重复的值,set集合自动去重
redisTemplate.opsForSet().add(RedisConstantKey.MY_REDIS_SET.key,"aa");
}
public void getRedisSet(){
Set<Object> members = redisTemplate.opsForSet().members(RedisConstantKey.MY_REDIS_SET.key);
Iterator<Object> it = members.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
result:
bb
cc
aa
复制

4)

zset

有时候我们需要存储一个有序的集合,比如大学的排名等,这个排行榜可能随时刷新,使用redis的有序集合来存储是非常合适的。redisTemplate.opsForZset()api 就是专门用来操作有序集合的。它排序的规则是根据入库的分数来计算的,在数据库里的存储顺序按照分数从小到大的顺序进行排序。取出的时候可以按照分数段区间取出,也可以按照正序或者倒序的顺序取出,比如示例代码里面获取排行榜前三位和后三位的学校。

public void setRedisZset(){
redisTemplate.opsForZSet().add(RedisConstantKey.MY_REDIS_ZSET.key,"Harvard大学",100);
redisTemplate.opsForZSet().add(RedisConstantKey.MY_REDIS_ZSET.key,"中山大学",80);
redisTemplate.opsForZSet().add(RedisConstantKey.MY_REDIS_ZSET.key,"清华大学",98);
redisTemplate.opsForZSet().add(RedisConstantKey.MY_REDIS_ZSET.key,"北京大学",99);
redisTemplate.opsForZSet().add(RedisConstantKey.MY_REDIS_ZSET.key,"复旦大学",87);
redisTemplate.opsForZSet().add(RedisConstantKey.MY_REDIS_ZSET.key,"上海大学",76);
redisTemplate.opsForZSet().add(RedisConstantKey.MY_REDIS_ZSET.key,"西藏大学",63);
}
public void getRedisZset(){
Set<Object> range1 = redisTemplate.opsForZSet().rangeByScore(RedisConstantKey.MY_REDIS_ZSET.key, 90, 100);
range1.forEach((v) -> System.out.println("90分以上的大学: "+v));
System.out.println("=====================================================");
Set<Object> range2 = redisTemplate.opsForZSet().rangeByScore(RedisConstantKey.MY_REDIS_ZSET.key, 80, 100);
range2.forEach((v) -> System.out.println("80分以上的大学: "+v));
System.out.println("=====================================================");
Set<Object> range3 = redisTemplate.opsForZSet().rangeByScore(RedisConstantKey.MY_REDIS_ZSET.key, 0, 100);
range3.forEach((v) -> System.out.println("60分以上的大学: "+v));
System.out.println("排名后三位的大学:::");
Set<Object> rank = redisTemplate.opsForZSet().range(RedisConstantKey.MY_REDIS_ZSET.key, 0, 2);
rank.forEach(System.out::println);
System.out.println("排名前三位的大学:::");
Set<Object> rank2 = redisTemplate.opsForZSet().reverseRange(RedisConstantKey.MY_REDIS_ZSET.key, 0, 2);
rank2.forEach(System.out::println);
}

result:
90分以上的大学: 清华大学
90分以上的大学: 北京大学
90分以上的大学: Harvard大学
=====================================================
80分以上的大学: 中山大学
80分以上的大学: 复旦大学
80分以上的大学: 清华大学
80分以上的大学: 北京大学
80分以上的大学: Harvard大学
=====================================================
60分以上的大学: 西藏大学
60分以上的大学: 上海大学
60分以上的大学: 中山大学
60分以上的大学: 复旦大学
60分以上的大学: 清华大学
60分以上的大学: 北京大学
60分以上的大学: Harvard大学
排名后三位的大学:::
西藏大学
上海大学
中山大学
排名前三位的大学:::
Harvard大学
北京大学
清华大学
本次请求的时间为:23
复制

5)

hash

hash 是一个string 类型的 field 和 value的映射表,hash特别适合于存储对象。使用redisTemplate.opsForHash()这个api分别存入多个字段。取出的时候可以使用entries()取出所有的字段,也可以根据需要取出该key下面的特定field的value,直接使用get()api即可,具体参考下面的示例代码:

 public void setRedisHash(){
Map<String,String> nameAgeMap = new HashMap<>();
nameAgeMap.put("name","alice");
nameAgeMap.put("address","beijing");
nameAgeMap.put("age","18");
redisTemplate.opsForHash().putAll(RedisConstantKey.MY_REDIS_HASH.key,nameAgeMap);
}

public void getRedisHash(){
Map<Object,Object> nameAgeMap = redisTemplate.opsForHash().entries(RedisConstantKey.MY_REDIS_HASH.key);
nameAgeMap.forEach((k,v)->{
System.out.println("k==="+k+"v==="+v);
});
Object o = redisTemplate.opsForHash().get(RedisConstantKey.MY_REDIS_HASH.key,"name");
System.out.println("name是:"+o);
}

result:
k===:address v===:beijing
k===:name v===:alice
k===:age v===:18
name是:alice
复制

04

小结

针对redis中经常使用到的string、list、set、zset、hash 等5种数据类型分别进行归纳分析,在实际项目中,首先应该分析业务场景找到最适合的数据结构类型再进行存储,这样往往可以达到事半功倍的效果。在Java项目中使用redisTemplate可以方便的实现对这5种数据类型的保存与获取(查询)。文章也提到了这些数据类型的常见使用场景。



扫二维码|关注我们

文章转载自DevHome,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论