Spring Boot 下使用 Redis,配置多个 database 数据源
兄弟们,上回咱唠了 Redis 默认 16 个库的门道,今儿咱接着整活儿 —— 在 Spring Boot 里咋配置多个 Redis database 数据源。是不是有兄弟在开发中遇到过这种情况:不同业务模块的数据想存到 Redis 的不同库里,比如用户模块用 0 号库,订单模块用 1 号库,可咋整?别慌,咱一步步来盘。
为啥要配置多个 Redis database 数据源?
先说说为啥咱需要在 Spring Boot 里搞多个 Redis database 数据源。举个栗子,假设咱搞个电商项目,用户信息、商品缓存、订单数据都得存 Redis。这时候要是全塞默认的 0 号库,键名一多就容易乱,而且后期维护起来也麻烦。要是能按业务分库存,比如用户数据放 1 号库,订单数据放 2 号库,那简直不要太爽,数据隔离性好,查起来也方便。
还有一种情况,就是咱可能得连不同的 Redis 实例,比如一个连主库,一个连从库,或者连不同环境的 Redis(测试环境、生产环境),这时候配置多个数据源就派上用场了。
Spring Boot 配置多个 Redis database 数据源的准备工作
咱先整个 Spring Boot 项目,引入 Redis 的依赖。一般来说,咱用 Spring Data Redis,在pom.xml
里加上这玩意儿:
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
|
然后,咱得在application.yml
或者application.properties
里配置 Redis 的基本信息。如果是单实例 Redis,配置多个 database 数据源其实就是配置不同的database
索引。要是连不同的 Redis 实例,还得配置不同的 IP、端口啥的。
单实例 Redis 配置多个 database 数据源
先整个简单的,单实例 Redis 配置多个 database 数据源,比如咱要配置两个数据源,一个连 0 号库,用于用户模块;一个连 1 号库,用于订单模块。
配置文件设置
在application.yml
里这么写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| spring: redis: host: 127.0.0.1 port: 6379 password: your_password timeout: 10s database: 0 lettuce: pool: min-idle: 0 max-idle: 8 max-active: 8 max-wait: -1ms
redis: order: host: 127.0.0.1 port: 6379 password: your_password timeout: 10s database: 1 lettuce: pool: min-idle: 0 max-idle: 8 max-active: 8 max-wait: -1ms
|
配置类实现
接下来咱写配置类,创建两个RedisTemplate
bean,分别对应不同的 database。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| package org.zxiat.speaker;
import com.alibaba.dubbo.common.utils.StringUtils; import lombok.Value;
@Configuration public class RedisConfig { @Bean(name = "mainRedisTemplate") public RedisTemplate<String, Object> mainRedisTemplate( @Value("${spring.redis.host}") String host, @Value("${spring.redis.port}") int port, @Value("${spring.redis.password}") String password, @Value("${spring.redis.database}") int database, @Value("${spring.redis.timeout}") Duration timeout) { return createRedisTemplate(host, port, password, database, timeout); }
@Bean(name = "orderRedisTemplate") public RedisTemplate<String, Object> orderRedisTemplate( @Value("${redis.order.host}") String host,
@Value("${redis.order.port}") int port,
@Value("${redis.order.password}") String password,
@Value("${redis.order.database}") int database,
@Value("${redis.order.timeout}") Duration timeout) { return createRedisTemplate(host, port, password, database, timeout); }
private RedisTemplate<String, Object> createRedisTemplate(String host, int port, String password, int database, Duration timeout) { LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(); lettuceConnectionFactory.setHostName(host); lettuceConnectionFactory.setPort(port);
if (!StringUtils.isEmpty(password)) { lettuceConnectionFactory.setPassword(password); }
lettuceConnectionFactory.setDatabase(database); lettuceConnectionFactory.setTimeout(timeout); lettuceConnectionFactory.afterPropertiesSet();
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(lettuceConnectionFactory);
StringRedisSerializer stringSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(stringSerializer); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setHashKeySerializer(stringSerializer); redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.afterPropertiesSet();
return redisTemplate; } }
|
使用方式
配置好之后,咱在业务代码里就可以注入对应的RedisTemplate
来使用了。比如用户模块用主数据源,订单模块用订单数据源:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package org.zxiat.speaker;
import com.alibaba.dubbo.config.annotation.Service;
@Service
public class UserService { @Autowired @Qualifier("mainRedisTemplate") private RedisTemplate<String, Object> redisTemplate;
public void saveUser(String userId, User user) { redisTemplate.opsForValue().set("user:" + userId, user); }
public User getUser(String userId) { return (User) redisTemplate.opsForValue().get("user:" + userId); } }
@Service
public class OrderService { @Autowired @Qualifier("orderRedisTemplate") private RedisTemplate<String, Object> redisTemplate;
public void saveOrder(String orderId, Order order) { redisTemplate.opsForValue().set("order:" + orderId, order); } public Order getOrder(String orderId) { return (Order) redisTemplate.opsForValue().get("order:" + orderId); } }
|
连接不同 Redis 实例的多数据源配置
上面说的是单实例不同 database 的配置,要是咱得连不同的 Redis 实例,比如一个连生产环境的 Redis,一个连测试环境的 Redis,配置方式其实差不多,就是在配置文件里把不同实例的 IP、端口、database 都写上。
配置文件示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| spring: redis: prod: host: 192.168.1.100 port: 6379 password: prod_password database: 0 timeout: 10s lettuce: pool: min-idle: 0 max-idle: 8 max-active: 8 max-wait: -1ms test: host: 192.168.1.101 port: 6379 password: test_password database: 0 timeout: 10s lettuce: pool: min-idle: 0 max-idle: 8 max-active: 8 max-wait: -1ms
|
配置类调整
配置类里创建不同的RedisTemplate
,分别读取不同的配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Bean(name = "prodRedisTemplate") public RedisTemplate<String, Object> prodRedisTemplate( @Value("${spring.redis.prod.host}") String host, @Value("${spring.redis.prod.port}") int port, @Value("${spring.redis.prod.password}") String password, @Value("${spring.redis.prod.database}") int database, @Value("${spring.redis.prod.timeout}") Duration timeout) { return createRedisTemplate(host, port, password, database, timeout); }
@Bean(name = "testRedisTemplate") public RedisTemplate<String, Object> testRedisTemplate( @Value("${spring.redis.test.host}") String host, @Value("${spring.redis.test.port}") int port, @Value("${spring.redis.test.password}") String password, @Value("${spring.redis.test.database}") int database, @Value("${spring.redis.test.timeout}") Duration timeout) { return createRedisTemplate(host, port, password, database, timeout); }
|
集群模式下的多数据源配置
不过兄弟们得注意,要是用 Redis 集群(Cluster)模式,这时候 Redis 的 database 概念就被弱化了,因为集群是通过哈希槽(hash slot)来分片数据的,每个节点负责一部分槽位,这时候再按 database 分库就没啥意义了。
在集群模式下,咱要是想区分不同业务的数据,更推荐在键名里加前缀,比如user:1001
、order:2001
,通过键名来区分不同业务的数据,这样更灵活,也符合集群的设计理念。
要是咱确实需要在集群模式下配置多个数据源,比如连不同的集群,配置方式和单实例类似,就是在配置文件里把不同集群的节点信息写上,然后创建不同的RedisConnectionFactory
和RedisTemplate
。
总结
最后咱总结一下在 Spring Boot 里配置多个 Redis database 数据源的步骤和注意事项:
在配置文件里定义不同数据源的连接信息,包括 host、port、password、database 等;
创建配置类,为每个数据源创建对应的RedisTemplate
bean,注意通过@Qualifier
注解区分;
在业务代码里注入对应的RedisTemplate
来使用;
如果是 Redis 集群模式,更推荐通过键名前缀来区分业务数据,而不是用 database;
配置时注意序列化方式,避免存到 Redis 的数据乱码。
怎么样,兄弟们,这下知道在 Spring Boot 里咋配置多个 Redis database 数据源了吧?实际开发中根据业务需求来整,该分库分库,该加前缀加前缀,把 Redis 玩得明明白白的。要是还有啥不明白的,评论区唠唠,咱一起琢磨琢磨。