Redis的常用数据类型的操作
Java环境说明
# 基本环境
JDK: 1.8_231
IDE: IDEA
SpringBoot: 2.3.8.RELEASE
Redis:3.0.504
Maven配置:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.51</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
RedisTemplate设置
RedisTemplate Bean配置
package com.study.redisdemo.config;
import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* Redis配置
*/
@Configuration
public class RedisTemplateConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
// 指定序列化器
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(keySerializer());
redisTemplate.setHashKeySerializer(keySerializer());
redisTemplate.setValueSerializer(valueSerializer());
redisTemplate.setHashValueSerializer(valueSerializer());
// 默认序列号
redisTemplate.setDefaultSerializer(keySerializer());
return redisTemplate;
}
/**
* 使用String类型作为Redis键的序列号器
* @return
*/
private RedisSerializer<String> keySerializer(){
return new StringRedisSerializer();
}
/**
* 使用Fastjson序列化器
* 国内还是使用fastjson习惯一些
* @return
*/
private RedisSerializer<Object> valueSerializer(){
return new GenericFastJsonRedisSerializer();
}
}
application.properties配置
server.port=8001
spring.application.name=redisdemo
################ Redis 配置 ##############
# Redis数据库索引(默认0)
spring.redis.database=0
#redis服务器地址
spring.redis.host=localhost
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接超时时间(毫秒)
spring.redis.timeout=6000
#Lettuce 是一个可伸缩线程安全的 Redis 客户端,多个线程可以共享同一个 RedisConnection,它利用优秀 netty NIO 框架来高效地管理多个连接
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.lettuce.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.lettuce.pool.min-idle=0
# 关闭超时时间
spring.redis.lettuce.shutdown-timeout=100
字符串类型
简介:
字符串对象的内部编码有3种 :int
、raw
和embstr
。Redis会根据当前值的类型和长度来决定使用哪种编码来实现。
直接上代码:
@Autowired
RedisTemplate redisTemplate;
/**
* 字符串类型
*/
@Test
public void stringDemo() {
// 未设置过期时间
redisTemplate.opsForValue().set("user:123456:token", UUID.randomUUID());
// 短信验证码,设置过期时间为1分钟
redisTemplate.opsForValue().set("user:123456:smscode","666666",1, TimeUnit.MINUTES);
// 读取结果
String token = Optional.ofNullable(redisTemplate.opsForValue().get("user:123456:token")).orElse("").toString();
String smscode = Optional.ofNullable(redisTemplate.opsForValue().get("user:123456:smscode")).orElse("").toString();
log.info("token:{},smscode:{}",token,smscode);
// 存储对象
UserInfo userInfo = new UserInfo("123456","大熊","男",new Date());
redisTemplate.opsForValue().set("user:123456",userInfo);
// 读取对象
UserInfo resUserInfo =(UserInfo) Optional.ofNullable(redisTemplate.opsForValue().get("user:123456")).orElse(new UserInfo());
log.info("userinfo:{}",resUserInfo);
}
使用Redis Desktop Manager查看数据存储情况
普通字符串:
对象序列号的JSON字符串:
hash类型
简介:
哈希对象用来存储一组数据对。每个数据对又包含键值两部分。
哈希对象也有两种实现方式:
- ziplist(压缩列表)
- hashtable(哈希表)
只有当存储的数据量比较小的情况下,Redis 才使用压缩列表来实现哈希对象。具体需要满足两个条件:
- 字典中保存的键和值的大小都要小于 64 字节;
- 字典中键值对的个数要小于 512 个。
当不能同时满足上面两个条件的时候,Redis 就使用哈希表来实现哈希对象。
代码:
/**
* hash数据类型
*/
@Test
public void hashDemo() {
// 保存hash键值对
redisTemplate.opsForHash().put("car:audi","model","RS6");
redisTemplate.opsForHash().put("car:audi","color","blue");
redisTemplate.opsForHash().put("car:audi","length","4.8m");
// 多少个键值
Long size = redisTemplate.opsForHash().size("car:audi");
log.info("size={}",size);
// 判断是否存某个key
boolean flag = redisTemplate.opsForHash().hasKey("car:audi","model");
if (flag) {
// 获取单个键的值
log.info("model={}",redisTemplate.opsForHash().get("car:audi","model"));
}
// 获取所有的keys
Set<String> keys = redisTemplate.opsForHash().keys("car:audi");
log.info("keys={}",keys);
// 获取多个值
List<String> values = redisTemplate.opsForHash().values("car:audi");
log.info("values={}",values);
}
输出:
com.study.redisdemo.RedisTest : size=3
com.study.redisdemo.RedisTest : model=RS6
com.study.redisdemo.RedisTest : keys=[model, color, length]
com.study.redisdemo.RedisTest : values=[RS6, blue, 4.8m]
列表类型
列表简介:列表(list)类型是用来存储多个有序的字符串,列表中的每个字符串称为元素(element),一个列表最多可以存储232-1个元素。在Redis中,可以对列表两端插入(push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下标的元素等。列表是一种比较灵活的数据结构,它可以充当栈和队列的角色,在实际开发上有很多应用场景。
列表类型有两个特点:
- 列表中的元素是有序的,这就意味着可以通过索引下标获取某个元素或者某个范围内的元素列表。
- 列表中的元素可以是重复的.
代码:
/**
* 数据类型:列表
*/
@Test
public void listDemo() {
String key = "books";
// 左侧入列表
redisTemplate.opsForList().leftPush(key,"Java In Action");
redisTemplate.opsForList().leftPush(key,"SQL 宝典");
redisTemplate.opsForList().leftPush(key,"演员的自我修养");
// 列表大小
Long size = redisTemplate.opsForList().size(key);
System.out.println("Size="+size);
// 根据索引获取元素
Object object = redisTemplate.opsForList().index(key,1);
System.out.println(object);
// 遍历列表
System.out.println("===遍历列表===");
List<String> list = redisTemplate.opsForList().range(key,0,-1);
list.forEach(str -> {
System.out.println(str);
});
}
使用列表模式实现队列
思路:队列主要是有序,并且先进先出,所以可以使用rpush插入队列(生产),使用lpop左侧弹出(消费)。相对的,使用lpush和rpop也可以。
/**
* 数据类型:列表模拟队列
*/
@Test
public void listQueueDemo() {
String key = "message";
// 右侧入队列
redisTemplate.opsForList().rightPush(key,"OK1");
redisTemplate.opsForList().rightPush(key,"OK2");
redisTemplate.opsForList().rightPush(key,"OK3");
// 左侧弹出(消费)
Object message = redisTemplate.opsForList().leftPop(key);
System.out.println("第一条消息:"+message);
message = redisTemplate.opsForList().leftPop(key);
System.out.println("第二条消息:"+message);
}
集合Set(无序)
集合set类型是用来保存多个字符串元素,但是和列表类型不一样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过下标获取元素。Redis除了支持集合内的增删改查外,还同时支持多个集合取交集、并集、差集,合理的使用好集合类型,能在实际开发中解决很多实际问题。
/**
* 集合Set类型
*/
@Test
public void setDemo() {
String key = "user:123456:mark";
// 塞入值
redisTemplate.opsForSet().add(key,"Java","后端");
redisTemplate.opsForSet().add(key,"Java");
// 集合大小
Long size = redisTemplate.opsForSet().size(key);
System.out.println("集合大小:" + size);
// 判断元素是否存在
boolean flag = redisTemplate.opsForSet().isMember(key,"Java");
System.out.println("元素是否存在:"+flag);
// 返回所有元素
System.out.println("返回所有元素");
Set<Object> objects = redisTemplate.opsForSet().members(key);
objects.forEach(s->{
System.out.println(s);
});
}
集合ZSet(有序)
有序集合相对于哈希、列表、集合来说有一点点陌生,它保留了集合不能有重复成员的特性,但不同的是,有序集合中的元素可以排序。但是和列表使用的索引下标作为排序依据不同,它给每个元素设置一个分数(score)作为排序的依据。
应用场景:
- 排行榜
- 社交
有序集合内的元素不可以重复,但分数可以重复
/**
* 有序集合ZSet
*/
@Test
public void zSetDemo() {
String key = "user:ranking";
redisTemplate.opsForZSet().add(key,"大熊",100);
redisTemplate.opsForZSet().add(key,"胖虎",88);
redisTemplate.opsForZSet().add(key,"静香",101);
// 顺序
System.out.println("===顺序===");
Set<Object> objects = redisTemplate.opsForZSet().rangeByScore(key,0,150);
objects.forEach(obj -> {
System.out.println(obj);
});
// 倒序
System.out.println("===倒序===");
Set<Object> reverseObjects = redisTemplate.opsForZSet().reverseRangeByScore(key,0,150);
reverseObjects.forEach(obj -> {
System.out.println(obj);
});
}
输出:
===顺序===
胖虎
大熊
静香
===倒序===
静香
大熊
胖虎