SpringBoot Redis 配置多数据源

这篇具有很好参考价值的文章主要介绍了SpringBoot Redis 配置多数据源。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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


SpringBoot Redis 配置多数据源,Redis从入门到精通2023版,spring boot,redis,java,缓存,后端
使用 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;
}

SpringBoot Redis 配置多数据源,Redis从入门到精通2023版,spring boot,redis,java,缓存,后端大家好,我是冰点,今天的Redis【实践篇】之SpringBoot Redis 配置多数据源,全部内容就是这些。如果你有疑问或见解可以在评论区留言。文章来源地址https://www.toymoban.com/news/detail-599074.html

到了这里,关于SpringBoot Redis 配置多数据源的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • springboot之多数据源配置

    实际开发中,进场可能遇到在一个引用中可能需要访问多个数据库的情况,以下是两种典型场景: 数据分布在不同的数据库汇总,数据库拆了,应用没拆。一个公司多个子项目,各用各的数据库,涉及数据共享。。。。 为了解决数据库的读性能瓶颈(读比写性能更高,写锁

    2024年02月07日
    浏览(41)
  • Springboot+Druid配置多数据源

    Spring的多数据源支持—AbstractRoutingDataSource,AbstractRoutingDataSource定义了抽象的determineCurrentLookupKey方法,子类实现此方法,来确定要使用的数据源 Druid 实现多数据源支持,核心是Overwrite AbstractRoutingDataSource 的 determineCurrentLookupKey 方法 以springboot框架为基础使用aop注解的方式依赖

    2024年02月11日
    浏览(52)
  • ruoyi(若依)配置多数据源(mysql+postgresql),rouyi(Springboot)多数据源设置

    (1)修改DatasourceType (2)修改DruidConfig,这里有很多细节要注意,就是大小写的问题 (3)使用选择数据源,会自动切换数据源

    2024年02月16日
    浏览(64)
  • SpringBoot整合Druid配置多数据源

    目录 1.初始化项目 1.1.初始化工程 1.2.添加依赖 1.3.配置yml文件 1.4.Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹 1.5.配置使用数据源 1.5.1.注解方式 1.5.2.基于AOP手动实现多数据源原生的方式 2.结果展示 Mybatis-Plus:简介 | MyBatis-Plus (baomidou.com) 在正式开始之前,先初始

    2024年02月01日
    浏览(54)
  • SpringBoot结合MyBatis实现多数据源配置

    SpringBoot框架实现多数据源操作,首先需要搭建Mybatis的运行环境。 由于是多数据源,也就是要有多个数据库,所以,我们创建两个测试数据库,分别是:【sp-demo01】和【sp-demo02】,如下图所示: 具体SQL代码: 创建【sp-demo01】数据库。 创建【sp-demo02】数据库。 MyBatis框架中,

    2024年02月09日
    浏览(38)
  • springboot+mybatis+pgsql多数据源配置

    jdk环境:1.8 配置了双数据源 pgsql+pgsql   第一个配置文件 :PrimaryDataSourceConfig 参数详情 :@Primary //指定你主要的数据源是哪一个 例如:我这里主要数据源是第一个配置文件 所以我的第二个配置文件并没有加这个注解 注意修改: @MapperScan里面的basePackages @ConfigurationProperties里面

    2024年02月03日
    浏览(104)
  • SpringBoot+mybatis+pgsql多个数据源配置

    jdk环境:1.8 配置了双数据源springboot+druid+pgsql,application.properties配置修改如下: 主数据库注入 从数据库Java代码:      这里就就不一一贴代码了,主要是接口对应mybatis xml配置文件。项目文件接口如下: 创建成以上目录就可以了,分别是dao接口、Java数据源配置、mybatis映射

    2024年02月11日
    浏览(38)
  • springboot整合druid及多数据源配置

    本篇主要分两部分 ①springboot整合druid的代码配置,以及druid的监控页面演示;②对实际场景中多数据源的配置使用进行讲解。 可以用idea快速生成一个可运行的demo工程,具体可以参考如何快速创建springboot项目 主要用到的依赖如下:  配置数据库需要的配置文件application.yml( 注

    2024年02月12日
    浏览(47)
  • springboot实现多数据源配置(Druid/Hikari)

    使用springboot+mybatis-plus+(Druid/Hikari)实现多数据源配置 操作步骤: 引入相应的maven坐标 编写mybatis配置,集成mybatis或mybatis-plus(如果已集成可跳过) 编写数据源配置类 编写注解,并通过aop进行增强(编写数据源切换代码) 类或方法中使用注解,对数据源进行切换 第一步:

    2024年02月13日
    浏览(52)
  • 【精·超详细】SpringBoot 配置多个数据源(连接多个数据库)

    目录 1.项目路径 2.pom.xml  引入依赖: 3.application.yml配置文件: 4.两个entity类 5.Conroller 6.两个Service以及两个ServiceImpl  7.两个Mapper及两个Mapper.xml  8.运行Application  然后在浏览器请求 9.查看两个数据库是否有新增数据           总结: 1.pom.xml 引入依赖: dynamic-datasource-spring-b

    2024年02月12日
    浏览(67)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包