Redis简介
Redis(Remote Dictionary Server)是一个开源的高性能键值对(Key-Value)数据库。它通常用作数据结构服务器,因为除了基本的字符串键值对存储之外,它还支持更复杂的数据结构,如哈希、列表、集合、有序集合、位图、超日志和地理空间索引等。
以下是Redis的一些关键特性和优势:
-
内存存储:Redis将所有数据存储在内存中,这使得它能够提供极高的读写速度。
-
持久化:虽然Redis是内存数据库,但它提供了持久化功能,可以将内存中的数据保存到磁盘,以防系统故障导致数据丢失。
-
支持数据结构:Redis支持丰富的数据结构,包括字符串、列表、集合、有序集合、散列、位图、超日志和地理空间索引等。
-
原子操作:Redis的所有操作都是原子的,这意味着它们可以在并发环境下安全地执行,而不会出现竞态条件。
-
发布/订阅:Redis提供了发布/订阅功能,允许客户端订阅频道以接收消息,这对于实现消息系统非常有用。
-
事务:Redis支持事务,可以通过MULTI和EXEC命令将多个操作组合成一个事务执行。
-
Lua脚本:Redis允许用户使用Lua脚本在服务器端执行复杂的逻辑。
-
高可用:Redis提供了主从复制和哨兵系统来提高数据的可用性和容错能力。
-
分布式:Redis支持分布式数据存储,可以通过Redis Cluster实现数据的自动分片和高可用。
-
性能:Redis的性能非常高,可以处理大量的并发请求,是许多实时应用程序的理想选择。
-
简单易用:Redis有一个简单的客户端和服务器协议,客户端库丰富,易于使用。
-
灵活的过期策略:可以为键设置过期时间,支持灵活的过期策略。
springboot整合Redis的Maven依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
application.yml配置
spring:
data:
redis:
#数据库索引
database: 0
#redis 服务器地址
host: 127.0.0.1
#redis 端口
port: 6379
#redis 密码 默认为空
password:
配置redisTemplate
/**
* Redis配置类
*
* @author WangWenXin
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
final RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置key的序列化规则
template.setKeySerializer(new StringRedisSerializer());
// 设置value的序列化规则
template.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
// 设置hash key的序列化规则
template.setHashKeySerializer(new StringRedisSerializer());
// 设置hash value的序列化规则
template.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
template.afterPropertiesSet();
return template;
}
}
为什么要重新配置RedisTemplate的序列化和反序列化?
如果不配置序列化和反序列化策略,RedisTemplate默认使用JDK自带的序列化方式,即使用JDK的ObjectOutputStream进行序列化,使用ObjectInputStream进行反序列化。这种方式的问题是,它会将对象序列化成字节流时,会包含一些额外的信息,如类名、字段名等等,导致存储在Redis中的值非常冗余。
因此,为了更高效地使用Redis存储对象,并且减少存储空间的占用,我们通常需要配置RedisTemplate的序列化和反序列化策略,例如使用JSON或者其他更紧凑的序列化方式。这样可以确保对象能够正确地序列化和反序列化存储到Redis中,并且可以在读取时正常还原成原始对象。
Redis工具类
/**
* Redis 工具类,封装了常用的 Redis 操作方法
*
* @author WangWenXin
*/
@Component
public class RedisUtils {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 设置键值对。
*
* @param key 键
* @param value 值
*/
public void set(String key, Object value) {
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
ops.set(key, value);
}
/**
* 设置键值对,并设置过期时间。
*
* @param key 键
* @param value 值
* @param timeout 过期时间
* @param timeUnit 时间单位(秒、分钟、小时等)
*/
public void set(String key, Object value, long timeout, TimeUnit timeUnit) {
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
ops.set(key, value, timeout, timeUnit);
}
/**
* 如果键不存在,则设置键值对。
*
* @param key 键
* @param value 值
* @return 是否设置成功
*/
public boolean setIfAbsent(String key, Object value) {
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
return ops.setIfAbsent(key, value);
}
/**
* 如果键不存在,则设置键值对,并设置过期时间。
*
* @param key 键
* @param value 值
* @param timeout 过期时间
* @param timeUnit 时间单位(秒、分钟、小时等)
* @return 是否设置成功
*/
public boolean setIfAbsent(String key, Object value, long timeout, TimeUnit timeUnit) {
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
return ops.setIfAbsent(key, value, timeout, timeUnit);
}
/**
* 获取键对应的值。
*
* @param key 键
* @return 值
*/
public Object get(String key) {
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
return ops.get(key);
}
/**
* 删除指定的键。
*
* @param key 键
*/
public void delete(String key) {
redisTemplate.delete(key);
}
/**
* 判断键是否存在。
*
* @param key 键
* @return 是否存在
*/
public boolean exists(String key) {
return redisTemplate.hasKey(key);
}
/**
* 获取键的剩余生存时间。
*
* @param key 键
* @return 剩余生存时间(毫秒)
*/
public Long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.MILLISECONDS);
}
/**
* 设置哈希表中的字段值。
*
* @param key 键
* @param field 字段
* @param value 值
*/
public void hset(String key, String field, Object value) {
HashOperations<String, String, Object> ops = redisTemplate.opsForHash();
ops.put(key, field, value);
}
/**
* 获取哈希表中的字段值。
*
* @param key 键
* @param field 字段
* @return 字段值
*/
public Object hget(String key, String field) {
HashOperations<String, String, Object> ops = redisTemplate.opsForHash();
return ops.get(key, field);
}
/**
* 获取哈希表中的所有字段和值。
*
* @param key 键
* @return 字段和值的映射
*/
public Map<String, Object> hgetAll(String key) {
HashOperations<String, String, Object> ops = redisTemplate.opsForHash();
return ops.entries(key);
}
/**
* 删除哈希表中的字段。
*
* @param key 键
* @param field 字段
*/
public void hdel(String key, String field) {
HashOperations<String, String, Object> ops = redisTemplate.opsForHash();
ops.delete(key, field);
}
/**
* 获取集合中的所有元素。
*
* @param key 键
* @return 元素集合
*/
public Set<Object> sGet(String key) {
SetOperations<String, Object> ops = redisTemplate.opsForSet();
return ops.members(key);
}
/**
* 向集合中添加元素。
*
* @param key 键
* @param value 值
*/
public void sAdd(String key, Object value) {
SetOperations<String, Object> ops = redisTemplate.opsForSet();
ops.add(key, value);
}
/**
* 从集合中删除元素。
*
* @param key 键
* @param value 值
*/
public void sRemove(String key, Object value) {
SetOperations<String, Object> ops = redisTemplate.opsForSet();
ops.remove(key, value);
}
/**
* 获取列表中的所有元素。
*
* @param key 键
* @return 元素列表
*/
public List<Object> lGet(String key) {
ListOperations<String, Object> ops = redisTemplate.opsForList();
return ops.range(key, 0, -1);
}
/**
* 向列表中添加元素。
*
* @param key 键
* @param value 值
*/
public void lPush(String key, Object value) {
ListOperations<String, Object> ops = redisTemplate.opsForList();
ops.leftPush(key, value);
}
/**
* 从列表中删除元素。
*
* @param key 键
* @param value 值
*/
public void lRemove(String key, Object value) {
ListOperations<String, Object> ops = redisTemplate.opsForList();
ops.remove(key, 0, value);
}
/**
* 获取列表中的元素数量。
*
* @param key 键
* @return 元素数量
*/
public long lSize(String key) {
ListOperations<String, Object> ops = redisTemplate.opsForList();
return ops.size(key);
}
/**
* 获取集合中的元素数量。
*
* @param key 键
* @return 元素数量
*/
public long sSize(String key) {
SetOperations<String, Object> ops = redisTemplate.opsForSet();
return ops.size(key);
}
/**
* 获取哈希表中的字段数量。
*
* @param key 键
* @return 字段数量
*/
public long hSize(String key) {
HashOperations<String, String, Object> ops = redisTemplate.opsForHash();
return ops.size(key);
}
/**
* 清空哈希表中的所有字段。
*
* @param key 键
*/
public void hClear(String key) {
HashOperations<String, String, Object> ops = redisTemplate.opsForHash();
ops.delete(key, (String[]) ops.keys(key).toArray(new String[0]));
}
/**
* 清空集合中的所有元素。
*
* @param key 键
*/
public void sClear(String key) {
SetOperations<String, Object> ops = redisTemplate.opsForSet();
ops.remove(key, (Object[]) ops.members(key).toArray());
}
/**
* 清空列表中的所有元素。
*
* @param key 键
*/
public void lClear(String key) {
ListOperations<String, Object> ops = redisTemplate.opsForList();
while (ops.size(key) > 0) {
ops.remove(key, 0, ops.range(key, 0, 0).get(0));
}
}
}
方法说明
基本操作:
set:设置键值对。
set:设置键值对,并设置过期时间。
get:获取键对应的值。
delete:删除指定的键。
exists:判断键是否存在。
getExpire:获取键的剩余生存时间。setIfAbsent:如果键不存在,则设置键值对。
哈希表操作:
hset:设置哈希表中的字段值。
hget:获取哈希表中的字段值。
hgetAll:获取哈希表中的所有字段和值。
hdel:删除哈希表中的字段。
hSize:获取哈希表中的字段数量。
hClear:清空哈希表中的所有字段。集合操作:
sGet:获取集合中的所有元素。
sAdd:向集合中添加元素。
sRemove:从集合中删除元素。
sSize:获取集合中的元素数量。
sClear:清空集合中的所有元素。列表操作:
lGet:获取列表中的所有元素。
lPush:向列表中添加元素。
lRemove:从列表中删除元素。
lSize:获取列表中的元素数量。
lClear:清空列表中的所有元素。