SpringBoot2.0Redis配置

项目升级到2.0之后,有些配置发生了变化
在springboot2.0之后, springbootredis默认使用Lettuce, springbootredis1.0使用jedis

Jedis和Lettuce都是Redis Client
Jedis 是直连模式,在多个线程间共享一个 Jedis 实例时是线程不安全的,
如果想要在多线程环境下使用 Jedis,需要使用连接池,
每个线程都去拿自己的 Jedis 实例,当连接数量增多时,物理连接成本就较高了。
Lettuce的连接是基于Netty的,连接实例可以在多个线程间共享,
所以,一个多线程的应用可以使用同一个连接实例,而不用担心并发线程的数量。
当然这个也是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。
通过异步的方式可以让我们更好的利用系统资源,而不用浪费线程等待网络或磁盘I/O。
Lettuce 是基于 netty 的,netty 是一个多线程、事件驱动的 I/O 框架,
所以 Lettuce 可以帮助我们充分利用异步的优势。

具体代码如下:

package com.kmind;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.kmind.base.util.JsonKit;
import com.kmind.chuqu.util.GenJsonPoint_Fastjson_Deserialize;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

import java.time.Duration;


/**
 * @author:liupengfei
 * @createTime: 2019-10-14
 * @discription: redis配置
 * @package:
 * @project:
 **/
@Configuration
@EnableAutoConfiguration
@EnableCaching
public class LettuceRedisConfig {

    @Value("${kmind.redis.host}")
    private String host;
    @Value("${kmind.redis.port}")
    private int port;
    @Value("${kmind.redis.timeout}")
    private int timeout;
    @Value("${kmind.redis.password}")
    private String password;
    @Value("${kmind.redis.db}")
    private int dbNum;

    /**
     * 连接池配置
     *
     * @return
     */
    @Bean
    public GenericObjectPoolConfig getRedisConfig() {
        GenericObjectPoolConfig config =
                new GenericObjectPoolConfig();
        config.setMaxIdle(20);
        config.setMinIdle(5);
        config.setMaxTotal(20);
        config.setMaxWaitMillis(10000);
        return config;
    }

    /**
     * 连接工厂类
     *
     * @param config
     * @return
     */
    @Bean
    public LettuceConnectionFactory getConnectionFactory(GenericObjectPoolConfig config) {
        /**
         * redis链接配置
         */
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(host, port);
        configuration.setPassword(RedisPassword.of(password));
        configuration.setDatabase(dbNum);
        System.out.println("-----------------------------------------------------");
        System.out.println("host:" + configuration.getHostName());
        System.out.println("---------------redis--------------------------");

        /**
         * 配置连接池
         */
        LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder
                builder = LettucePoolingClientConfiguration.builder().
                commandTimeout(Duration.ofMillis(10000));

        builder.shutdownTimeout(Duration.ofMillis(10000));
        builder.poolConfig(config);
        LettuceClientConfiguration lettuceClientConfiguration = builder.build();

        /**
         * 根据配置和客户端配置创建连接
         */
        LettuceConnectionFactory factory = new LettuceConnectionFactory(configuration, lettuceClientConfiguration);
        factory.afterPropertiesSet();

        return factory;
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate(GenericObjectPoolConfig config) {
        LettuceConnectionFactory factory = getConnectionFactory(config);
        StringRedisTemplate template = new StringRedisTemplate(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = JsonKit.intMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(Point.class, new GenJsonPoint_Fastjson_Deserialize());
        objectMapper.registerModule(module);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    @Bean
    public StringRedisTemplate stringRedisTemplate(GenericObjectPoolConfig config) {
        LettuceConnectionFactory factory = getConnectionFactory(config);
        StringRedisTemplate template = new StringRedisTemplate(factory);
        return template;
    }

    @Bean
    public CacheManager cacheManager(GenericObjectPoolConfig config) {

        RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
        configuration.usePrefix();
        configuration.computePrefixWith(new RedisPrefix("prefix"));
        // 整体缓存过期时间
        configuration.entryTtl(Duration.ofMillis(3600));

        RedisCacheManager manager = new RedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(getConnectionFactory(config)), configuration);

        manager.afterPropertiesSet();
        return manager;
    }
}