爱萝莉真是太好了 爱萝莉真是太好了

努力让自己变得更优秀呀!

目录
RedisTemplate 随意切换多个db库 不影响其他线程
/    

RedisTemplate 随意切换多个db库 不影响其他线程

问题描述

原切换 db 的方式会使全局的 redisTemplate 被修改掉,并发量稍微高一点,就会影响到其他线程查询 Redis 数据

1//原切换db的方式(错误的)
2public RedisTemplate<Serializable, Object> initRedis(Integer indexDb){
3    	LettuceConnectionFactory jedisConnectionFactory = (LettuceConnectionFactory) redisTemplate.getConnectionFactory();
4    	jedisConnectionFactory.setDatabase(indexDb);
5    	redisTemplate.setConnectionFactory(jedisConnectionFactory);
6    	jedisConnectionFactory.resetConnection();
7    	return redisTemplate;
8}

解决方案,为每一个 db 创建一个 redisTemplate

  1import java.io.Serializable;
  2import java.util.HashMap;
  3import java.util.List;
  4import java.util.Map;
  5
  6import javax.annotation.PostConstruct;
  7
  8import org.springframework.beans.factory.annotation.Value;
  9import org.springframework.data.redis.connection.RedisConnectionFactory;
 10import org.springframework.data.redis.connection.RedisPassword;
 11import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
 12import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
 13import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
 14import org.springframework.data.redis.core.RedisTemplate;
 15import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
 16import org.springframework.data.redis.serializer.StringRedisSerializer;
 17import org.springframework.stereotype.Component;
 18
 19import lombok.extern.slf4j.Slf4j;
 20import redis.clients.jedis.JedisPoolConfig;
 21
 22@Component
 23@Slf4j
 24public class RedisConfig {
 25
 26	@Value("${redis.host}")
 27	private String hostName;
 28	@Value("${redis.port}")
 29	private int port;
 30	@Value("${redis.password}")
 31	private String passWord;
 32	@Value("${redis.maxIdle}")
 33	private int maxIdl;
 34	@Value("${redis.minIdle}")
 35	private int minIdl;
 36	@Value("${redis.timeout}")
 37	private int timeout;
 38
 39	private int defaultDb;
 40
 41	@Value("${redis.dbs}")
 42	private List<Integer> dbs;
 43
 44
 45	public static Map<Integer, RedisTemplate<Serializable, Object>> redisTemplateMap = new HashMap<>();
 46
 47	@PostConstruct
 48	public void initRedisTemp() throws Exception {
 49		log.info("###### START 初始化 Redis 连接池 START ######");
 50		defaultDb = dbs.get(0);
 51		for (Integer db : dbs) {
 52			log.info("###### 正在加载Redis-db-" + db+ " ######");
 53			redisTemplateMap.put(db, redisTemplateObject(db));
 54		}
 55		log.info("###### END 初始化 Redis 连接池 END ######");
 56	}
 57
 58	public RedisTemplate<Serializable, Object> redisTemplateObject(Integer dbIndex) throws Exception {
 59		RedisTemplate<Serializable, Object> redisTemplateObject = new RedisTemplate<Serializable, Object>();
 60		redisTemplateObject.setConnectionFactory(redisConnectionFactory(jedisPoolConfig(), dbIndex));
 61		setSerializer(redisTemplateObject);
 62		redisTemplateObject.afterPropertiesSet();
 63		return redisTemplateObject;
 64	}
 65
 66	/**
 67	 * 连接池配置信息
 68	 * 
 69	 * @return
 70	 */
 71	public JedisPoolConfig jedisPoolConfig() {
 72		JedisPoolConfig poolConfig = new JedisPoolConfig();
 73		// 最大连接数
 74		poolConfig.setMaxIdle(maxIdl);
 75		// 最小空闲连接数
 76		poolConfig.setMinIdle(minIdl);
 77		poolConfig.setTestOnBorrow(true);
 78		poolConfig.setTestOnReturn(true);
 79		poolConfig.setTestWhileIdle(true);
 80		poolConfig.setNumTestsPerEvictionRun(10);
 81		poolConfig.setTimeBetweenEvictionRunsMillis(60000);
 82		// 当池内没有可用的连接时,最大等待时间
 83		poolConfig.setMaxWaitMillis(10000);
 84		// ------其他属性根据需要自行添加-------------
 85		return poolConfig;
 86	}
 87
 88	/**
 89	 * jedis连接工厂
 90	 * 
 91	 * @param jedisPoolConfig
 92	 * @return
 93	 */
 94	public RedisConnectionFactory redisConnectionFactory(JedisPoolConfig jedisPoolConfig, int db) {
 95		// 单机版jedis
 96		RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
 97		// 设置redis服务器的host或者ip地址
 98		redisStandaloneConfiguration.setHostName(hostName);
 99		// 设置默认使用的数据库
100		redisStandaloneConfiguration.setDatabase(db);
101		// 设置密码
102		redisStandaloneConfiguration.setPassword(RedisPassword.of(passWord));
103		// 设置redis的服务的端口号
104		redisStandaloneConfiguration.setPort(port);
105
106		// 获得默认的连接池构造器(怎么设计的,为什么不抽象出单独类,供用户使用呢)
107		JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcb = (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration
108				.builder();
109		// 指定jedisPoolConifig来修改默认的连接池构造器(真麻烦,滥用设计模式!)
110		jpcb.poolConfig(jedisPoolConfig);
111		// 通过构造器来构造jedis客户端配置
112		JedisClientConfiguration jedisClientConfiguration = jpcb.build();
113		// 单机配置 + 客户端配置 = jedis连接工厂
114		return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
115	}
116
117	private void setSerializer(RedisTemplate<Serializable, Object> template) {
118		template.setKeySerializer(new StringRedisSerializer());
119		template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
120	}
121
122
123	public RedisTemplate<Serializable, Object> getRedisTemplateByDb(int db){
124            return redisTemplateMap.get(db);
125        }
126
127	public RedisTemplate<Serializable, Object> getRedisTemplate(){
128            return redisTemplateMap.get(defaultDb);
129        }
130}
131

application.yml

1redis: 
2    host: 192.168.100.77
3    port: 6379
4    password: 123456      # 密码(默认为空)
5    maxIdle: 10
6    minIdle: 5
7    timeout: 1000
8    dbs: 0,1      # 可以指定多个,用“,”隔开,写在第一个的为defaultDB

使用方法

1@Resource RedisConfig redisConfig;
2
3//无参数时默认查询defaultDB  也就是配置文件中写在第一个的db
4redisConfig.getRedisTemplate().opsForValue().....
5
6//可以指定具体查询哪个DB
7redisConfig.getRedisTemplate(1).opsForValue().....

标题:RedisTemplate 随意切换多个db库 不影响其他线程
地址:https://www.1-love.cn/RedisTemplate-update-db.html