spring boot整合redis多实例
Posted wenwblog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring boot整合redis多实例相关的知识,希望对你有一定的参考价值。
最近项目中遇到需要连接两个redis实例的情况,于是就在spring boot原先的基础上修改了一点。
1. 定义配置文件的bean,继承自RedisProperties
- 下面是配置文件的内容
redis:
config:
multiple:
- name: develop
database: 0
lettuce:
pool:
max-idle: 10
max-active: 1000
max-wait: 1000ms
min-idle: 5
timeout: 100000ms
cluster:
nodes: 192.168.2.86:6380,192.168.2.87:6380,192.168.2.88:6380
- name: test
database: 0
lettuce:
pool:
max-idle: 10
max-active: 1000
max-wait: 1000ms
min-idle: 5
timeout: 100000ms
cluster:
nodes: 192.168.2.86:6379,192.168.2.87:6379,192.168.2.88:6379
- 配置文件对应的实体
@Data
public class MultipleRedisProperties extends RedisProperties {
/**
* redis的自定义名称
*/
private String name;
}
2. 获取配置文件属性的值
@Getter
@Setter
@ConfigurationProperties(prefix = "redis.config")
public class RedisConfigPropertySupport {
List<MultipleRedisProperties> multiple = new ArrayList<>();
}
3.加载到spring 容器中
@Getter
@Setter
@Configuration
@EnableConfigurationProperties(RedisConfigPropertySupport.class)
public class RedisPropertiesAutoConfig {
private RedisConfigPropertySupport redisProperties;
public RedisPropertiesAutoConfig(RedisConfigPropertySupport redisProperties) {
this.redisProperties = redisProperties;
}
}
- 创建redis部署模式的枚举值
public enum RedisModeEnum {
/**
* 单机
*/
STAND_ALONE,
/**
* 哨兵
*/
SENTINEL,
/**
* 集群
*/
CLUSTER
}
4. 使用spring boot的创建连接工厂进行配置redis的连接工厂类
public abstract class AbstractRedisConnectionFactoryConfig implements BeanFactoryAware, InitializingBean {
@Autowired
private RedisPropertiesAutoConfig redisProperties;
private BeanFactory beanFactory;
private static final String DEFAULT = "default";
@Override
public void afterPropertiesSet() {
ConfigurableListableBeanFactory listableBeanFactory = (ConfigurableListableBeanFactory) this.getBeanFactory();
if (getRedisProperties().getRedisProperties() == null || CollectionUtils.isEmpty(getRedisProperties().getRedisProperties().getMultiple())) {
RedisConnectionFactory defaultConnectionFactory = buildRedisConnectionFactory(null);
listableBeanFactory.registerSingleton(DEFAULT + "_redisConnectionFactory", defaultConnectionFactory);
}
getRedisProperties().getRedisProperties().getMultiple().forEach(redisProperty -> {
RedisConnectionFactory redisConnectionFactory = buildRedisConnectionFactory(redisProperty);
listableBeanFactory.registerSingleton(redisProperty.getName().trim() + "_redisConnectionFactory", redisConnectionFactory);
});
}
/**
* 创建{@link RedisConnectionFactory},由子类实现
*
* @param redisProperties
* @return
*/
protected abstract RedisConnectionFactory buildRedisConnectionFactory(RedisProperties redisProperties);
/**
* 根据redisProperty判断redis部署模式
*
* @param redisProperty redisProperty
* @return {@link RedisModeEnum}
*/
protected abstract RedisModeEnum getRedisMode(RedisProperties redisProperty);
static class RedisConnectionPoolBuilderFactory {
public LettuceClientConfiguration.LettuceClientConfigurationBuilder createBuilder(RedisProperties.Pool properties) {
return LettucePoolingClientConfiguration.builder().poolConfig(getPoolConfig(properties));
}
private GenericObjectPoolConfig<?> getPoolConfig(RedisProperties.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;
}
}
@Override
public void setBeanFactory(@Nullable BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public BeanFactory getBeanFactory() {
return beanFactory;
}
public RedisPropertiesAutoConfig getRedisProperties() {
return redisProperties;
}
}
- 工厂实现类
@Configuration
public class LettuceRedisConnectionFactoryConfig extends AbstractRedisConnectionFactoryConfig {
@Override
protected RedisConnectionFactory buildRedisConnectionFactory(RedisProperties redisProperty) {
if (redisProperty == null) {
//创建默认的redis连接工厂
LettuceConnectionFactory defaultConnectionFactory = createDefaultConnectionFactory();
defaultConnectionFactory.afterPropertiesSet();
return defaultConnectionFactory;
}
LettuceClientConfiguration clientConfig = buildLettuceClientConfiguration(DefaultClientResources.create(),
redisProperty.getLettuce().getPool(), redisProperty);
//创建lettuce连接工厂
LettuceConnectionFactory redisConnectionFactory;
if (getRedisMode(redisProperty) == RedisModeEnum.CLUSTER) {
redisConnectionFactory = new LettuceConnectionFactory(new RedisClusterConfiguration
(redisProperty.getCluster().getNodes()), clientConfig);
} else if (getRedisMode(redisProperty) == RedisModeEnum.SENTINEL) {
redisConnectionFactory = new LettuceConnectionFactory(new RedisSentinelConfiguration
(redisProperty.getSentinel().getMaster(), new HashSet<>(redisProperty.getSentinel().getNodes())), clientConfig);
} else {
redisConnectionFactory = new LettuceConnectionFactory(new RedisStandaloneConfiguration
(redisProperty.getHost(), redisProperty.getPort()), clientConfig);
}
redisConnectionFactory.afterPropertiesSet();
return redisConnectionFactory;
}
@Override
protected RedisModeEnum getRedisMode(RedisProperties redisProperty) {
if (redisProperty.getCluster() != null) {
Assert.notNull(redisProperty.getCluster().getNodes(), "集群节点不能为空");
return RedisModeEnum.CLUSTER;
} else if (redisProperty.getSentinel() != null) {
Assert.hasText(redisProperty.getSentinel().getMaster(), "哨兵的主节点不能为空");
Assert.notNull(redisProperty.getSentinel().getNodes(), "哨兵的从节点不能为空");
return RedisModeEnum.SENTINEL;
}
return RedisModeEnum.STAND_ALONE;
}
private LettuceClientConfiguration buildLettuceClientConfiguration(ClientResources clientResources, RedisProperties.Pool pool, RedisProperties redisProperties) {
LettuceClientConfiguration.LettuceClientConfigurationBuilder builder = createBuilder(pool);
applyProperties(builder, redisProperties);
builder.clientResources(clientResources);
return builder.build();
}
private LettuceClientConfiguration.LettuceClientConfigurationBuilder applyProperties(
LettuceClientConfiguration.LettuceClientConfigurationBuilder builder, RedisProperties redisProperties) {
if (redisProperties.isSsl()) {
builder.useSsl();
}
if (redisProperties.getTimeout() != null) {
builder.commandTimeout(redisProperties.getTimeout());
}
if (redisProperties.getLettuce() != null) {
RedisProperties.Lettuce lettuce = redisProperties.getLettuce();
if (lettuce.getShutdownTimeout() != null && !lettuce.getShutdownTimeout().isZero()) {
builder.shutdownTimeout(redisProperties.getLettuce().getShutdownTimeout());
}
}
return builder;
}
private LettuceClientConfiguration.LettuceClientConfigurationBuilder createBuilder(RedisProperties.Pool pool) {
if (pool == null) {
return LettuceClientConfiguration.builder();
}
return new RedisConnectionPoolBuilderFactory().createBuilder(pool);
}
private LettuceConnectionFactory createDefaultConnectionFactory() {
return new LettuceConnectionFactory(new RedisStandaloneConfiguration());
}
}
5.redisTemplate的配置
public abstract class AbstractRedisConfiguration implements ApplicationContextAware {
private ApplicationContext applicationContext;
protected RedisTemplate<String, Object> buildRedisTemplate(String name) {
return buildRedisTemplate(name, new GenericJackson2JsonRedisSerializer(), false);
}
protected RedisTemplate<String, Object> buildRedisTemplate(String name, Boolean enableTransaction) {
return buildRedisTemplate(name, new GenericJackson2JsonRedisSerializer(), enableTransaction);
}
protected RedisTemplate<String, Object> buildRedisTemplate(String name, RedisSerializer redisSerializer,
Boolean enableTransaction) {
if (StringUtils.isBlank(name)) {
throw new IllegalArgumentException("redis properties name field must not null");
}
RedisConnectionFactory redisConnectionFactory = getRedisConnectionFactory(name);
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(redisSerializer);
redisTemplate.setHashValueSerializer(redisSerializer);
redisTemplate.setEnableTransactionSupport(enableTransaction);
return redisTemplate;
}
private RedisConnectionFactory getRedisConnectionFactory(String name) {
return (RedisConnectionFactory) applicationContext.getBean(name.trim() + "_redisConnectionFactory");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
- 配置redisTemplate
@Configuration
@DependsOn("lettuceRedisConnectionFactoryConfig")
public class RedisConfiguration extends AbstractRedisConfiguration {
@Bean("developRedisTemplate")
public RedisTemplate<String, Object> getDevelopRedisTemplate() {
return buildRedisTemplate("develop");
}
@Bean("testRedisTemplate")
public RedisTemplate<String, Object> getTestRedisTemplate() {
return buildRedisTemplate("test");
}
}
- 下面利用spring boot的ApplicationRunner接口测试一下,用redis客户端查看发现结果已经存入进去了。
@Autowired
@Qualifier("developRedisTemplate")
private RedisTemplate developRedisTemplate;
@Autowired
@Qualifier("testRedisTemplate")
private RedisTemplate testRedisTemplate;
@Override
public void run(ApplicationArguments args) throws Exception {
developRedisTemplate.opsForValue().set("develop_RedisMultiple", "test", 120, TimeUnit.SECONDS);
testRedisTemplate.opsForValue().set("test_RedisMultiple", "test", 120, TimeUnit.SECONDS);
}
以上是关于spring boot整合redis多实例的主要内容,如果未能解决你的问题,请参考以下文章