千家信息网

springboot中怎么配置创建多个redis

发表于:2025-01-27 作者:千家信息网编辑
千家信息网最后更新 2025年01月27日,这篇文章将为大家详细讲解有关springboot中怎么配置创建多个redis,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。以下是配置的定义规范:spr
千家信息网最后更新 2025年01月27日springboot中怎么配置创建多个redis

这篇文章将为大家详细讲解有关springboot中怎么配置创建多个redis,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

以下是配置的定义规范:

spring:  redis:      timeout:  1000    lettuce:      pool:         maxActive: 2500        max-wait: 6000        max-idle: 500        min-idle: 100    sentinels:       temp1:        master: a        nodes:  ip1:10201,ip2:10202        password:       temp2:        master: b        nodes:  ip3:10201,ip4:10202        password:        primary: true //是否主要的bean

配置中其他的redis配置还是遵循springboot官方的,但另外扩展了一个sentinels属性,这个属性填充多个redis 配置信息,由于我们项目主要使用哨兵模式,故这里使用sentinel方式实现。

其次配置类根据上面的配置信息可以定义了:

@ConfigurationProperties(prefix = "spring.redis.sentinels")public class RedisExtProperties extends HashMap{        private static final long serialVersionUID = 856175258267105532L;        public static class ExtSentinel extends Sentinel {                private String password;                private boolean primary;                public String getPassword() {                        return password;                }                public void setPassword(String password) {                        this.password = password;                }                public boolean isPrimary() {                        return primary;                }                public void setPrimary(boolean primary) {                        this.primary = primary;                }        }}

以上是获取配置信息的配置类了,接下来要通过某些手段去生成StringRedisTemplate的bean了,由于有多个bean,而且bean的名称要自己通过配置文件中定义的,通过注解@Bean或者xml等方式貌似都无法达到目的,这里就利用BeanDefinitionRegistryPostProcessor接口去实现,该接口怎么使用可以去查看spring的一些文档或者网上搜索都可以找到,这里不在赘述。

这个接口有两个方法postProcessBeanFactory、postProcessBeanDefinitionRegistry,这两个方法都可以实现动态注册bean,大家也可以去网上搜索,但是呢,这里却不能通过这两个方法去实现动态注册StringRedisTemplate的bean,因为在初始化BeanDefinitionRegistryPostProcessor这个接口的实现时,还并没有完全加载springboot的相关配置,导致在这两个方法里或者通过注解@Autowired都无法把RedisExtProperties注入进来,即便注入进来,也是没有把相关配置信息初始化进去的,这把就坑了,后面想了半天直接通过AutowiredAnnotationBeanPostProcessor这个实现,重写它的postProcessProperties方法去触发动态注册bean。

@Componentpublic class RedisCustomFactory extends AutowiredAnnotationBeanPostProcessor                implements BeanDefinitionRegistryPostProcessor {        private final Logger logger = LoggerFactory.getLogger(getClass());        BeanDefinitionRegistry registry;        ConfigurableListableBeanFactory factory;        AtomicBoolean open = new AtomicBoolean(false);        @Override        public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {                if (!open.get()) {                        processFields(bean, bean.getClass().getDeclaredFields());                }                return super.postProcessProperties(pvs, bean, beanName);        }        private void processFields(Object bean, Field[] declaredFields) {                for (Field field : declaredFields) {                        if (!open.get() && field.getType().isAssignableFrom(RedisOperations.class)) {                                register(factory.getBean(RedisProperties.class), factory.getBean(RedisExtProperties.class),                                                factory.getBeanProvider(LettuceClientConfigurationBuilderCustomizer.class));                                open.compareAndSet(false, true);                        }                }        }        private LettuceClientConfigurationBuilder createBuilder(Pool pool) {                if (pool == null) {                        return LettuceClientConfiguration.builder();                }                return new PoolBuilderFactory().createBuilder(pool);        }//      private void customize(LettuceClientConfiguration.LettuceClientConfigurationBuilder builder,//                      ObjectProvider builderCustomizers) {//              builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));//      }        private LettuceClientConfigurationBuilder applyProperties(                        LettuceClientConfiguration.LettuceClientConfigurationBuilder builder, RedisProperties properties) {                if (properties.isSsl()) {                        builder.useSsl();                }                if (properties.getTimeout() != null) {                        builder.commandTimeout(properties.getTimeout());                }                if (properties.getLettuce() != null) {                        RedisProperties.Lettuce lettuce = properties.getLettuce();                        if (lettuce.getShutdownTimeout() != null && !lettuce.getShutdownTimeout().isZero()) {                                builder.shutdownTimeout(properties.getLettuce().getShutdownTimeout());                        }                }                return builder;        }        private LettuceClientConfiguration getLettuceClientConfiguration(ClientResources clientResources, Pool pool,                        RedisProperties properties,                        ObjectProvider builderCustomizers) {                LettuceClientConfigurationBuilder builder = createBuilder(pool);                applyProperties(builder, properties);                builder.clientResources(clientResources);//              customize(builder, builderCustomizers);                return builder.build();        }        private List createSentinels(RedisProperties.Sentinel sentinel) {                List nodes = new ArrayList<>();                for (String node : sentinel.getNodes()) {                        try {                                String[] parts = StringUtils.split(node, ":");                                Assert.state(parts.length == 2, "Must be defined as 'host:port'");                                nodes.add(new RedisNode(parts[0], Integer.valueOf(parts[1])));                        } catch (RuntimeException ex) {                                throw new IllegalStateException("Invalid redis sentinel " + "property '" + node + "'", ex);                        }                }                return nodes;        }        protected RedisSentinelConfiguration getSentinelConfig(ExtSentinel sentinelProperties, RedisProperties properties) {                if (sentinelProperties != null) {                        RedisSentinelConfiguration config = new RedisSentinelConfiguration();                        config.master(sentinelProperties.getMaster());                        config.setSentinels(createSentinels(sentinelProperties));                        if (sentinelProperties.getPassword() != null) {                                config.setPassword(RedisPassword.of(sentinelProperties.getPassword()));                        }                        config.setDatabase(properties.getDatabase());                        return config;                }                return null;        }        private LettuceConnectionFactory createLettuceConnectionFactory(LettuceClientConfiguration clientConfiguration,                        RedisSentinelConfiguration redisSentinelConfiguration, RedisProperties properties) {                return new LettuceConnectionFactory(redisSentinelConfiguration, clientConfiguration);        }        private LettuceConnectionFactory redisConnectionFactory(ClientResources clientResources,                        RedisSentinelConfiguration redisSentinelConfiguration, RedisProperties properties,                        ObjectProvider builderCustomizers)                        throws UnknownHostException {                LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(clientResources,                                properties.getLettuce().getPool(), properties, null);                return createLettuceConnectionFactory(clientConfig, redisSentinelConfiguration, properties);        }        public synchronized void register(RedisProperties properties, RedisExtProperties extProperties,                        ObjectProvider builderCustomizers) throws BeansException {                if (extProperties == null) {                        return;                }                extProperties.forEach((name, sentinel) -> {                        try {                                if (!factory.containsBeanDefinition(name + "RedisTemplate")) {                                        logger.info("{} -----> {}", name, sentinel.isPrimary());                                        DefaultClientResources res = DefaultClientResources.create();                                        BeanDefinitionBuilder builder0 = BeanDefinitionBuilder                                                        .genericBeanDefinition(DefaultClientResources.class, () -> res);                                        BeanDefinition beanDefinition0 = builder0.getRawBeanDefinition();                                        beanDefinition0.setPrimary(sentinel.isPrimary());                                        beanDefinition0.setDestroyMethodName("shutdown");                                        registry.registerBeanDefinition(name + "DefaultClientResources", beanDefinition0);                                        LettuceConnectionFactory ref = redisConnectionFactory(res, getSentinelConfig(sentinel, properties),                                                        properties, builderCustomizers);                                        BeanDefinitionBuilder builder1 = BeanDefinitionBuilder                                                        .genericBeanDefinition(RedisConnectionFactory.class, () -> ref);                                        BeanDefinition beanDefinition1 = builder1.getRawBeanDefinition();                                        beanDefinition1.setPrimary(sentinel.isPrimary());                                        registry.registerBeanDefinition(name + "RedisConnectionFactory", beanDefinition1);                                        BeanDefinitionBuilder builder2 = BeanDefinitionBuilder                                                        .genericBeanDefinition(StringRedisTemplate.class, () -> {                                                                StringRedisTemplate template = new StringRedisTemplate();                                                                template.setConnectionFactory(ref);                                                                return template;                                                        });                                        BeanDefinition beanDefinition2 = builder2.getRawBeanDefinition();                                        beanDefinition2.setPrimary(sentinel.isPrimary());                                        registry.registerBeanDefinition(name + "RedisTemplate", beanDefinition2);                                }                        } catch (Exception ex) {                                logger.error("register redisProperties error", ex);                        }                });        }        @Override        public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {                this.factory = factory;        }        @Override        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {                this.registry = registry;        }        @Override        public int getOrder() {                return super.getOrder() - 1;        }}
public class PoolBuilderFactory {        public LettuceClientConfigurationBuilder createBuilder(Pool properties) {                return LettucePoolingClientConfiguration.builder().poolConfig(getPoolConfig(properties));        }        private GenericObjectPoolConfig getPoolConfig(Pool properties) {                GenericObjectPoolConfig config = new GenericObjectPoolConfig<>();                config.setMaxTotal(properties.getMaxActive());                config.setMaxIdle(properties.getMaxIdle());                config.setMinIdle(properties.getMinIdle());                if (properties.getTimeBetweenEvictionRuns() != null) {                        config.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRuns().toMillis());                }                if (properties.getMaxWait() != null) {                        config.setMaxWaitMillis(properties.getMaxWait().toMillis());                }                return config;        }}

根据代码的细节,可以看到sentinels其实是一个map,会把sentinels的key和RedisTemplate拼接成bean的名字,所以在使用的过程中,如果有primary配置的直接使用@Autowired就可以直接注入了,其他的则@Qualifier+@Autowired既可以注入了。

    @Autowired        private StringRedisTemplate stringRedisTemplate;//对应的master 为b的        @Autowired        @Qualifier("temp1RedisTemplate")        private StringRedisTemplate microblogRedisTemplate;//对应的master 为a的

关于springboot中怎么配置创建多个redis就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

0