有时候我们可能会遇到这样的场景,有多个业务使用redis做缓存。其他业务比较占用资源。由于redis是单线程,所以会影响到主业务,这个时候我们就需要使用不同的redis的库。这个时候通过springboot+redis的多实例配置就可以实现。
Maven依赖
(1)本文使用的redis依赖如下
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
在application.yml中加入reids 的配置信息
spring:
main-redis:
#redis的地址
host: localhost
#redis 的端口
port: 6379
#redis 的连接超时时间(毫秒)
timeout: 6000
#redis 的密码 默认为空
password:
pool:
#redis 连接池最大连接数
max-active: 10
#redis 连接池最大空闲连接
max-idle: 5
#redis 连接池最大阻塞等待时间
max-wait: 2
#redis 连接池最小空闲连接数
min-idle: 1
lesser-redis:
host: localhost
port: 6333
timeout: 6000
password:
pool:
max-active: 10
max-idle: 5
max-wait: 2
min-idle: 1
项目的目录结构如下:
这里主要提供了三个类进行不同环境的配置;
RedisAutoConfiguration 自动配置
/**
* @author kmz
*/
@Configuration
@EnableConfigurationProperties({RedisAutoConfiguration.MainRedisProperties.class,RedisAutoConfiguration.LesserRedisProperties.class})
public class RedisAutoConfiguration {
/**
* @Primary 注解告诉Spring遇到多个bean的时候,它为默认
* prefix 告诉spring读取前缀为spring.main-redis的配置信息
*/
@Primary
@ConfigurationProperties(prefix = "spring.main-redis")
public static class MainRedisProperties extends RedisProperties {
}
@ConfigurationProperties(prefix = "spring.lesser-redis")
public static class LesserRedisProperties extends RedisProperties {
}
/**
* 通过配置获取RedisConnectionFactory
* @param mainRedisProperties mainRedis的配置信息
* @return
*/
@Primary
@Bean("mainRedisConnectionFactory")
public static RedisConnectionFactory getMainRedisConnectionFactory(MainRedisProperties mainRedisProperties){
RedisConnectionConfiguration factory = new RedisConnectionConfiguration(mainRedisProperties);
return factory.redisConnectionFactory();
}
/**
* 获取mainredis的StringRedisTemplate实例
* @param redisConnectionFactory 使用@Qulifier指定需要的factory
* @return template
*/
@Primary
@Bean("mainStringRedisTemplate")
public static StringRedisTemplate getMainStringRedisTemplate(
@Qualifier(value = "mainRedisConnectionFactory") RedisConnectionFactory redisConnectionFactory){
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean("lesserRedisConnectionFactory")
public static RedisConnectionFactory getLesserRedisConnectionFactory(LesserRedisProperties lesserRedisProperties){
RedisConnectionConfiguration factory = new RedisConnectionConfiguration(lesserRedisProperties);
return factory.redisConnectionFactory();
}
@Bean("lesserStringRedisTemplate")
public static StringRedisTemplate getLesserStringRedisTemplate(
@Qualifier(value = "lesserRedisConnectionFactory") RedisConnectionFactory redisConnectionFactory){
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
RedisConnectionConfiguration 连接配置(来自于源码)
package com.example.redisautoconfiguration.config;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.util.StringUtils;
import redis.clients.jedis.JedisPoolConfig;
import java.net.URI;
import java.net.URISyntaxException;
/**
* @author kmz
* Redis连接的配置类
* from 源码
*/
public class RedisConnectionConfiguration {
private final RedisProperties properties;
RedisConnectionConfiguration(RedisProperties properties) {
this.properties = properties;
}
JedisConnectionFactory redisConnectionFactory() {
return applyProperties(createJedisConnectionFactory());
}
private JedisConnectionFactory applyProperties(JedisConnectionFactory factory) {
configureConnection(factory);
if (this.properties.isSsl()) {
factory.setUseSsl(true);
}
factory.setDatabase(this.properties.getDatabase());
if (this.properties.getTimeout() > 0) {
factory.setTimeout(this.properties.getTimeout());
}
return factory;
}
private void configureConnection(JedisConnectionFactory factory) {
if (StringUtils.hasText(this.properties.getUrl())) {
configureConnectionFromUrl(factory);
} else {
factory.setHostName(this.properties.getHost());
factory.setPort(this.properties.getPort());
if (this.properties.getPassword() != null) {
factory.setPassword(this.properties.getPassword());
}
}
}
private void configureConnectionFromUrl(JedisConnectionFactory factory) {
String url = this.properties.getUrl();
if (url.startsWith("rediss://")) {
factory.setUseSsl(true);
}
try {
URI uri = new URI(url);
factory.setHostName(uri.getHost());
factory.setPort(uri.getPort());
if (uri.getUserInfo() != null) {
String password = uri.getUserInfo();
int index = password.indexOf(":");
if (index >= 0) {
password = password.substring(index + 1);
}
factory.setPassword(password);
}
} catch (URISyntaxException ex) {
throw new IllegalArgumentException("Malformed 'spring.redis.url' " + url, ex);
}
}
private JedisConnectionFactory createJedisConnectionFactory() {
JedisPoolConfig poolConfig = this.properties.getPool() != null ? jedisPoolConfig() : new JedisPoolConfig();
return new JedisConnectionFactory(poolConfig);
}
private JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig config = new JedisPoolConfig();
RedisProperties.Pool props = this.properties.getPool();
config.setMaxTotal(props.getMaxActive());
config.setMaxIdle(props.getMaxIdle());
config.setMinIdle(props.getMinIdle());
config.setMaxWaitMillis(props.getMaxWait());
return config;
}
}
RedisPRoperties 配置信息(来自于源码)
package com.example.redisautoconfiguration.config;
import java.util.List;
/**
* Configuration properties for Redis.
*
* @author Dave Syer
* @author Christoph Strobl
* @author Eddú Meléndez
* @author Marco Aust
*/
public class RedisProperties {
/**
* Database index used by the connection factory.
*/
private int database = 0;
/**
* Redis url, which will overrule host, port and password if set.
*/
private String url;
/**
* Redis server host.
*/
private String host = "localhost";
/**
* Login password of the redis server.
*/
private String password;
/**
* Redis server port.
*/
private int port = 6379;
/**
* Enable SSL.
*/
private boolean ssl;
/**
* Connection timeout in milliseconds.
*/
private int timeout;
private Pool pool;
private Sentinel sentinel;
private Cluster cluster;
public int getDatabase() {
return this.database;
}
public void setDatabase(int database) {
this.database = database;
}
public String getUrl() {
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
public String getHost() {
return this.host;
}
public void setHost(String host) {
this.host = host;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public int getPort() {
return this.port;
}
public void setPort(int port) {
this.port = port;
}
public boolean isSsl() {
return this.ssl;
}
public void setSsl(boolean ssl) {
this.ssl = ssl;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getTimeout() {
return this.timeout;
}
public Sentinel getSentinel() {
return this.sentinel;
}
public void setSentinel(Sentinel sentinel) {
this.sentinel = sentinel;
}
public Pool getPool() {
return this.pool;
}
public void setPool(Pool pool) {
this.pool = pool;
}
public Cluster getCluster() {
return this.cluster;
}
public void setCluster(Cluster cluster) {
this.cluster = cluster;
}
/**
* Pool properties.
*/
public static class Pool {
/**
* Max number of "idle" connections in the pool. Use a negative value to indicate
* an unlimited number of idle connections.
*/
private int maxIdle = 8;
/**
* Target for the minimum number of idle connections to maintain in the pool. This
* setting only has an effect if it is positive.
*/
private int minIdle = 0;
/**
* Max number of connections that can be allocated by the pool at a given time.
* Use a negative value for no limit.
*/
private int maxActive = 8;
/**
* Maximum amount of time (in milliseconds) a connection allocation should block
* before throwing an exception when the pool is exhausted. Use a negative value
* to block indefinitely.
*/
private int maxWait = -1;
public int getMaxIdle() {
return this.maxIdle;
}
public void setMaxIdle(int maxIdle) {
this.maxIdle = maxIdle;
}
public int getMinIdle() {
return this.minIdle;
}
public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
}
public int getMaxActive() {
return this.maxActive;
}
public void setMaxActive(int maxActive) {
this.maxActive = maxActive;
}
public int getMaxWait() {
return this.maxWait;
}
public void setMaxWait(int maxWait) {
this.maxWait = maxWait;
}
}
/**
* Cluster properties.
*/
public static class Cluster {
/**
* Comma-separated list of "host:port" pairs to bootstrap from. This represents an
* "initial" list of cluster nodes and is required to have at least one entry.
*/
private List<String> nodes;
/**
* Maximum number of redirects to follow when executing commands across the
* cluster.
*/
private Integer maxRedirects;
public List<String> getNodes() {
return this.nodes;
}
public void setNodes(List<String> nodes) {
this.nodes = nodes;
}
public Integer getMaxRedirects() {
return this.maxRedirects;
}
public void setMaxRedirects(Integer maxRedirects) {
this.maxRedirects = maxRedirects;
}
}
/**
* Redis sentinel properties.
*/
public static class Sentinel {
/**
* Name of Redis server.
*/
private String master;
/**
* Comma-separated list of host:port pairs.
*/
private String nodes;
public String getMaster() {
return this.master;
}
public void setMaster(String master) {
this.master = master;
}
public String getNodes() {
return this.nodes;
}
public void setNodes(String nodes) {
this.nodes = nodes;
}
}
}
测试类
package com.example.redisautoconfiguration;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {
/**
* 默认 main
*/
@Autowired
StringRedisTemplate mainStringRedisTemplate;
/**
* 指定template实例
*/
@Autowired
@Qualifier("lesserStringRedisTemplate")
StringRedisTemplate lesserStringRedisTemplate;
@Test
public void test(){
System.out.println("begin");
mainStringRedisTemplate.opsForValue().set("test","this is 6379");
lesserStringRedisTemplate.opsForValue().set("test","this is 6333");
}
}
在本地以不同端口号启动多个redis服务
1.在mac中redis的默认安装目录为/user/loacl/ 2.在这个目录下找到redis,进入后找到redis.conf配置文件 3.复制一份重命名为6333redis.conf,将其端口号改为6333(详情请自行百度) 4.redis使用redis-server方式启动默认使用6379的端口配置文件,可以用redis-server 配置文件名 。用指定的配置文件启动redis服务 5.使用redis-cli(默认6379) -p 6333 进入两个redis库用于查看是否成功。
具体操作如下: 6379: 6333:
测试代码运行前后
运行前 6379: 6333: 测试代码运行后: 6379: 6333: 这样就实现了redis不同库的多环境配置。 代码的demo这github上有,有需要可自行查看: redis-autoconfiguration