SpringBoot 整合Spring Data Redis
简介:Redis客户端实现方式有Jedis、Spring Data Redis等,而Spring Data Redis是Spring框架提供的,是对Jedis和Lettuce驱动的统一封装,优点如下:
对具体redis客户端做了封装,客户端可在jedis,jredis,rjc等Java客户端中做出选择和切换;
用template对调用做了封装,省去了建立连接,释放连接等繁琐代码;
对对象的序列化也可自由选择工具;
提供对spring cache的支持,可用注解实现Cache,但是无法设定缓存失效时间。
一、Redis基础
1. pom.xml Maven依赖
<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>
2. application.ym文件配置
spring:
redis:
cluster: # 集群版
nodes:
- 172.17.0.1:6379
- 172.17.0.1:6380
- 172.17.0.1:6381
- 172.17.0.2:6379
- 172.17.0.2:6380
- 172.17.0.2:6381
- 172.17.0.3:6379
- 172.17.0.3:6380
- 172.17.0.3:6381
password: 123456
#host: localhost # 单机版
#port: 6379
timeout: 3000 # 连接超时时间(毫秒)
lettuce:
pool:
max-active: 8 # 连接池最大连接数(负值表示没有限制)
max-idle: 8 # 连接池中的最大空闲连接
min-idle: 0 # 连接池中的最小空闲连接
max-wait: -1 # 连接池最大阻塞等待时间(负值表示没有限制)
3. 配置类
@Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); // String序列化 StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // FastJson序列化 FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); redisTemplate.setKeySerializer(stringRedisSerializer); redisTemplate.setValueSerializer(fastJsonRedisSerializer); redisTemplate.setHashKeySerializer(stringRedisSerializer); redisTemplate.setHashValueSerializer(fastJsonRedisSerializer); redisTemplate.setConnectionFactory(redisConnectionFactory); return redisTemplate; } }
4. RedisTemplate用法
A. RedisTemplate是线程安全的,开箱即用;
B. 操作类型
操作字符串:redisTemplate.opsForValue();
字符串set操作方法,如下图,只有这三个,切勿把setRange方法用了;
字符串setRange方法,如下图;
操作散列:redisTemplate.opsForHash();
操作列表:redisTemplate.opsForList();
操作集合:redisTemplate.opsForSet();
操作有序集合:redisTemplate.opsForZSet();
C. 与StringRedisTemplate的区别
StringRedisTemplate继承RedisTemplate类;
StringRedisTemplate默认使用String序列化方式,RedisTemplate默认使用Jdk自带的序列化方式;
两者数据不互通,只能各自管理各自处理过的数据。
5. 序列化器
A. 序列化:目的是为了让对象可以跨平台存储和进行网络传输,因为跨平台存储和进行网络传输方式是IO,而IO支持的数据格式为字节数组,事实上存储和网络传输都需要把一个对象状态保存成一种跨平台识别的字节格式,然后其他的平台可以通过字节信息解析还原对象信息。
B. 序列化器分两类:
RedisSerializer:双向串行器,数据序列化成bute[];
RedisElementReader/RedisElementWriter:元素读写使用,数据变成ByteBuffer;
C. 序列化器实现类(共10种)
StringRedisSerializer(StringRedisTemplate默认系列化方式):String/byte[]转换,速度快;
JdkSerializationRedisSerializer(RedisTemplate默认系列化方式):JDK自带序列化,优点是反序列化不需要提供类型信息(.class对象),缺点是需要实现Serializable接口,且序列化后的结果庞大,是JSON格式的5倍,导致消耗redis大量内存;
Jackson2JsonRedisSerializer:Jackson序列化,需要定义JavaType,优点是速度快,序列化后的字符串短小精悍,不需要实现Serializable接口,缺点是此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class对象),这个只在反序列过程中使用上了;
FastJsonRedisSerializer:FastJson序列化,与Jackson序列化类似。
D. 从Spring Data Redis框架本身的角度看,存放到Redis的数据只是字节,虽然Redis本身支持各种类型,但大部分是指数据存储的方式,而不是它所代表的内容,由用户决定是否将字节转换为字符串或其他对象。
6. 连接池
A. SpringBoot2.0以上是使用Lettuce客户端来连接Redis服务端的,默认不使用Redis连接池的,只有配置lettuce属性时才用上;
B. max-active:连接池最大连接数(负值表示没有限制),超过此限制,不在建立连接,而是等待下一个已有的连接释放使用;
min-idle:连接池中的确保最小空闲连接,即连接池初始化的连接数;
max-idle:连接池中的允许最大空闲连接,当连接数大于min-idle时,需要就建立一个连接,当连接数大于max-idle时但小于max-active时,依然需要就建立一个连接,但是用完后就会关闭;
max-wait:连接池最大阻塞等待时间(负值表示没有限制);
C. 要使用原有的jedis客户端,只需排除Lettuce依赖并引入Jedis依赖,默认是有连接池的,可更改配置参数。
二、核心功能
1. 事务支持
A. Spring Data Redis提供了SessionCallback接口,在同一个连接中需要执行多个操作时使用,与使用Redis事务时一样;
B. @Transactional注解支持,默认是关闭的,需要开启,如果没有错误即成功,有错误就全部回滚。
2. key失效事件监听
A. 监听配置类
package com.ruhuanxingyun.redis.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
/**
* @description: Redis监听配置
* @author: ruphie
* @date: Create in 2020/11/10 21:24
* @company: ruhuanxingyun
*/
@Configuration
public class RedisListenerConfig {
@Bean
RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory) {
RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
return redisMessageListenerContainer;
}
}
B. 自定义监听器
package com.ruhuanxingyun.redis.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
/**
* @description: 监听过期事件__keyevent@*__:expired"
* @author: ruphie
* @date: Create in 2020/11/10 21:27
* @company: ruhuanxingyun
*/
@Component
@Slf4j
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
@Override
public void onMessage(Message message, byte[] pattern) {
String expiredKey = message.toString();
log.info("失效key:" + expiredKey);
}
}
三、Spring整合Redis实现注解缓存
1. 注解
A. @EnableCaching:开启基于注解的缓存;
B. @Cacheable:根据请求参数对结果进行缓存,主要用在方法上
value/cacheNames:缓存的名字;
key:缓存数据使用的key,需写SPEL,默认是使用方法的参数值;
condition:符合指定条件的情况下才缓存;
sync:是否异步处理,默认false;
C. @CachePut:修改缓存;
D. @CacheEvict:清空缓存;
beforeInvocation:是否在方法执行之前清空缓存,默认false;
2. 缓存key的spel表达式
A. 获取被调用的方法名字:#root.methodName | #root.method.name;
B. 当前被调用的目标对象:#root.target;
C. 当前被调用的目标对象类:#root.targetClass;
D. 当前被调用的方法的参数列表:#root.args[0];
E. 当前方法被调用使用的缓存列表:#root.caches[0].name;
F. 参数名a,参数的索引0:#a0;
G. 方法执行后的返回值:#result。
可参考:SpringCache扩展@CacheEvict的key模糊匹配清除