zoukankan      html  css  js  c++  java
  • SpringBoot实现redis切换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;
        }
    }
    
  • 相关阅读:
    团队与领导力健康检查 | 体检表
    如何改变组织文化
    如何在各种文化背景下成功敏捷
    OKR痛点与误区 | 敏捷家分享007
    Scrum培训感想
    如何讲好故事
    Lc70_爬楼梯
    Lc641_设计循环双端队列
    Lc32_最长有效括号
    Lc239_滑动窗口最大值
  • 原文地址:https://www.cnblogs.com/yanpeng19940119/p/15202060.html
Copyright © 2011-2022 走看看