【实践篇】4.11 SpringBoot Redis 配置多数据源

Redis 从入门到精通【应用篇】之SpringBoot Redis 配置多数据源


在这里插入图片描述
使用 RedisTemplate 支持多个 Redis 数据库

0. Redis从入门到精通系列文章

  1. 《Redis 从入门到精通【进阶篇】之Lua脚本详解》
  2. 《Redis 从入门到精通【实践篇】SpringBoot Redis 配置多数据源》
  3. 《Redis 从入门到精通【进阶篇】三分钟了解Redis地理位置数据结构GeoHash》
  4. 《Redis 从入门到精通【进阶篇】一文学会Lua脚本》
  5. 《Redis使用Lua脚本和Redisson来保证库存扣减中的原子性和一致性》
  6. 《SpringBoot Redis 使用Lettuce和Jedis配置哨兵模式》
  7. 《Redis【应用篇】之RedisTemplate基本操作》
  8. 《Redis 从入门到精通【实践篇】之SpringBoot配置Redis多数据源》
  9. 《Redis 从入门到精通【进阶篇】之三分钟了解Redis HyperLogLog 数据结构》
  10. 《Redis 从入门到精通【进阶篇】之三分钟了解Redis地理位置数据结构GeoHash》
  11. 《Redis 从入门到精通【进阶篇】之高可用哨兵机制(Redis Sentinel)详解》
  12. 《Redis 从入门到精通【进阶篇】之redis主从复制详解》
  13. 《Redis 从入门到精通【进阶篇】之Redis事务详解》
  14. 《Redis从入门到精通【进阶篇】之对象机制详解》
  15. 《Redis从入门到精通【进阶篇】之消息传递发布订阅模式详解》
  16. 《Redis从入门到精通【进阶篇】之持久化 AOF详解》
  17. 《Redis从入门到精通【进阶篇】之持久化RDB详解》
  18. 《Redis从入门到精通【高阶篇】之底层数据结构字典(Dictionary)详解》
  19. 《Redis从入门到精通【高阶篇】之底层数据结构快表QuickList详解》
  20. 《Redis从入门到精通【高阶篇】之底层数据结构简单动态字符串(SDS)详解》
  21. 《Redis从入门到精通【高阶篇】之底层数据结构压缩列表(ZipList)详解》
  22. 《Redis从入门到精通【进阶篇】之数据类型Stream详解和使用示例》

感谢@爱喝茶同学和其他几位同学的问题反馈。对Redis多数据源进行了改造升级,兼容不同版本和硬编码配置项的问题,将Jedis 替换为Lettuce, 支持<=Spring boot 2.7.12

1.教程

0. 添加依赖

在项目中使用 RedisTemplate 支持多个 Redis 数据库之前,需要先添加 Spring Data Redis 的依赖。在 Maven 项目中,可以通过在 pom.xml 文件中添加以下依赖来引入 Spring Data Redis:

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

<spring-boot.version>2.7.12</spring-boot.version>

1. 配置多个 Redis 连接信息

在 Spring Boot 中,可以通过在 application.properties 或 application.yml 文件中指定不同的 Redis 连接信息来配置多个 RedisConnectionFactory 实例,并通过 @Bean 注解将它们注入到 RedisTemplate 中,例如:
Redis的常用配置大概是这些

# Redis 服务器的主机名或 IP 地址
spring.redis.host=127.0.0.1

# Redis 服务器的端口号
spring.redis.port=6379

# Redis 服务器的密码,如果没有设置密码,则为空字符串
spring.redis.password=

# Redis 数据库的编号,默认为 0
spring.redis.database=0

# Redis 服务器连接超时时间(毫秒),默认为 5000 毫秒
spring.redis.timeout=5000

# 连接池最大连接数,即最多允许多少个客户端同时连接到 Redis 服务器
spring.redis.pool.max-active=8

# 连接池中最大空闲连接数,即在连接池中最多允许多少个连接处于空闲状态
spring.redis.pool.max-idle=8

# 连接池中最小空闲连接数,即在连接池中最少保持多少个连接处于空闲状态
spring.redis.pool.min-idle=0

# 连接池最大等待时间(毫秒),即当连接池中的连接全部被占用时,新的连接请求最多等待多长时间
# 如果设置为-1,则表示无限等待
spring.redis.pool.max-wait=-1

# 是否启用 SSL 加密连接,默认为 false
spring.redis.ssl=false

我们将上面的配置改造一下,支持Redis多数据源

有同学反馈之前的写法有两方面问题,配置写死了,新增一个Redis 实例,需要改代码。还有一个问题是如果没有排除spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration 会报错
所以本次进行修正。将配置支持不限个数的Redis数据源,将Jedis 客户端改为了lettuce Spring boot版本升级为<spring-boot.version>2.7.12</spring-boot.version>



# 配置 Redis 数据库 主数据源
spring.redis.master.host=172.0.0.1
spring.redis.master.port=6379
spring.redis.master.password=
spring.redis.master.database=15
spring.redis.master.timeout=5000
spring.redis.master.pool.max-active=8
spring.redis.master.pool.max-idle=8
spring.redis.master.pool.min-idle=0
spring.redis.master.pool.max-wait=-1
spring.redis.master.ssl=false

# 配置 Redis 数据库 0

spring.redis.database0.host=172.0.0.1
spring.redis.database0.port=6379
spring.redis.database0.password=
spring.redis.database0.database=0
spring.redis.database0.timeout=5000
spring.redis.database0.pool.max-active=8
spring.redis.database0.pool.max-idle=8
spring.redis.database0.pool.min-idle=0
spring.redis.database0.pool.max-wait=-1
spring.redis.database0.ssl=false

# 配置 Redis 数据库 1
spring.redis.database1.host=172.0.0.1
spring.redis.database1.port=6379
spring.redis.database1.password=
spring.redis.database1.database=1
spring.redis.database1.timeout=5000
spring.redis.database1.pool.max-active=8
spring.redis.database1.pool.max-idle=8
spring.redis.database1.pool.min-idle=0
spring.redis.database1.pool.max-wait=-1
spring.redis.database1.ssl=false

2. 配置

@ConfigurationProperties(prefix = "spring.redis.database0")@ConfigurationProperties(prefix = "spring.redis.database1") 注解来将不同的 Redis 配置注入到 Java 类中,例如:

 package com.icepip.project;

import com.alibaba.nacos.common.utils.StringUtils;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.data.redis.connection.*;
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 org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Configuration
@ConfigurationProperties(prefix = "spring")
public class RedisConfig implements ApplicationContextAware, InitializingBean, BeanPostProcessor {
    /**
     * 将多个Redis 数据源的配置信息放到一个Map中,然后遍历Map 创建不同的RedisTemplate实例
     * Map<String, Map<String, Object>> redis 中的 key 为配置的spring.redis.xx  xx为key  value xx一组的值组装成了map
     * 创建的RedisTemplate实例的名称为 xxRedisTemplate
     */
    protected static Map<String, Map<String, Object>> redis = new HashMap<>();
    // 配置主数据源
    @Value("${primary.redis.key:master}")
    private String primaryKey;
    private static ApplicationContext applicationContext;

    public RedisConfig() {
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        RedisConfig.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() {
        redis.forEach((k, v) -> {
            if (Objects.equals(k, this.primaryKey)) {
                Map<String, Object> paramMap = new HashMap(4);
                v.forEach((k1, v1) -> {
                    paramMap.put("spring.redis." + k1, v1);
                });
                MapPropertySource mapPropertySource = new MapPropertySource("redisAutoConfigProperty", paramMap);
                ((StandardEnvironment) applicationContext.getEnvironment()).getPropertySources().addLast(mapPropertySource);
            }
            RedisConnectionFactory lettuceConnectionFactory = this.buildLettuceConnectionFactory(k, v, this.buildGenericObjectPoolConfig(k, v));
            this.buildRedisTemplate(k, lettuceConnectionFactory);
            this.buildStringRedisTemplate(k, lettuceConnectionFactory);
        });
    }


    @Bean
    public RedisTemplate<Object, Object> redisTemplate() {
        Map<String, Object> redisParam = redis.get(this.primaryKey);
        GenericObjectPoolConfig<?> genericObjectPoolConfig = this.buildGenericObjectPoolConfig(this.primaryKey, redisParam);
        RedisConnectionFactory lettuceConnectionFactory = this.buildLettuceConnectionFactory(this.primaryKey, redisParam, genericObjectPoolConfig);
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(lettuceConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    public StringRedisTemplate stringRedisTemplate() {
        Map<String, Object> redisParam = redis.get(this.primaryKey);
        GenericObjectPoolConfig<?> genericObjectPoolConfig = this.buildGenericObjectPoolConfig(this.primaryKey, redisParam);
        RedisConnectionFactory lettuceConnectionFactory = this.buildLettuceConnectionFactory(this.primaryKey, redisParam, genericObjectPoolConfig);
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(lettuceConnectionFactory);
        return template;
    }


    private void buildStringRedisTemplate(String k, RedisConnectionFactory lettuceConnectionFactory) {
        ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
        constructorArgumentValues.addIndexedArgumentValue(0, lettuceConnectionFactory);
        this.setCosBean(k + "StringRedisTemplate", StringRedisTemplate.class, constructorArgumentValues);
    }

    private void buildRedisTemplate(String k, RedisConnectionFactory lettuceConnectionFactory) {
        Jackson2JsonRedisSerializer<?> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);
        Map<String, Object> original = new HashMap<>(2);
        original.put("connectionFactory", lettuceConnectionFactory);
        original.put("valueSerializer", serializer);
        original.put("keySerializer", new StringRedisSerializer());
        original.put("hashKeySerializer", new StringRedisSerializer());
        original.put("hashValueSerializer", serializer);
        this.setBean(k + "RedisTemplate", RedisTemplate.class, original);
    }

    public GenericObjectPoolConfig<?> buildGenericObjectPoolConfig(String redisKey, Map<String, Object> param) {
        GenericObjectPoolConfig<?> result;
        if (applicationContext.containsBean(redisKey + "GenericObjectPoolConfig")) {
            result = getBean(redisKey + "GenericObjectPoolConfig");
        } else {
            Map<String, Object> original = new HashMap<>(8);
            original.put("maxTotal", param.getOrDefault("maxTotal", 8));
            original.put("maxIdle", param.getOrDefault("maxIdle", 8));
            original.put("minIdle", param.getOrDefault("minIdle", 0));
            original.put("maxWaitMillis", param.getOrDefault("maxWaitMillis", -1L));
            original.put("testOnBorrow", param.getOrDefault("testOnBorrow", Boolean.FALSE));
            this.setBean(redisKey + "GenericObjectPoolConfig", GenericObjectPoolConfig.class, original);
            result = getBean(redisKey + "GenericObjectPoolConfig");
        }


        return result;
    }

    public RedisConnectionFactory buildLettuceConnectionFactory(String redisKey, Map<String, Object> param, GenericObjectPoolConfig genericObjectPoolConfig) {
        if (!applicationContext.containsBean(redisKey + "redisConnectionFactory")) {
            long timeout = Long.parseLong((String) param.getOrDefault("timeout", "3000"));
            LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder().commandTimeout(Duration.ofMillis(timeout)).poolConfig(genericObjectPoolConfig).build();
            RedisConfiguration firstArgument = null;
            // 根据配置项判断是否是集群或者哨兵或者单机
            if (this.isCluster(param)) {
                firstArgument = this.buildClusterConfig(param);
            } else if (this.isSentinel(param)) {
                firstArgument = this.buildSentinelConfig(param);
            } else {
                firstArgument = this.buildStandaloneConfig(param);
            }

            ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
            constructorArgumentValues.addIndexedArgumentValue(0, firstArgument);
            constructorArgumentValues.addIndexedArgumentValue(1, clientConfig);
            this.setCosBean(redisKey + "redisConnectionFactory", LettuceConnectionFactory.class, constructorArgumentValues);
        }
        return getBean(redisKey + "redisConnectionFactory");
    }


    private RedisStandaloneConfiguration buildStandaloneConfig(Map<String, Object> param) {
        RedisStandaloneConfiguration standaloneConfig = new RedisStandaloneConfiguration();
        standaloneConfig.setHostName(String.valueOf(param.get("host")));
        standaloneConfig.setDatabase(Integer.parseInt((String) param.get("database")));
        standaloneConfig.setPort(Integer.parseInt((String) param.get("port")));
        standaloneConfig.setPassword(RedisPassword.of((String) param.get("password")));
        return standaloneConfig;
    }

    private RedisSentinelConfiguration buildSentinelConfig(Map<String, Object> param) {
        RedisSentinelConfiguration config = new RedisSentinelConfiguration();
        // todo 如果是哨兵模式需要要在此处额外的配置,可以完善
        return config;
    }

    private RedisClusterConfiguration buildClusterConfig(Map<String, Object> param) {
        RedisClusterConfiguration config = new RedisClusterConfiguration();
        // todo 如果是Cluster模式需要在此处额外的配置,可以完善
        return config;
    }


    private static void checkApplicationContext() {
        if (applicationContext == null) {
            throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextUtil");
        }
    }

    public static <T> T getBean(String name) {
        checkApplicationContext();
        return applicationContext.containsBean(name) ? (T) applicationContext.getBean(name) : null;
    }


    public synchronized void setBean(String beanName, Class<?> clazz, Map<String, Object> original) {
        checkApplicationContext();
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
        if (!beanFactory.containsBean(beanName)) {
            GenericBeanDefinition definition = new GenericBeanDefinition();
            definition.setBeanClass(clazz);
            if (beanName.startsWith(this.primaryKey)) {
                definition.setPrimary(true);
            }
            definition.setPropertyValues(new MutablePropertyValues(original));
            beanFactory.registerBeanDefinition(beanName, definition);
        }
    }

    public synchronized void setCosBean(String beanName, Class<?> clazz, ConstructorArgumentValues original) {
        checkApplicationContext();
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
        if (!beanFactory.containsBean(beanName)) {
            GenericBeanDefinition definition = new GenericBeanDefinition();
            definition.setBeanClass(clazz);
            if (beanName.startsWith(this.primaryKey)) {
                definition.setPrimary(true);
            }

            definition.setConstructorArgumentValues(new ConstructorArgumentValues(original));
            beanFactory.registerBeanDefinition(beanName, definition);
        }
    }

    private boolean isSentinel(Map<String, Object> param) {
        String sentinelMaster = (String) param.get("sentinel.master");
        String sentinelNodes = (String) param.get("sentinel.nodes");
        return StringUtils.isNotEmpty(sentinelMaster) && StringUtils.isNotEmpty(sentinelNodes);
    }

    private boolean isCluster(Map<String, Object> param) {
        String clusterNodes = (String) param.get("cluster.nodes");
        return StringUtils.isNotEmpty(clusterNodes);
    }


    public Map<String, Map<String, Object>> getRedis() {
        return redis;
    }
}

使用 @ConfigurationProperties(prefix = "spring") 注解将不同的redis Map配置 实例中,并通过动态构造 RedisTemplate 实例.并且放置到Spring容器中, 这样,在代码中就可以通过 @Qualifier 注解来注入不同的 RedisTemplate 实例,从而访问不同的 Redis 数据库。还有同学反馈 需要有个主Redis 实例,所以又把RedisTemplate 手动构造了一份放置容器

3. 使用 RedisTemplate 实例

在 Spring Boot 中,可以通过 @Qualifier@Autowired 注解将不同的 RedisTemplate 实例注入到 Java 类中,例如:

   @RestController
public class ConsumerController {

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    private StringRedisTemplate  stringRedisTemplate;
    @Autowired
    @Qualifier("database0RedisTemplate")
    private RedisTemplate<Object, Object> redisTemplate0;

    @Autowired
    @Qualifier("database1RedisTemplate")
    private RedisTemplate<Object, Object> redisTemplate1;

    @Autowired
    @Qualifier("database0StringRedisTemplate")
    private StringRedisTemplate stringRedisTemplate0;

    @Autowired
    @Qualifier("database1StringRedisTemplate")
    private StringRedisTemplate stringRedisTemplate1;

    @GetMapping("/call")
    public String call() {
        return "call";
    }

    @GetMapping("/save")
    public String save() {
        return "save";
    }
}

4. 使用 RedisTemplate 操作 Redis

在 RedisTemplate 中,提供了一系列方法来操作 Redis,例如:

// 存储数据到 Redis 数据库 0
redisTemplate0.opsForValue().set("key0", "value0");
// 获取数据从 Redis 数据库 0
Object value0 = redisTemplate0.opsForValue().get("key0");
// 删除数据从 Redis 数据库 0
redisTemplate0.delete("key0");

// 存储数据到 Redis 数据库 1
redisTemplate1.opsForValue().set("key1", "value1");
// 获取数据从 Redis 数据库 1
Object value1 = redisTemplate1.opsForValue().get("key1");
// 删除数据从 Redis 数据库 1
redisTemplate1.delete("key1");

2. 常见问题

按照之前版本在使用 Spring Boot 中的 Redis 进行多数据源配置时,可能会遇到以下几个常见问题,新版本应该不会遇到,已经做了兼容。

2.1. RedisTemplate 实例重名问题

在配置多个 Redis 数据库时,需要为每个 Redis 数据库创建一个 RedisTemplate 实例。如果不同的 RedisTemplate 实例的名称相同,可能会导致实例重名的问题,进而导致应用程序无法启动。为每个 RedisTemplate 实例指定不同的名称。例如,可以在配置类中通过 @Bean 注解为每个 RedisTemplate 实例指定名称

@Bean(name = "redisTemplate0")
public RedisTemplate<String, Object> redisTemplate0(RedisConnectionFactory redisConnectionFactory0) {
    RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
    redisTemplate.setConnectionFactory(redisConnectionFactory0);
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
    redisTemplate.afterPropertiesSet();
    return redisTemplate;
}

@Bean(name = "redisTemplate1")
public RedisTemplate<String, Object> redisTemplate1(RedisConnectionFactory redisConnectionFactory1) {
    RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
    redisTemplate.setConnectionFactory(redisConnectionFactory1);
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
    redisTemplate.afterPropertiesSet();
    return redisTemplate;
}

在上面的代码中,我们分别为两个 RedisTemplate 实例指定了不同的名称,分别为 “redisTemplate0” 和 “redisTemplate1”。

2.2. RedisConnectionFactory 实例重用问题

在配置多个 Redis 数据库时,需要为每个 Redis 数据库创建一个 RedisConnectionFactory 实例。如果多个 RedisConnectionFactory 实例使用了同一个 Redis 连接池,可能会导致实例重用的问题,进而导致应用程序无法启动。可以为每个 RedisConnectionFactory 实例配置不同的 Redis 连接池。例如,可以在配置类中创建不同的 RedisConnectionFactory 实例,并分别为它们配置不同的 Redis 连接池

@Bean(name = "redisConnectionFactory0")
public RedisConnectionFactory redisConnectionFactory0() {
    RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
    config.setHostName("localhost");
    config.setPort(6379);
    config.setPassword(RedisPassword.of("password"));
    LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(config);
    connectionFactory.setDatabase(0);
    connectionFactory.afterPropertiesSet();
    return connectionFactory;
}

@Bean(name = "redisConnectionFactory1")
public RedisConnectionFactory redisConnectionFactory1() {
    RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
    config.setHostName("localhost");
    config.setPort(6379);
    config.setPassword(RedisPassword.of("password"));
    LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(config);
    connectionFactory.setDatabase(1);
    connectionFactory.afterPropertiesSet();
    return connectionFactory;
}

2.3. 数据库编号配置问题

在配置多个 Redis 数据库时,需要为每个 Redis 数据库指定不同的数据库编号。如果多个 Redis 数据库使用了同一个数据库编号,可能会导致数据被覆盖或丢失。为了解决这个问题,可以为每个 RedisConnectionFactory 实例配置不同的数据库编号。例如,可以在 RedisStandaloneConfiguration 中指定不同的数据库编号

@Bean(name = "redisConnectionFactory0")
public RedisConnectionFactory redisConnectionFactory0() {
    RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
    config.setHostName("localhost");
    config.setPort(6379);
    config.setPassword(RedisPassword.of("password"));
    config.setDatabase(0);
    LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(config);
    connectionFactory.afterPropertiesSet();
    return connectionFactory;
}

@Bean(name = "redisConnectionFactory1")
public RedisConnectionFactory redisConnectionFactory1() {
    RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
    config.setHostName("localhost");
    config.setPort(6379);
    config.setPassword(RedisPassword.of("password"));
    config.setDatabase(1);
    LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(config);
    connectionFactory.afterPropertiesSet();
    return connectionFactory;
}

2.4. RedisTemplate 序列化问题

在使用 RedisTemplate 时,需要对数据进行序列化和反序列化。如果不同的 Redis 数据库使用了不同的序列化方式,可能会导致数据无法正常读写。每个 RedisTemplate 实例指定不同的序列化器。例如,可以为每个 RedisTemplate 实例分别设置不同的 keySerializer 和 valueSerializer 。但是通常情况下我们的的项目中的序列化方式都是一致的,除非是在连别的项目的Redis时候人家已经按自己的序列化方式将值已经写入,我们只能按照对接方的方式配置序列化。

@Bean(name = "redisTemplate0")
public RedisTemplate<String, Object> redisTemplate0(RedisConnectionFactory redisConnectionFactory0) {
    RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
    redisTemplate.setConnectionFactory(redisConnectionFactory0);
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
    redisTemplate.afterPropertiesSet();
    return redisTemplate;
}

@Bean(name = "redisTemplate1")
public RedisTemplate<String, Object> redisTemplate1(RedisConnectionFactory redisConnectionFactory1) {
    RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
    redisTemplate.setConnectionFactory(redisConnectionFactory1);
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    redisTemplate.afterPropertiesSet();
    return redisTemplate;
}

在这里插入图片描述大家好,我是冰点,今天的Redis【实践篇】之SpringBoot Redis 配置多数据源,全部内容就是这些。如果你有疑问或见解可以在评论区留言。

  • 27
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 44
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 44
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰点.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值