概述
在Redis中默认有16个库,一些业务场景需要对Redis分库,每个库按业务需求存储不同数据。比如下面:
publicenum RedisDBEnum { Default(0,"默认"), Banner(1,"Banner热数据"), Captcha_Token(2, "图片验证码/短信验证码/token"), ShoppingCart(3, "购物车"), Order(4,"订单"), Goods(5,"商品"), User(6, "用户"), District(7,"中国省份城市数据库"); //TODO and so on private Integer index; private String desc; private RedisDBEnum(Integer index, String desc) { this.index = index; this.desc = desc; } public Integer getIndex() { return index; } public String getDesc() { return desc; } }
使用原生的 spring-boot-starter-data-redis
默认只能构建出单例的 RedisTemplate 和 LettuceConnectionFactory,并且只能操作指定的一个Redis 库。所以,我们需要 改造LettuceConnectionFactory 让其能构建多个 RedisTemplate 。
实现过程
在 pom.xml 中引入相关依赖
<!-- 配置管理,里面有依赖FastJson --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> </dependency> <dependency> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
修改bootstrap配置文集
src/main/resources/bootstrap.properties
#配置中心 spring.cloud.nacos.config.server-addr=192.168.1.4:8848 spring.cloud.nacos.config.namespace=c51764ea-936b-42a9-a169-8b78ca9ea93e spring.cloud.nacos.config.ext-config[0].data-id=redis_config.properties spring.cloud.nacos.config.ext-config[0].group=DEFAULT_GROUP spring.cloud.nacos.config.ext-config[0].refresh=false
在Nacos的DEV命名空间新增redis_config.properties 配置文件
redis.host=192.168.1.4 redis.port=6379 redis.password= redis.timeout=10000 redis.lettuce.pool.max-idle=4 redis.lettuce.pool.min-idle=0 redis.lettuce.pool.max-active=8 redis.lettuce.pool.max-wait=10000 redis.lettuce.shutdown-timeout=4000
编写配置类RedisConfig.java
import java.time.Duration; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import lombok.Data; @Data @Component @ConfigurationProperties(prefix = "redis") publicclass RedisConfig { private String host; private Integer port; private String password; private Duration timeout; privatefinal Lettuce lettuce = new Lettuce(); @Data publicstaticclass Pool { privateint maxIdle = 8; privateint minIdle = 0; privateint maxActive = 8; private Duration maxWait = Duration.ofMillis(-1); private Duration timeBetweenEvictionRuns; } @Data publicstaticclass Lettuce { private Duration shutdownTimeout = Duration.ofMillis(100); private Pool pool; } }
构建多个RedisTemplate
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration publicclass ProjectRedisTemplate { @Autowired private RedisConfig redisConfig; private LettuceConnectionFactory createLettuceConnectionFactory(int dbIndex) { // Redis配置 RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration(redisConfig.getHost(), redisConfig.getPort()); redisConfiguration.setDatabase(dbIndex); redisConfiguration.setPassword(redisConfig.getPassword()); // 连接池配置 GenericObjectPoolConfig<Object> genericObjectPoolConfig = new GenericObjectPoolConfig<Object>(); RedisConfig.Pool pool = redisConfig.getLettuce().getPool(); genericObjectPoolConfig.setMaxIdle(pool.getMaxIdle()); genericObjectPoolConfig.setMinIdle(pool.getMinIdle()); genericObjectPoolConfig.setMaxTotal(pool.getMaxActive()); genericObjectPoolConfig.setMaxWaitMillis(pool.getMaxWait().toMillis()); // Redis客户端配置 LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration .builder().commandTimeout(redisConfig.getTimeout()); builder.shutdownTimeout(redisConfig.getLettuce().getShutdownTimeout()); builder.poolConfig(genericObjectPoolConfig); // 根据配置和客户端配置创建连接 LettuceClientConfiguration lettuceClientConfiguration = builder.build(); LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisConfiguration, lettuceClientConfiguration); lettuceConnectionFactory.afterPropertiesSet(); return lettuceConnectionFactory; } /** * Banner 数据存储 * * @return */ @Bean public RedisTemplate<String, Object> bannerRedisTemplate() { LettuceConnectionFactory lettuceConnectionFactory = createLettuceConnectionFactory(RedisDBEnum.Banner.getIndex()); RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>(); redisTemplate.setConnectionFactory(lettuceConnectionFactory); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(stringRedisSerializer); redisTemplate.setHashKeySerializer(stringRedisSerializer); FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); redisTemplate.setValueSerializer(fastJsonRedisSerializer); redisTemplate.setHashValueSerializer(fastJsonRedisSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; } /** * 验证码/token 数据存储 * * @return */ @Bean public RedisTemplate<String, Object> captchaTokenRedisTemplate() { LettuceConnectionFactory lettuceConnectionFactory = createLettuceConnectionFactory(RedisDBEnum.Captcha_Token.getIndex()); RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>(); redisTemplate.setConnectionFactory(lettuceConnectionFactory); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(stringRedisSerializer); redisTemplate.setHashKeySerializer(stringRedisSerializer); FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); redisTemplate.setValueSerializer(fastJsonRedisSerializer); redisTemplate.setHashValueSerializer(fastJsonRedisSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; } /** * 默认 * * @return */ @Bean public RedisTemplate<String, Object> redisTemplate() { LettuceConnectionFactory lettuceConnectionFactory = createLettuceConnectionFactory(RedisDBEnum.Default.getIndex()); RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>(); redisTemplate.setConnectionFactory(lettuceConnectionFactory); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(stringRedisSerializer); redisTemplate.setHashKeySerializer(stringRedisSerializer); FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); redisTemplate.setValueSerializer(fastJsonRedisSerializer); redisTemplate.setHashValueSerializer(fastJsonRedisSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; } }
业务测试
@Slf4j @RestController publicclass DemoController { @Autowired @Qualifier("bannerRedisTemplate") private RedisTemplate<String, Object> bannerRedisTemplate; @Autowired @Qualifier("captchaTokenRedisTemplate") private RedisTemplate<String, Object> captchaTokenRedisTemplate; @GetMapping("/store") public String store() { captchaTokenRedisTemplate.opsForValue().set("captchaPureNumber", RandomStringUtils.randomNumeric(6), 30, TimeUnit.MINUTES); captchaTokenRedisTemplate.opsForValue().set("token", RandomStringUtils.randomAlphabetic(21), 30, TimeUnit.MINUTES); List<Money> moneyList = Arrays.asList(new Money(1L, "人民币", 100), new Money(2L, "越南盾", 100000)); bannerRedisTemplate.opsForList().rightPushAll("homePageLeftBanner", moneyList); SetOperations<String, Object> moneySet = bannerRedisTemplate.opsForSet(); moneySet.add("homePageRightBanner", new Money(11L, "日元", 10000)); moneySet.add("homePageRightBanner", new Money(22L, "加元", 20000)); moneySet.add("homePageRightBanner", new Money(33L, "泰铢", 30000)); return"somewhere"; } @GetMapping("/view") public String view(Model model) { model.addAttribute("captchaPureNumber", captchaTokenRedisTemplate.opsForValue().get("captchaPureNumber")); model.addAttribute("token", captchaTokenRedisTemplate.opsForValue().get("token")); Set<Object> homePageRightBanner = bannerRedisTemplate.opsForSet().members("homePageRightBanner"); model.addAttribute("homePageRightBanner", homePageRightBanner); List<Object> homePageLeftBanner = (List<Object>) bannerRedisTemplate.opsForList().range("homePageLeftBanner", 0,-1); model.addAttribute("homePageLeftBanner", homePageLeftBanner); return"<pre>" + JSON.toJSONString(model, SerializerFeature.PrettyFormat,SerializerFeature.WriteMapNullValue) + "</pre>"; } } @Builder @Data class Money { private Long id; private String currency; private Integer value; }
访问 Controller中的 store
方法,不同业务的RedisTemplate操作不同Redis库。访问 Controller view 方法,查看不同Redis库数据。
好了,各位朋友们,本期的内容到此就全部结束啦,能看到这里的同学都是优秀的同学,下一个升职加薪的就是你了!