文章目录
我使用的版本是SpringBoot 2.6.4
可以实现注入不同的库连接或是动态切换库
依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.4</version>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Jedis配置
spring:
redis:
# open自定义的,使用aop切面控制
open: false # 是否开启redis缓存 true开启 false关闭
database: 0
host: 127.0.0.1
password: 123456
# history 自定义,切换库索引
history: 1 #历史数据使用的库
port: 6379
timeout: 6000ms # 连接超时时长(毫秒)
jedis:
pool:
max-active: 1000 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 10 # 连接池中的最大空闲连接
min-idle: 5 # 连接池中的最小空闲连接
使用lettuce配置 推荐使用,也是springboot默认的
redis:
database: 0
host: 127.0.0.1
port: 6379
password: # 密码(默认为空)
timeout: 60000 # 连接超时时长(毫秒)
jedis:
pool:
max-active: 100 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 10 # 连接池中的最大空闲连接
min-idle: 5 # 连接池中的最小空闲连接
enabled: false
lettuce:
pool:
enabled: true
max-active: 100
max-wait: -1
max-idle: 10
min-idle: 5
shutdown-timeout: 100
jedis配置类, 默认0号库使用@Autowired注入,自定义库使用@Resource(name = “history”)注入
动态切库有个问题就是一旦切库 后面的数据就会一直保存在切换的库里面,比如实时数据需要保存在1号库,历史数据需要保存在2号库,切库后 实时的就会存历史里面、下面这种配置,想用哪个库就注入哪个库,不存在切库问题
import org.springframework.beans.factory.annotation.Autowired;
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.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/**
* Redis配置
*/
@Configuration
public class RedisConfig {
@Autowired
private RedisConnectionFactory factory;
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private Integer port;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.history}")
private Integer history;
/**
* 实时数据库 配置 默认0号库
*/
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 解决value不能转成string chens 2022-06-08
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.setConnectionFactory(factory);
return template;
}
/**
* redis历史数据库 配置 根据yml配置库
*/
@Bean("history")
public RedisTemplate<String, Object> redisTemplatetwo() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 解决value不能转成string
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
// 建立连接,设置库索引
redisStandaloneConfiguration.setDatabase(history);
redisStandaloneConfiguration.setHostName(host);
redisStandaloneConfiguration.setPort(port);
redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
LettuceConnectionFactory factory = new LettuceConnectionFactory(redisStandaloneConfiguration, LettuceClientConfiguration.builder()
// 超时时间
.commandTimeout(Duration.ofMinutes(30)).build());
factory.afterPropertiesSet();
template.setConnectionFactory(factory);
return template;
}
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
@Bean
public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
return redisTemplate.opsForValue();
}
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
}
工具类,setDbIndex()动态切换库,方法调用完成应切回默认库
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
* <p>
* https://www.renren.io
* <p>
* 版权所有,侵权必究!
*/
package common.redis;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import common.server.hss.entity.HssRealtimeEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* Redis工具类
*
* @author Mark sunlightcs@gmail.com
*/
@Component
public class RedisUtils {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private ValueOperations<String, String> valueOperations;
@Autowired
private HashOperations<String, String, Object> hashOperations;
@Autowired
private ListOperations<String, Object> listOperations;
@Autowired
private SetOperations<String, Object> setOperations;
@Autowired
private ZSetOperations<String, Object> zSetOperations;
// 默认数据库
private static Integer database = 0;
/**
* 默认过期时长,单位:秒
*/
public final static long DEFAULT_EXPIRE = 60 * 60 * 24;
/**
* 不设置过期时长
*/
public final static long NOT_EXPIRE = -1;
private final static Gson gson = new Gson();
public void set(String key, Object value, long expire) {
valueOperations.set(key, toJson(value));
if (expire != NOT_EXPIRE) {
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
}
public void set(String key, Object value, int expire, TimeUnit unit) {
valueOperations.set(key, toJson(value));
if (expire != NOT_EXPIRE) {
redisTemplate.expire(key, expire, unit);
}
}
public void set(Integer index, String key, Object value, long expire) {
setDbIndex(index);
valueOperations.set(key, toJson(value));
if (expire != NOT_EXPIRE) {
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
}
public void set(String key, Object value) {
set(key, value, DEFAULT_EXPIRE);
}
public void set(Integer index, String key, Object value) {
setDbIndex(index);
set(key, value, DEFAULT_EXPIRE);
}
public <T> T get(String key, Class<T> clazz, long expire) {
String value = valueOperations.get(key);
if (expire != NOT_EXPIRE) {
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
return value == null ? null : fromJson(value, clazz);
}
public <T> T get(Integer index, String key, Class<T> clazz, long expire) {
setDbIndex(index);
String value = valueOperations.get(key);
if (expire != NOT_EXPIRE) {
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
return value == null ? null : fromJson(value, clazz);
}
// 获取实时数据集合 非批量 chens
public <T> List<T> getList(List<String> keys, Class<T> clazz) {
List<T> list = new LinkedList<>();
if (keys.size() < 1) return list;
for (String key : keys) {
T t = get(key, clazz, NOT_EXPIRE);
if (t != null) {
list.add(t);
}
}
//keys.forEach(i -> list.add(get(i, clazz, NOT_EXPIRE)));
return list;
}
// 批量获取数据 chens
public <T> List<T> getbatchList(List<String> keys, Class<T> clazz) {
List<Object> list = redisTemplate.executePipelined(new SessionCallback<Map>() {
@Override
public <K, V> Map execute(RedisOperations<K, V> operations) throws DataAccessException {
ValueOperations<K, V> value = operations.opsForValue();
keys.forEach(i -> value.get(i));
return null;
}
});
list.removeAll(Collections.singleton(null));
List<T> res = new ArrayList<>();
for (Object obj : list) {
// 实体传入错误导致不能转换 返回空值
try {
T bean = BeanUtil.toBean(obj, clazz);
res.add(bean);
} catch (Exception e) {
return res;
}
}
return res;
}
public Boolean contains(String key) {
return redisTemplate.hasKey(key);
}
public <T> T get(String key, Class<T> clazz) {
return get(key, clazz, NOT_EXPIRE);
}
public <T> T get(Integer index, String key, Class<T> clazz) {
setDbIndex(index);
return get(key, clazz, NOT_EXPIRE);
}
public String get(String key, long expire) {
String value = valueOperations.get(key);
if (expire != NOT_EXPIRE) {
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
return value;
}
public String get(Integer index, String key, long expire) {
setDbIndex(index);
String value = valueOperations.get(key);
if (expire != NOT_EXPIRE) {
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
return value;
}
public String get(String key) {
return get(key, NOT_EXPIRE);
}
public String get(Integer index, String key) {
setDbIndex(index);
return get(key, NOT_EXPIRE);
}
public void delete(String key) {
redisTemplate.delete(key);
}
public void delete(Integer index, String key) {
setDbIndex(index);
redisTemplate.delete(key);
}
/**
* Object转成JSON数据
*/
private String toJson(Object object) {
if (object instanceof Integer || object instanceof Long || object instanceof Float ||
object instanceof Double || object instanceof Boolean || object instanceof String) {
return String.valueOf(object);
}
return gson.toJson(object);
}
/**
* JSON数据,转成Object
*/
private <T> T fromJson(String json, Class<T> clazz) {
//T t = JSONObject.parseObject(json, clazz);
//return t;
return gson.fromJson(json, clazz);
}
/**
* 设置数据库索引
* chens
*
* @param dbIndex 数据库索引
*/
private void setDbIndex(Integer dbIndex) {
// 边界判断
if (dbIndex == null || dbIndex > 15 || dbIndex < 0) {
dbIndex = database;
}
LettuceConnectionFactory redisConnectionFactory = (LettuceConnectionFactory) redisTemplate
.getConnectionFactory();
if (redisConnectionFactory == null) {
return;
}
redisConnectionFactory.setDatabase(dbIndex);
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 属性设置后
redisConnectionFactory.afterPropertiesSet();
// 重置连接
redisConnectionFactory.resetConnection();
}
}
lettuce配置类 推荐使用
不同库分开注入,减少频繁切换库,可以利用工具类重写
@Autowired
private RedisTemplate redisTemplate; // 0号库
@Autowired
private RedisTemplate redisTemplate1; // 1号库
@Autowired
private RedisTemplate redisTemplate2; // 2号库
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
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.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/**
* Redis配置
*/
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
@Slf4j
public class RedisConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private long timeout;
@Value("${spring.redis.lettuce.shutdown-timeout}")
private long shutDownTimeout;
@Value("${spring.redis.lettuce.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.lettuce.pool.min-idle}")
private int minIdle;
@Value("${spring.redis.lettuce.pool.max-active}")
private int maxActive;
@Value("${spring.redis.lettuce.pool.max-wait}")
private long maxWait;
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
private LettuceConnectionFactory lettuceConnectionFactory(int index) {
GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
genericObjectPoolConfig.setMaxIdle(maxIdle);
genericObjectPoolConfig.setMinIdle(minIdle);
genericObjectPoolConfig.setMaxTotal(maxActive);
genericObjectPoolConfig.setMaxWaitMillis(maxWait);
genericObjectPoolConfig.setTimeBetweenEvictionRunsMillis(100);
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setDatabase(index);
redisStandaloneConfiguration.setHostName(host);
redisStandaloneConfiguration.setPort(port);
redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
.commandTimeout(Duration.ofMillis(timeout))
.shutdownTimeout(Duration.ofMillis(shutDownTimeout))
.poolConfig(genericObjectPoolConfig)
.build();
LettuceConnectionFactory factory = new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfig);
factory.afterPropertiesSet();
return factory;
}
private RedisTemplate<String, Object> initRedisTemplate(int index) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(lettuceConnectionFactory(index));
//使用Jackson2JsonRedisSerializer替换默认的JdkSerializationRedisSerializer来序列化和反序列化redis的value值
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
return initRedisTemplate(0);
}
@Bean
public RedisTemplate<String, Object> redisTemplate1() {
return initRedisTemplate(1);
}
@Bean
public RedisTemplate<String, Object> redisTemplate2() {
return initRedisTemplate(2);
}
}