介绍
在SpringBoot中一般使用RedisTemplate提供的方法来操作Redis
SpringBoot 2.x后 ,原来底层使用的 Jedis 被 lettuce[赖忒死] 替换。所以在springboot中引入spring-boot-starter-data-redis
依赖时,默认使用的时Lettuce。
- jedis:采用的直连,多个线程操作的话,是不安全的。如果要避免不安全,使用jedis pool连接池!更像BIO模式(阻塞模式)。
- lettuce:采用netty(高性能网络框架,异步请求),实例可以在多个线程中共享,不存在线程不安全的情况!可以减少线程数量了,更像NIO模式。
而我们要是使用的是StringRedisTemplate 而不是 RedisTemplate
StringRedisTemplate是RedisTemplate的子类(不代表value只能是string,而是序列化策略为StringRedisSerializer)
- RedisTemplate默认采用的是JDK的序列化策略,即JdkSerializationRedisSerializer,保存的key和value都是采用此策略序列化保存的。比如说存入数据会将数据先序列化成字节数组然后在存入Redis数据库,这个时候打开Redis查看的时候,你会看到你的数据不是以可读的形式展现的,而是以字节数组显示,类似下面,当然从Redis获取数据的时候也会默认将数据当做字节数组转化。
- StringRedisTemplate的API假定所有的数据类型化都是字符类型,即key和value都是字符串类型。默认采用的是String的序列化策略,即StringRedisSerializer,保存的key和value都是采用此策略序列化保存的。
作用
redis连接数据库,可以实现排行榜(有序集合),缓存(字符串类型)等功能
快速开始
导入依赖
<!--redis场景启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redis 连接池 -->
<!--新版本连接池lettuce-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
配置文件
#****************************redis****************************
# Redis数据库索引(默认为0)
redis:
database:
# 默认库
default: 0
# 缓存库
cache: 1
# 排行榜库
sort: 2
# 搜索历史的库
history: 3
spring:
redis:
host: 127.0.0.1
lettuce:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 20
# 连接池中的最大空闲连接
max-idle: 10
# 连接池中的最小空闲连接
min-idle: 5
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: 5000
# Redis服务器连接密码(默认为空,代表没有密码)
password: 10401
# Redis服务器连接端口
port: 6379
# 连接超时时间(毫秒)
timeout: 5000
配置类
import io.lettuce.core.resource.DefaultClientResources;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.ObjectUtils;
import java.time.Duration;
@Configuration
public class RedisConfig {
@Value("${redis.database.default}")
private int defaultDataBase;
@Value("${redis.database.sort}")
private int sortDataBase;
@Value("${redis.database.cache}")
private int drugCacheDataBase;
@Value("${redis.database.history}")
private int historyDataBase;
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.lettuce.pool.max-active}")
private int maxActive;
@Value("${spring.redis.lettuce.pool.max-wait}")
private int maxWait;
@Value("${spring.redis.lettuce.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.lettuce.pool.min-idle}")
private int minIdle;
@Value("${spring.redis.timeout}")
private long timeout;
/**
* 配置redis连接池
*/
@Bean
public GenericObjectPoolConfig poolConfig() {
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxTotal(maxActive);
poolConfig.setMaxIdle(maxIdle);
poolConfig.setMinIdle(minIdle);
poolConfig.setMaxWaitMillis(maxWait);
return poolConfig;
}
/**
* 配置默认客户端资源
*/
@Bean("defaultClientResources")
public DefaultClientResources getDefaultClientResources(){
return DefaultClientResources.create();
}
private StringRedisTemplate getStringRedisTemplate(int database, GenericObjectPoolConfig poolConfig, DefaultClientResources defaultClientResources) {
// 构建工厂对象
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(host);
config.setPort(port);
if (!ObjectUtils.isEmpty(password)) {
RedisPassword redisPassword = RedisPassword.of(password);
config.setPassword(redisPassword);
}
LettucePoolingClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
.commandTimeout(Duration.ofSeconds(timeout))
.poolConfig(poolConfig)
.clientResources(defaultClientResources)
.build();
LettuceConnectionFactory factory = new LettuceConnectionFactory(config, clientConfig);
// 设置使用的redis数据库
factory.setDatabase(database);
// 重新初始化工厂
factory.afterPropertiesSet();
return new StringRedisTemplate(factory);
}
@Bean(name="redisTemplateDefault")
public StringRedisTemplate redisTemplateDefault(GenericObjectPoolConfig poolConfig,
@Qualifier("defaultClientResources") DefaultClientResources defaultClientResources) {
return getStringRedisTemplate(defaultDataBase, poolConfig,defaultClientResources);
}
@Bean(name="redisTemplateSort")
public StringRedisTemplate redisTemplateSort(GenericObjectPoolConfig poolConfig,
@Qualifier("defaultClientResources") DefaultClientResources defaultClientResources) {
return getStringRedisTemplate(sortDataBase, poolConfig,defaultClientResources);
}
@Bean(name="redisTemplateDrugCache")
public StringRedisTemplate redisTemplateCacheDrug(GenericObjectPoolConfig poolConfig,
@Qualifier("defaultClientResources") DefaultClientResources defaultClientResources) {
return getStringRedisTemplate(drugCacheDataBase, poolConfig,defaultClientResources);
}
@Bean(name="redisTemplateHistory")
public StringRedisTemplate redisTemplateHistory(GenericObjectPoolConfig poolConfig,
@Qualifier("defaultClientResources") DefaultClientResources defaultClientResources) {
return getStringRedisTemplate(historyDataBase, poolConfig,defaultClientResources);
}
}
一总往Spring容器注入了四个StringRedisTemplate对象,分别对应操作不同的库
使用
指定名称的从IOC容器获取,因为配置了多个对象
@Resource(name = "redisTemplateDefault")
private StringRedisTemplate stringRedisTemplate;