SpringBoot实现redis切换dbindex

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 在实际springboot集成redis使用过程中,针对不同类型的业务数据,可能存在不同的dbindex中,例如token存储db0,redis全局锁存储dbindex1,需要我们对RedisTemplate操作进行扩展,支持单次操作不同的dbindex

前言

在实际springboot集成redis使用过程中,针对不同类型的业务数据,可能存在不同的dbindex中,例如token存储db0,redis全局锁存储dbindex1,需要我们对RedisTemplate操作进行扩展,支持单次操作不同的dbindex

方案

系统加载时初始化根据redis使用库的dbindex,初始化对应个数的RedisTemplate,调用时根据dbindex获取对应的操作对象实例,本次实现是将15个db全部初始化

RedisRegist

初始化redis的Factory,线程池配置及RedisTemplate,StringRedisTemplate的Bean对象

public class RedisRegist implements EnvironmentAware,ImportBeanDefinitionRegistrar {
   
    private static final Logger logger = LoggerFactory.getLogger(RedisRegist.class);

    private static Map<String, Object> registerBean = new ConcurrentHashMap<>();

    private Environment environment;
    private Binder binder;


    @Override
    public void setEnvironment(Environment environment) {
   
        this.environment = environment;
        this.binder = Binder.get(this.environment);
    }


    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
   
        RedisEntity redisEntity;
        try {
   
            redisEntity = binder.bind("spring.redis", RedisEntity.class).get();
        } catch (NoSuchElementException e) {
   
            logger.error("redis not setting.");
            return;
        }
        boolean onPrimary = true;

        //根据多个库实例化出多个连接池和Template

        for (int i = 0; i < 15; i++) {
   
            int database = i;
            //单机模式
            RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
            configuration.setHostName(String.valueOf(redisEntity.getHost()));
            configuration.setPort(Integer.parseInt(String.valueOf(redisEntity.getPort())));
            configuration.setDatabase(database);
            String password = redisEntity.getPassword();
            if (password != null && !"".equals(password)) {
   
                RedisPassword redisPassword = RedisPassword.of(password);
                configuration.setPassword(redisPassword);
            }

            //池配置
            GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();

            RedisProperties.Pool pool = redisEntity.getLettuce().getPoolEntity();
            genericObjectPoolConfig.setMaxIdle(pool.getMaxIdle());
            genericObjectPoolConfig.setMaxTotal(pool.getMaxActive());
            genericObjectPoolConfig.setMinIdle(pool.getMinIdle());
            if (pool.getMaxWait() != null) {
   
                genericObjectPoolConfig.setMaxWaitMillis(pool.getMaxWait().toMillis());
            }
            Supplier<LettuceConnectionFactory> lettuceConnectionFactorySupplier = () -> {
   
                LettuceConnectionFactory factory = (LettuceConnectionFactory) registerBean.get("LettuceConnectionFactory" + database);
                if (factory != null) {
   
                    return factory;
                }
                LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder();
                Duration shutdownTimeout = redisEntity.getLettuce().getShutdownTimeout();
                if(shutdownTimeout == null){
   
                    shutdownTimeout = redisEntity.getTimeout();
                }
                if (shutdownTimeout != null) {
   
                    builder.shutdownTimeout(shutdownTimeout);
                }
                LettuceClientConfiguration clientConfiguration = builder.poolConfig(genericObjectPoolConfig).build();
                factory = new LettuceConnectionFactory(configuration, clientConfiguration);
                registerBean.put("LettuceConnectionFactory" + database, factory);
                return factory;
            };

            LettuceConnectionFactory lettuceConnectionFactory = lettuceConnectionFactorySupplier.get();
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(LettuceConnectionFactory.class, lettuceConnectionFactorySupplier);
            AbstractBeanDefinition factoryBean = builder.getRawBeanDefinition();
            factoryBean.setPrimary(onPrimary);
            registry.registerBeanDefinition("lettuceConnectionFactory" + database, factoryBean);
            // StringRedisTemplate
            GenericBeanDefinition stringRedisTemplate = new GenericBeanDefinition();
            stringRedisTemplate.setBeanClass(StringRedisTemplate.class);
            ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
            constructorArgumentValues.addIndexedArgumentValue(0, lettuceConnectionFactory);
            stringRedisTemplate.setConstructorArgumentValues(constructorArgumentValues);
            stringRedisTemplate.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);
            registry.registerBeanDefinition("stringRedisTemplate" + database, stringRedisTemplate);

            // 定义RedisTemplate对象
            GenericBeanDefinition redisTemplate = new GenericBeanDefinition();
            redisTemplate.setBeanClass(RedisTemplate.class);
            redisTemplate.getPropertyValues().add("connectionFactory", lettuceConnectionFactory);
            redisTemplate.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);


            RedisSerializer stringSerializer = new StringRedisSerializer();
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
            // key采用String的序列化方式,value采用json序列化方式
            redisTemplate.getPropertyValues().add("keySerializer",new StringRedisSerializer());
            redisTemplate.getPropertyValues().add("hashKeySerializer",stringSerializer);
            redisTemplate.getPropertyValues().add("valueSerializer",jackson2JsonRedisSerializer);
            redisTemplate.getPropertyValues().add("hashValueSerializer",stringSerializer);

            //注册Bean
            registry.registerBeanDefinition("redisTemplate" + database, redisTemplate);
            //logger.info("Registration redis ({}) !", database);
            if (onPrimary) {
   
                onPrimary = false;
            }
        }
    }

}

RedisManage

RedisTemplate,StringRedisTemplate的Bean对象统一管理定义

public class RedisManage {
   
    private Map<String, RedisTemplate> redisTemplateMap;

    private Map<String, StringRedisTemplate> stringRedisTemplateMap;

    public RedisManage(Map<String, RedisTemplate> redisTemplateMap,
                       Map<String, StringRedisTemplate> stringRedisTemplateMap) {
   
        this.redisTemplateMap = redisTemplateMap;
        this.stringRedisTemplateMap = stringRedisTemplateMap;
    }

    public RedisTemplate redisTemplate(int dbIndex) {
   
        RedisTemplate redisTemplate = redisTemplateMap.get("redisTemplate" + dbIndex);
        return redisTemplate;
    }

    public StringRedisTemplate stringRedisTemplate(int dbIndex) {
   
        StringRedisTemplate stringRedisTemplate = stringRedisTemplateMap.get("stringRedisTemplate" + dbIndex);
        stringRedisTemplate.setEnableTransactionSupport(true);
        return stringRedisTemplate;
    }

    public Map<String, RedisTemplate> getRedisTemplateMap() {
   
        return redisTemplateMap;
    }

    public Map<String, StringRedisTemplate> getStringRedisTemplateMap() {
   
        return stringRedisTemplateMap;
    }

}

RedisConfig

将操作类Bean对象注入道RedisManage中

@AutoConfigureBefore({RedisAutoConfiguration.class})
@Import(RedisRegist.class)
@Configuration
public class RedisConfig implements EnvironmentAware, ApplicationContextAware {
    private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);

    private static String key1 = "redisTemplate";
    private static String key2 = "stringRedisTemplate";

    Map<String, RedisTemplate> redisTemplateMap = new HashMap<>();
    Map<String, StringRedisTemplate> stringRedisTemplateMap = new HashMap<>();
    private Binder binder;
    private Environment environment;
    private ApplicationContext applicationContext;

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
        this.binder = Binder.get(this.environment);
    }
    @PostConstruct
    public Map<String,RedisTemplate> initRedisTemplate(){
        RedisEntity redisEntity;
        try {
            redisEntity = binder.bind("spring.redis", RedisEntity.class).get();
        } catch (NoSuchElementException e) {
            throw new RuntimeException("Failed to configure  spring.redis: 'spring.redis' attribute is not specified and no embedded redis could be configured.");
        }

        for (int i=0;i<15;i++){
            int database = i;
            String key = key1 + database;
            RedisTemplate redisTemplate = applicationContext.getBean(key , RedisTemplate.class);
            if(redisTemplate != null){
                redisTemplateMap.put(key , redisTemplate);
            }

            key = key2 + database;
            if(stringRedisTemplateMap != null){
                StringRedisTemplate stringRedisTemplate = applicationContext.getBean(key , StringRedisTemplate.class);
                stringRedisTemplateMap.put(key , stringRedisTemplate);
            }
        }

        if(redisTemplateMap.size() == 0 && stringRedisTemplateMap.size() == 0){
            throw new RuntimeException("load redisTemplate failure , please check spring.redis property config!!!");
        }
        return redisTemplateMap;
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Bean
    public RedisManage redisManage(){
        return new RedisManage(redisTemplateMap , stringRedisTemplateMap);
    }
}

RedisUtil

调用RedisManage封装具体相关操作调用

@Component
public class RedisUtil {
   
    @Autowired
    private RedisManage redisManage;
    private int defatuDBIndex= 0;

    public void redisTemplateSet(String key, Object value){
   
        ValueOperations<Object, Object> ops = redisManage.redisTemplate(defatuDBIndex).opsForValue();
        ops.set(key, value);
    }

    public void redisTemplateSet(String key, Object value,int dbIndex){
   
        ValueOperations<Object, Object> ops = redisManage.redisTemplate(dbIndex).opsForValue();
        ops.set(key, value);
    }

    public Object redisTemplateGet(String key){
   
        ValueOperations<Object, Object> ops = redisManage.redisTemplate(defatuDBIndex).opsForValue();
        return ops.get(key);
    }

    public Object redisTemplateGet(String key,int dbIndex){
   
        ValueOperations<Object, Object> ops = redisManage.redisTemplate(dbIndex).opsForValue();
        return ops.get(key);
    }

    public void redisTemplateRemove(String key){
   
        ValueOperations<Object, Object> ops = redisManage.redisTemplate(defatuDBIndex).opsForValue();
        ops.getOperations().delete(key);
    }

    public void redisTemplateRemove(String key,int dbIndex){
   
        ValueOperations<Object, Object> ops = redisManage.redisTemplate(dbIndex).opsForValue();
        ops.getOperations().delete(key);
    }

    public void redisTemplateSetForList(String key, Map<String,Object> map){
   
        HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(defatuDBIndex).opsForHash();
        ops.putAll(key,map);
    }

    public void redisTemplateSetForList(String key, Map<String,Object> map,int dbIndex){
   
        HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(dbIndex).opsForHash();
        ops.putAll(key,map);
    }

    public void redisTemplateSetForList(String key, String hashKey,Object value){
   
        HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(defatuDBIndex).opsForHash();
        ops.put(key,hashKey,value);
    }

    public void redisTemplateSetForList(String key, String hashKey,Object value,int dbIndex){
   
        HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(dbIndex).opsForHash();
        ops.put(key,hashKey,value);
    }

    public Map<Object, Object> redisTemplateGetForList(String key){
   
        HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(defatuDBIndex).opsForHash();
        return ops.entries(key);
    }

    public Map<Object, Object> redisTemplateGetForList(String key,int dbIndex){
   
        HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(dbIndex).opsForHash();
        return ops.entries(key);
    }

    public Object redisTemplateGetForList(String key,String hasKey){
   
        HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(defatuDBIndex).opsForHash();
        return ops.get(key,hasKey);
    }

    public Object redisTemplateGetForList(String key,String hasKey,int dbIndex){
   
        HashOperations<Object, Object,Object> ops = redisManage.redisTemplate(dbIndex).opsForHash();
        return ops.get(key,hasKey);
    }

    public  void setExpire(String key,long timeout, final TimeUnit unit,int dbIndex){
   
        redisManage.redisTemplate(dbIndex).expire(key,timeout, unit);
    }

    public  void setExpire(String key,long timeout, final TimeUnit unit){
   
        redisManage.redisTemplate(defatuDBIndex).expire(key,timeout, unit);
    }

    public boolean isValid(String key){
   
        boolean flag = false;
        if(  redisManage.redisTemplate(defatuDBIndex).hasKey(key)){
   
            if( redisManage.redisTemplate(defatuDBIndex).getExpire(key,TimeUnit.SECONDS)>0){
   
                flag = true;
            }
        }
        return flag;
    }

    public boolean isValid(String key,int dbIndex){
   
        boolean flag = false;
        if(  redisManage.redisTemplate(dbIndex).hasKey(key)){
   
            if( redisManage.redisTemplate(dbIndex).getExpire(key,TimeUnit.SECONDS)>0){
   
                flag = true;
            }
        }
        return flag;
    }
}
目录
相关文章
|
1月前
|
NoSQL Java 网络安全
SpringBoot启动时连接Redis报错:ERR This instance has cluster support disabled - 如何解决?
通过以上步骤一般可以解决由于配置不匹配造成的连接错误。在调试问题时,一定要确保服务端和客户端的Redis配置保持同步一致。这能够确保SpringBoot应用顺利连接到正确配置的Redis服务,无论是单机模式还是集群模式。
198 5
|
2月前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
206 0
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
8月前
|
NoSQL Java 关系型数据库
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Redis 介绍
本文介绍在 Spring Boot 中集成 Redis 的方法。Redis 是一种支持多种数据结构的非关系型数据库(NoSQL),具备高并发、高性能和灵活扩展的特点,适用于缓存、实时数据分析等场景。其数据以键值对形式存储,支持字符串、哈希、列表、集合等类型。通过将 Redis 与 Mysql 集群结合使用,可实现数据同步,提升系统稳定性。例如,在网站架构中优先从 Redis 获取数据,故障时回退至 Mysql,确保服务不中断。
341 0
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Redis 介绍
|
8月前
|
缓存 NoSQL Java
基于SpringBoot的Redis开发实战教程
Redis在Spring Boot中的应用非常广泛,其高性能和灵活性使其成为构建高效分布式系统的理想选择。通过深入理解本文的内容,您可以更好地利用Redis的特性,为应用程序提供高效的缓存和消息处理能力。
755 79
|
9月前
|
NoSQL Java Redis
Springboot使用Redis实现分布式锁
通过这些步骤和示例,您可以系统地了解如何在Spring Boot中使用Redis实现分布式锁,并在实际项目中应用。希望这些内容对您的学习和工作有所帮助。
915 83
|
5月前
|
机器学习/深度学习 数据采集 人机交互
springboot+redis互联网医院智能导诊系统源码,基于医疗大模型、知识图谱、人机交互方式实现
智能导诊系统基于医疗大模型、知识图谱与人机交互技术,解决患者“知症不知病”“挂错号”等问题。通过多模态交互(语音、文字、图片等)收集病情信息,结合医学知识图谱和深度推理,实现精准的科室推荐和分级诊疗引导。系统支持基于规则模板和数据模型两种开发原理:前者依赖人工设定症状-科室规则,后者通过机器学习或深度学习分析问诊数据。其特点包括快速病情收集、智能病症关联推理、最佳就医推荐、分级导流以及与院内平台联动,提升患者就诊效率和服务体验。技术架构采用 SpringBoot+Redis+MyBatis Plus+MySQL+RocketMQ,确保高效稳定运行。
417 0
|
8月前
|
存储 人工智能 NoSQL
SpringBoot整合Redis、ApacheSolr和SpringSession
本文介绍了如何使用SpringBoot整合Redis、ApacheSolr和SpringSession。SpringBoot以其便捷的配置方式受到开发者青睐,通过引入对应的starter依赖,可轻松实现功能整合。对于Redis,可通过配置RedisSentinel实现高可用;SpringSession则提供集群Session管理,支持多种存储方式如Redis;整合ApacheSolr时,借助Zookeeper搭建SolrCloud提高可用性。文中详细说明了各组件的配置步骤与代码示例,方便开发者快速上手。
165 11
|
10月前
基于springboot+thymeleaf+Redis仿知乎网站问答项目源码
基于springboot+thymeleaf+Redis仿知乎网站问答项目源码
315 36
|
8月前
|
NoSQL Java API
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Spring Boot 集成 Redis
本文介绍了在Spring Boot中集成Redis的方法,包括依赖导入、Redis配置及常用API的使用。通过导入`spring-boot-starter-data-redis`依赖和配置`application.yml`文件,可轻松实现Redis集成。文中详细讲解了StringRedisTemplate的使用,适用于字符串操作,并结合FastJSON将实体类转换为JSON存储。还展示了Redis的string、hash和list类型的操作示例。最后总结了Redis在缓存和高并发场景中的应用价值,并提供课程源代码下载链接。
2004 0
|
8月前
|
NoSQL Java Redis
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Redis 安装
本教程介绍在 VMware 虚拟机(CentOS 7)或阿里云服务器中安装 Redis 的过程,包括安装 gcc 编译环境、下载 Redis(官网或 wget)、解压安装、修改配置文件(如 bind、daemonize、requirepass 等设置)、启动 Redis 服务及测试客户端连接。通过 set 和 get 命令验证安装是否成功。适用于初学者快速上手 Redis 部署。
234 0