关于springboot:SpringBoot实现redis切换dbindex

6次阅读

共计 10687 个字符,预计需要花费 27 分钟才能阅读完成。

前言

在理论 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;
    }
}
正文完
 0