在Spring的应用中,redis可以算是基础操作了。那么想要玩转redis,我们需要知道哪些知识点呢?
redis配置,默认,非默认,集群,多实例,连接池参数等
redis读写操作,RedisTemplate的基本使用姿势
几种序列化方式对比
本篇博文为redis系列的开篇,将介绍最基本的配置
I. redis基本配置 1. 默认配置 最简单的使用其实开箱即可用,添加依赖
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-data-redis</artifactId > </dependency >
本机启动redis,一切采用默认的配置 (host:127.0.0.1, port:6379, 无密码)
然后就可以愉快的玩耍了,可以直接注入redisTemplate实例,进行各种读写操作
1 2 3 4 5 6 7 8 9 10 11 12 13 @SpringBootApplication public class Application { public Application (RedisTemplate<String, String> redisTemplate) { redisTemplate.opsForValue().set("hello" , "world" ); String ans = redisTemplate.opsForValue().get("hello" ); Assert.isTrue("world" .equals(ans)); } public static void main (String[] args) { SpringApplication.run(Application.class, args); } }
2. 自定义配置参数 前面是默认的配置参数,在实际的使用中,一般都会修改这些默认的配置项,如果我的应用中,只有一个redis,那么完全可以只修改默认的配置参数
修改配置文件: application.yml
1 2 3 4 5 6 7 8 9 10 11 12 spring: redis: host: 127.0.0.1 port: 6379 password: database: 0 lettuce: pool: max-active: 32 max-wait: 300ms max-idle: 16 min-idle: 8
使用和前面没有什么区别,直接通过注入RedisTemplate来操作即可,需要额外注意的是设置了连接池的相关参数,需要额外引入依赖
1 2 3 4 <dependency > <groupId > org.apache.commons</groupId > <artifactId > commons-pool2</artifactId > </dependency >
3. 多redis配置 依赖多个不同的redis,也就是说我的项目需要从多个redis实例中获取数据,这种时候,就不能直接使用默认的,需要我们自己来声明ConnectionFactory和 RedisTemplate
配置如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 spring: redis: host: 127.0.0.1 port: 6379 password: lettuce: pool: max-active: 32 max-wait: 300 max-idle: 16 min-idle: 8 database: 0 local-redis: host: 127.0.0.1 port: 6379 database: 0 password: lettuce: pool: max-active: 16 max-wait: 100 max-idle: 8 min-idle: 4
对应的配置类,采用Lettuce,基本设置如下,套路都差不多,先读取配置,初始化ConnectionFactory,然后创建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 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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 @Configuration public class RedisAutoConfig { @Bean public LettuceConnectionFactory defaultLettuceConnectionFactory (RedisStandaloneConfiguration defaultRedisConfig, GenericObjectPoolConfig defaultPoolConfig) { LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder().commandTimeout(Duration.ofMillis(100 )) .poolConfig(defaultPoolConfig).build(); return new LettuceConnectionFactory(defaultRedisConfig, clientConfig); } @Bean public RedisTemplate<String, String> defaultRedisTemplate ( LettuceConnectionFactory defaultLettuceConnectionFactory) { RedisTemplate<String, String> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(defaultLettuceConnectionFactory); redisTemplate.afterPropertiesSet(); return redisTemplate; } @Bean @ConditionalOnBean (name = "localRedisConfig" ) public LettuceConnectionFactory localLettuceConnectionFactory (RedisStandaloneConfiguration localRedisConfig, GenericObjectPoolConfig localPoolConfig) { LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder().commandTimeout(Duration.ofMillis(100 )) .poolConfig(localPoolConfig).build(); return new LettuceConnectionFactory(localRedisConfig, clientConfig); } @Bean @ConditionalOnBean (name = "localLettuceConnectionFactory" ) public RedisTemplate<String, String> localRedisTemplate (LettuceConnectionFactory localLettuceConnectionFactory) { RedisTemplate<String, String> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(localLettuceConnectionFactory); redisTemplate.afterPropertiesSet(); return redisTemplate; } @Configuration @ConditionalOnProperty (name = "host" , prefix = "spring.local-redis" ) public static class LocalRedisConfig { @Value ("${spring.local-redis.host:127.0.0.1}" ) private String host; @Value ("${spring.local-redis.port:6379}" ) private Integer port; @Value ("${spring.local-redis.password:}" ) private String password; @Value ("${spring.local-redis.database:0}" ) private Integer database; @Value ("${spring.local-redis.lettuce.pool.max-active:8}" ) private Integer maxActive; @Value ("${spring.local-redis.lettuce.pool.max-idle:8}" ) private Integer maxIdle; @Value ("${spring.local-redis.lettuce.pool.max-wait:-1}" ) private Long maxWait; @Value ("${spring.local-redis.lettuce.pool.min-idle:0}" ) private Integer minIdle; @Bean public GenericObjectPoolConfig localPoolConfig () { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); config.setMaxTotal(maxActive); config.setMaxIdle(maxIdle); config.setMinIdle(minIdle); config.setMaxWaitMillis(maxWait); return config; } @Bean public RedisStandaloneConfiguration localRedisConfig () { RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(); config.setHostName(host); config.setPassword(RedisPassword.of(password)); config.setPort(port); config.setDatabase(database); return config; } } @Configuration public static class DefaultRedisConfig { @Value ("${spring.redis.host:127.0.0.1}" ) private String host; @Value ("${spring.redis.port:6379}" ) private Integer port; @Value ("${spring.redis.password:}" ) private String password; @Value ("${spring.redis.database:0}" ) private Integer database; @Value ("${spring.redis.lettuce.pool.max-active:8}" ) private Integer maxActive; @Value ("${spring.redis.lettuce.pool.max-idle:8}" ) private Integer maxIdle; @Value ("${spring.redis.lettuce.pool.max-wait:-1}" ) private Long maxWait; @Value ("${spring.redis.lettuce.pool.min-idle:0}" ) private Integer minIdle; @Bean public GenericObjectPoolConfig defaultPoolConfig () { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); config.setMaxTotal(maxActive); config.setMaxIdle(maxIdle); config.setMinIdle(minIdle); config.setMaxWaitMillis(maxWait); return config; } @Bean public RedisStandaloneConfiguration defaultRedisConfig () { RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(); config.setHostName(host); config.setPassword(RedisPassword.of(password)); config.setPort(port); config.setDatabase(database); return config; } } }
测试类如下,简单的演示下两个template的读写
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 @SpringBootApplication public class Application { public Application (RedisTemplate<String, String> localRedisTemplate, RedisTemplate<String, String> defaultRedisTemplate) throws InterruptedException { localRedisTemplate.delete("key" ); localRedisTemplate.opsForValue().set("key" , "value" , 100 , TimeUnit.MILLISECONDS); String ans = localRedisTemplate.opsForValue().get("key" ); System.out.println("value" .equals(ans)); TimeUnit.MILLISECONDS.sleep(200 ); ans = localRedisTemplate.opsForValue().get("key" ); System.out.println("value" .equals(ans) + " >> false ans should be null! ans=[" + ans + "]" ); defaultRedisTemplate.opsForValue().set("key" , "value" , 100 , TimeUnit.MILLISECONDS); ans = defaultRedisTemplate.opsForValue().get("key" ); System.out.println(ans); } public static void main (String[] args) { SpringApplication.run(Application.class, args); } }
上面的代码执行演示如下
上面的演示为动图,抓一下重点:
注意 localRedisTemplate, defaultRedisTemplate 两个对象不相同(看debug窗口后面的@xxx)
同样两个RedisTemplate的ConnectionFactory也是两个不同的实例(即分别对应前面配置类中的两个Factory)
执行后输出的结果正如我们预期的redis操作
塞值,马上取出没问题
失效后,再查询,返回null
最后输出异常日志,提示如下
1 2 3 4 5 6 7 8 9 10 Description: Parameter 0 of method redisTemplate in org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration required a single bean, but 2 were found: - defaultLettuceConnectionFactory: defined by method 'defaultLettuceConnectionFactory' in class path resource [com/git/hui/boot/redis/config/RedisAutoConfig.class] - localLettuceConnectionFactory: defined by method 'localLettuceConnectionFactory' in class path resource [com/git/hui/boot/redis/config/RedisAutoConfig.class] Action: Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
上面表示说有多个ConnectionFactory存在,然后创建默认的RedisTemplate就不知道该选择哪一个了,有两种方法
方法一:指定默认的ConnectionFactory
借助@Primary来指定默认的连接工厂,然后在使用工程的时候,通过@Qualifier注解来显示指定,我需要的工厂是哪个(主要是localRedisTemplate这个bean的定义,如果不加,则会根据defaultLettuceConnectionFactory这个实例来创建Redis连接了)
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 @Bean @Primary public LettuceConnectionFactory defaultLettuceConnectionFactory (RedisStandaloneConfiguration defaultRedisConfig, GenericObjectPoolConfig defaultPoolConfig) { } @Bean public RedisTemplate<String, String> defaultRedisTemplate ( @Qualifier("defaultLettuceConnectionFactory" ) LettuceConnectionFactory defaultLettuceConnectionFactory) { } @Bean @ConditionalOnBean (name = "localRedisConfig" )public LettuceConnectionFactory localLettuceConnectionFactory (RedisStandaloneConfiguration localRedisConfig, GenericObjectPoolConfig localPoolConfig) { } @Bean @ConditionalOnBean (name = "localLettuceConnectionFactory" )public RedisTemplate<String, String> localRedisTemplate ( @Qualifier("localLettuceConnectionFactory" ) LettuceConnectionFactory localLettuceConnectionFactory) { }
方法二:忽略默认的自动配置类
既然提示的是org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration类加载bean冲突,那么就不加载这个配置即可
1 2 3 4 5 @SpringBootApplication @EnableAutoConfiguration (exclude = {RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class})public class Application { }
II. 其他 0. 项目
1. 一灰灰Blog
一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
2. 声明 尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激
3. 扫描关注 一灰灰blog
知识星球
打赏
如果觉得我的文章对您有帮助,请随意打赏。
微信打赏
支付宝打赏