springboot redis接入

简易接入

springboot默认提供了开箱即用的start

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

引入后,配置一些基本的信息后

#Redis服务器地址
spring.redis.host= your ip
#Redis服务器连接端口
spring.redis.port=6379
#redis连接密码
spring.redis.password= your password 

就可以使用进行一系列操作了。

@Autowired
private RedisTemplate<String, String> redisTemplate;

常规接入

新增引入

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

引入commons-pool2是因为不管是jedis还是lettuce都没有提供池化的操作,通常在日常开发中都会建立连接池,所以引入这个包。

另外需要注意的是,spring-boot-starter-data-redis 默认使用的是lettuce来驱动,但lettuce有个问题:https://github.com/lettuce-io/lettuce-core/issues/2082 目前还处于open状态,大意是在意外情况下,如果lettuce的连接发生了超时,那么将会在一段时间后才会进行重试。这个一段时间925.6 s in Linux。

解决办法参考:https://www.cnblogs.com/wingcode/p/14527107.html

另外lettuce的FAQ也提到了这个问题

https://github.com/lettuce-io/lettuce-core/wiki/Frequently-Asked-Questions

所以下面我就不想用lettuce了。。。直接上jedis接入

引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <artifactId>lettuce-core</artifactId>
            <groupId>io.lettuce</groupId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

单数据源接入

由于springboot有自动配置,所以配置文件为

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=mypassword
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.min-idle=8
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.max-wait=3000
spring.redis.jedis.pool.enabled=true

一些其他的优化参数可参考:https://help.aliyun.com/document_detail/98726.html

但有些参数似乎并不能设置。。。。

然后设置config注册到容器,就能正常使用RedisTemplate了

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import com.alibaba.fastjson2.support.spring.data.redis.GenericFastJsonRedisSerializer;

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 配置连接工厂
        template.setConnectionFactory(redisConnectionFactory);
        // 配置key的序列化方式, 这里使用fastjson2
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericFastJsonRedisSerializer());
        // 初始化配置, 一般来说, 如果启动没报错就不需要写这个
        // template.afterPropertiesSet();
        
        return template;
    }
}

多数据源自定义接入

写配置类

import java.time.Duration;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import redis.clients.jedis.JedisPoolConfig;

@Configuration
public class RedisConfig {

    @Bean(name = "redisDevTemplate")
    public RedisTemplate<String, Object> redisDevTemplate(@Value("${redis.dev.host}") String host,
                                                       @Value("${redis.dev.port}") int port,
                                                       @Value("${redis.dev.password}") String password,
                                                       @Value("${redis.dev.database}") int index,
                                                       @Value("${redis.dev.pool.max-total:8}") int maxTotal,
                                                       @Value("${redis.dev.pool.min-idle:1}") int minIdle,
                                                       @Value("${redis.dev.pool.max-idle:8}") int maxIdle,
                                                       @Value("${redis.dev.pool.max-wait}") long maxWaitMillis
    ) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(
                connectionFactory(host, port, password, index, maxTotal, minIdle, maxIdle, maxWaitMillis));

        template.setDefaultSerializer(new StringRedisSerializer());

        return template;
    }

    @Bean(name = "redisProdTemplate")
    public RedisTemplate<String, Object> redisProdTemplate(@Value("${redis.prod.host}") String host,
                                                       @Value("${redis.prod.port}") int port,
                                                       @Value("${redis.prod.password}") String password,
                                                       @Value("${redis.prod.database}") int index,
                                                       @Value("${redis.prod.pool.max-total:8}") int maxTotal,
                                                       @Value("${redis.prod.pool.min-idle:1}") int minIdle,
                                                       @Value("${redis.prod.pool.max-idle:8}") int maxIdle,
                                                       @Value("${redis.prod.pool.max-wait}") long maxWaitMillis
    ) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(
                connectionFactory(host, port, password, index, maxTotal, minIdle, maxIdle, maxWaitMillis));

        template.setDefaultSerializer(new StringRedisSerializer());

        return template;
    }



    public RedisConnectionFactory connectionFactory(String host, int port, String password, int index, int maxTotal,
                                                    int minIdle, int maxIdle, long maxWaitMillis) {

        RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration();
        standaloneConfiguration.setHostName(host);
        standaloneConfiguration.setPort(port);
        if (password != null && !password.isEmpty()) {
            standaloneConfiguration.setPassword(password);
        }
        if (index != 0) {
            standaloneConfiguration.setDatabase(index);
        }

        JedisClientConfiguration jedisClientConfiguration =
                JedisClientConfiguration.builder().usePooling().poolConfig(poolConfig(minIdle, maxIdle, maxTotal,
                        maxWaitMillis
                )).build();

        JedisConnectionFactory jedisConnectionFactory =
                new JedisConnectionFactory(standaloneConfiguration, jedisClientConfiguration);

        // 用过时的方法更简便一点 :(
        // JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(standaloneConfiguration);
        // jedisConnectionFactory.setPoolConfig(poolConfig(maxIdle, maxTotal, maxWaitMillis,minIdle));

        // 初始化
        jedisConnectionFactory.afterPropertiesSet();

        return jedisConnectionFactory;
    }

    public JedisPoolConfig poolConfig(int minIdle, int maxIdle, int maxTotal, long maxWaitMillis) {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxIdle(maxIdle);
        poolConfig.setMinIdle(minIdle);
        poolConfig.setMaxTotal(maxTotal);

        poolConfig.setMaxWait(Duration.ofMillis(maxWaitMillis));
        // 在空闲资源监测时通过ping命令监测连接有效性, 无效连接将被销毁, new JedisPoolConfig已设
        // poolConfig.setTestWhileIdle(true);

        return poolConfig;
    }

}
这里的设置是根据阿里云的建议设置的

然后在配置里配置对应的数据即可

redis.dev.host=localhost
redis.dev.port=6379
redis.dev.password=mypassword
redis.dev.database=1
redis.dev.pool.max-total=10
redis.dev.pool.min-idle=1
redis.dev.pool.max-idle=10
redis.dev.pool.max-wait=10000


redis.prod.host=localhost
redis.prod.port=6379
redis.prod.password=mypassword
redis.prod.database=2
redis.prod.pool.max-total=20
redis.prod.pool.min-idle=10
redis.prod.pool.max-idle=20
redis.prod.pool.max-wait=10000

然后正常使用即可

@Resource(name = "redisDevTemplate")
private RedisTemplate<String, Object> redisDevTemplate;

@Resource(name = "redisProdTemplate")
private RedisTemplate<String, Object> redisProdTemplate;