问题描述
原切换 db 的方式会使全局的 redisTemplate 被修改掉,并发量稍微高一点,就会影响到其他线程查询 Redis 数据
//原切换db的方式(错误的) public RedisTemplate<Serializable, Object> initRedis(Integer indexDb){ LettuceConnectionFactory jedisConnectionFactory = (LettuceConnectionFactory) redisTemplate.getConnectionFactory(); jedisConnectionFactory.setDatabase(indexDb); redisTemplate.setConnectionFactory(jedisConnectionFactory); jedisConnectionFactory.resetConnection(); return redisTemplate; }
解决方案,为每一个 db 创建一个 redisTemplate
import java.io.Serializable; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Value; 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.jedis.JedisClientConfiguration; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.stereotype.Component; import lombok.extern.slf4j.Slf4j; import redis.clients.jedis.JedisPoolConfig; @Component @Slf4j public class RedisConfig { @Value("${redis.host}") private String hostName; @Value("${redis.port}") private int port; @Value("${redis.password}") private String passWord; @Value("${redis.maxIdle}") private int maxIdl; @Value("${redis.minIdle}") private int minIdl; @Value("${redis.timeout}") private int timeout; private int defaultDb; @Value("${redis.dbs}") private List<Integer> dbs; public static Map<Integer, RedisTemplate<Serializable, Object>> redisTemplateMap = new HashMap<>(); @PostConstruct public void initRedisTemp() throws Exception { log.info("###### START 初始化 Redis 连接池 START ######"); defaultDb = dbs.get(0); for (Integer db : dbs) { log.info("###### 正在加载Redis-db-" + db+ " ######"); redisTemplateMap.put(db, redisTemplateObject(db)); } log.info("###### END 初始化 Redis 连接池 END ######"); } public RedisTemplate<Serializable, Object> redisTemplateObject(Integer dbIndex) throws Exception { RedisTemplate<Serializable, Object> redisTemplateObject = new RedisTemplate<Serializable, Object>(); redisTemplateObject.setConnectionFactory(redisConnectionFactory(jedisPoolConfig(), dbIndex)); setSerializer(redisTemplateObject); redisTemplateObject.afterPropertiesSet(); return redisTemplateObject; } /** * 连接池配置信息 * * @return */ public JedisPoolConfig jedisPoolConfig() { JedisPoolConfig poolConfig = new JedisPoolConfig(); // 最大连接数 poolConfig.setMaxIdle(maxIdl); // 最小空闲连接数 poolConfig.setMinIdle(minIdl); poolConfig.setTestOnBorrow(true); poolConfig.setTestOnReturn(true); poolConfig.setTestWhileIdle(true); poolConfig.setNumTestsPerEvictionRun(10); poolConfig.setTimeBetweenEvictionRunsMillis(60000); // 当池内没有可用的连接时,最大等待时间 poolConfig.setMaxWaitMillis(10000); // ------其他属性根据需要自行添加------------- return poolConfig; } /** * jedis连接工厂 * * @param jedisPoolConfig * @return */ public RedisConnectionFactory redisConnectionFactory(JedisPoolConfig jedisPoolConfig, int db) { // 单机版jedis RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); // 设置redis服务器的host或者ip地址 redisStandaloneConfiguration.setHostName(hostName); // 设置默认使用的数据库 redisStandaloneConfiguration.setDatabase(db); // 设置密码 redisStandaloneConfiguration.setPassword(RedisPassword.of(passWord)); // 设置redis的服务的端口号 redisStandaloneConfiguration.setPort(port); // 获得默认的连接池构造器(怎么设计的,为什么不抽象出单独类,供用户使用呢) JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcb = (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration .builder(); // 指定jedisPoolConifig来修改默认的连接池构造器(真麻烦,滥用设计模式!) jpcb.poolConfig(jedisPoolConfig); // 通过构造器来构造jedis客户端配置 JedisClientConfiguration jedisClientConfiguration = jpcb.build(); // 单机配置 + 客户端配置 = jedis连接工厂 return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration); } private void setSerializer(RedisTemplate<Serializable, Object> template) { template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); } public RedisTemplate<Serializable, Object> getRedisTemplateByDb(int db){ return redisTemplateMap.get(db); } public RedisTemplate<Serializable, Object> getRedisTemplate(){ return redisTemplateMap.get(defaultDb); } }
application.yml
redis: host: 192.168.100.77 port: 6379 password: 123456 # 密码(默认为空) maxIdle: 10 minIdle: 5 timeout: 1000 dbs: 0,1 # 可以指定多个,用“,”隔开,写在第一个的为defaultDB
使用方法
@Resource RedisConfig redisConfig; //无参数时默认查询defaultDB 也就是配置文件中写在第一个的db redisConfig.getRedisTemplate().opsForValue()..... //可以指定具体查询哪个DB redisConfig.getRedisTemplate(1).opsForValue().....
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于