SpringBoot高级篇Redis之基本配置

更多Spring文章,欢迎点击 一灰灰Blog-Spring专题java

在Spring的应用中,redis能够算是基础操做了。那么想要玩转redis,咱们须要知道哪些知识点呢?git

  • redis配置,默认,非默认,集群,多实例,链接池参数等
  • redis读写操做,RedisTemplate的基本使用姿式
  • 几种序列化方式对比

本篇博文为redis系列的开篇,将介绍最基本的配置github

<!-- more -->redis

I. redis基本配置

1. 默认配置

最简单的使用其实开箱便可用,添加依赖spring

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

本机启动redis,一切采用默认的配置 (host:127.0.0.1, port:6379, 无密码)apache

而后就能够愉快的玩耍了,能够直接注入redisTemplate实例,进行各类读写操做app

@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,那么彻底能够只修改默认的配置参数ide

修改配置文件: application.ymlspring-boot

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来操做便可,须要额外注意的是设置了链接池的相关参数,须要额外引入依赖学习

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

3. 多redis配置

依赖多个不一样的redis,也就是说个人项目须要从多个redis实例中获取数据,这种时候,就不能直接使用默认的,须要咱们本身来声明ConnectionFactoryRedisTemplate

配置以下

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实例,设置链接工厂

@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的读写

@SpringBootApplication
public class Application {

    public Application(RedisTemplate<String, String> localRedisTemplate, RedisTemplate<String, String>
            defaultRedisTemplate)
            throws InterruptedException {
        // 10s的有效时间
        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);
    }
}

上面的代码执行演示以下

showcase

上面的演示为动图,抓一下重点:

  • 注意 localRedisTemplate, defaultRedisTemplate 两个对象不相同(看debug窗口后面的@xxx)
  • 一样两个RedisTemplateConnectionFactory也是两个不一样的实例(即分别对应前面配置类中的两个Factory)
  • 执行后输出的结果正如咱们预期的redis操做
    • 塞值,立刻取出没问题
    • 失效后,再查询,返回null
  • 最后输出异常日志,提示以下
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链接了)

@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冲突,那么就不加载这个配置便可

@SpringBootApplication
@EnableAutoConfiguration(exclude = {RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class})
public class Application {
  // ...
}

II. 其余

0. 项目

1. 一灰灰Blog

一灰灰的我的博客,记录全部学习和工做中的博文,欢迎你们前去逛逛

2. 声明

尽信书则不如,以上内容,纯属一家之言,因我的能力有限,不免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

3. 扫描关注

一灰灰blog

QrCode

知识星球

goals

相关文章
相关标签/搜索