本文基于spring boot 2.0.7,讲解如何配置多数据源redis,采用lettuce做为redis客户端,并附上示例代码。
skyarthur: redis1: host: 127.0.0.1 port: 6378 lettuce: pool: min-idle: 5 max-idle: 10 max-active: 8 max-wait: 1ms shutdown-timeout: 100ms redis2: host: 127.0.0.1 port: 6379 lettuce: pool: min-idle: 5 max-idle: 10 max-active: 8 max-wait: 1ms shutdown-timeout: 100ms
共配置2个redis数据源,并采用 lettuce pool 做为redis客户端
package com.skyarthur.springboot.config; import io.lettuce.core.resource.ClientResources; import io.lettuce.core.resource.DefaultClientResources; import lombok.Getter; import lombok.Setter; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisPassword; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; import org.springframework.data.redis.core.StringRedisTemplate; /** * Created by skyarthur on 2019-12-21 */ @Configuration @ConfigurationProperties(prefix = "skyarthur") @Getter @Setter public class RedisConfig { private RedisProperties redis1; private RedisProperties redis2; @Bean(destroyMethod = "shutdown") @ConditionalOnMissingBean(ClientResources.class) public DefaultClientResources lettuceClientResources() { return DefaultClientResources.create(); } @Bean(name = "stringRedisTemplate1") @Primary public StringRedisTemplate stringRedisTemplate1( @Qualifier("Redis1LettuceConnectionFactory") RedisConnectionFactory redisConnectionFactory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean(name = "Redis1LettuceConnectionFactory") @Primary public LettuceConnectionFactory Redis1LettuceConnectionFactory(ClientResources clientResources) { RedisStandaloneConfiguration redis1StandaloneConfiguration = getStandaloneConfig(redis1); LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(clientResources, redis1); return new LettuceConnectionFactory(redis1StandaloneConfiguration, clientConfig); } @Bean(name = "stringRedisTemplate2") public StringRedisTemplate stringRedisTemplate2( @Qualifier("Redis2LettuceConnectionFactory") RedisConnectionFactory redisConnectionFactory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean(name = "Redis2LettuceConnectionFactory") public LettuceConnectionFactory Redis2LettuceConnectionFactory(ClientResources clientResources) { RedisStandaloneConfiguration redis1StandaloneConfiguration = getStandaloneConfig(redis2); LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(clientResources, redis2); return new LettuceConnectionFactory(redis1StandaloneConfiguration, clientConfig); } /** * redis standalone config * * @param redisProperties redis 配置参数 * @return RedisStandaloneConfiguration */ private RedisStandaloneConfiguration getStandaloneConfig(RedisProperties redisProperties) { RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(); config.setHostName(redisProperties.getHost()); config.setPort(redisProperties.getPort()); config.setPassword(RedisPassword.of(redisProperties.getPassword())); config.setDatabase(redisProperties.getDatabase()); return config; } /** * 构建 LettuceClientConfiguration * * @param clientResources clientResources * @param redisProperties redisProperties * @return LettuceClientConfiguration */ private LettuceClientConfiguration getLettuceClientConfiguration(ClientResources clientResources, RedisProperties redisProperties) { LettuceClientConfiguration.LettuceClientConfigurationBuilder builder = createBuilder(redisProperties.getLettuce().getPool()); 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()); } } builder.clientResources(clientResources); return builder.build(); } /** * 创建 LettuceClientConfigurationBuilder * * @param pool 连接池配置 * @return LettuceClientConfigurationBuilder */ private LettuceClientConfiguration.LettuceClientConfigurationBuilder createBuilder(RedisProperties.Pool pool) { if (pool == null) { return LettuceClientConfiguration.builder(); } return LettucePoolingClientConfiguration.builder() .poolConfig(getPoolConfig(pool)); } /** * pool config * * @param properties redis 参数配置 * @return GenericObjectPoolConfig */ private GenericObjectPoolConfig getPoolConfig(RedisProperties.Pool properties) { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); config.setMaxTotal(properties.getMaxActive()); config.setMaxIdle(properties.getMaxIdle()); config.setMinIdle(properties.getMinIdle()); if (properties.getMaxWait() != null) { config.setMaxWaitMillis(properties.getMaxWait().toMillis()); } return config; } }
以上配置主要参考 spring 官方配置 RedisAutoConfiguration
, LettuceConnectionConfiguration
。简单来说: RedisAutoConfiguration
注册了2个bean, RedisTemplate
和 StringRedisTemplate
,这两个bean又依赖 RedisConnectionFactory
的注入,在 RedisAutoConfiguration
可以看到, RedisConnectionFactory
有两个实现, LettuceConnectionFactory
和 JedisConnectionFactory
,具体可以直接参考官方配置 LettuceConnectionConfiguration
package com.skyarthur.springboot.config; import com.skyarthur.springboot.ApplicationTests; import com.skyarthur.springboot.common.enums.RedisType; import org.junit.Assert; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.StringRedisTemplate; /** * Created by skyarthur on 2019-12-21 */ public class RedisConfigTest extends ApplicationTests { @Autowired @Qualifier("stringRedisTemplate1") private StringRedisTemplate stringRedisTemplate1; @Autowired @Qualifier("stringRedisTemplate2") private StringRedisTemplate stringRedisTemplate2; @Test public void test() { LettuceConnectionFactory factory = (LettuceConnectionFactory) stringRedisTemplate1.getConnectionFactory(); Assert.assertNotNull(factory); Assert.assertEquals(6378, factory.getPort()); Assert.assertEquals("127.0.0.1", factory.getHostName()); factory = (LettuceConnectionFactory) stringRedisTemplate2.getConnectionFactory(); Assert.assertNotNull(factory); Assert.assertEquals(6379, factory.getPort()); Assert.assertEquals("127.0.0.1", factory.getHostName()); stringRedisTemplate1.opsForValue().set(RedisType.PERSON_INFO.getRealKey("test"), "6378"); stringRedisTemplate2.opsForValue().set("test", "6379"); Assert.assertEquals("6378", stringRedisTemplate1.opsForValue().get(RedisType.PERSON_INFO.getRealKey("test"))); Assert.assertEquals("6379", stringRedisTemplate2.opsForValue().get("test")); } }