在前面说的JedisSentinelPool只能实现主从的切换,而无法实现读写的分离。
1.哨兵的客户端实现主从切换方案
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.6.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
# Redis哨兵服务器地址
redis.sentinel=aliyun:26885,aliyun:26886,aliyun:26887
redis.master=mymaster
# Redis服务器连接密码(默认为空)
redis.password=null
redis.timeout=30000
# 连接池最大连接数(使用负值表示没有限制)
redis.maxTotal=30
# 连接池中的最大空闲连接
redis.maxIdle=10
redis.numTestsPerEvictionRun=1024
redis.timeBetweenEvictionRunsMillis=30000
redis.minEvictableIdleTimeMillis=1800000
redis.softMinEvictableIdleTimeMillis=10000
# 连接池最大阻塞等待时间(使用负值表示没有限制)
redis.maxWaitMillis=1500
redis.testOnBorrow=true
redis.testWhileIdle=true
redis.blockWhenExhausted=false
redis.JmxEnabled=true
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
import java.util.Set;
@Configuration
@PropertySource("classpath:application.properties")
public class RedisSentinelConfig {
@Value("${redis.sentinel}")
private String hosts;
@Value("${redis.master}")
private String master;
@Value("${redis.timeout}")
private int timeout;
@Value("${redis.maxIdle}")
private int maxIdle;
@Value("${redis.maxWaitMillis}")
private int maxWaitMillis;
@Value("${redis.blockWhenExhausted}")
private Boolean blockWhenExhausted;
@Value("${redis.JmxEnabled}")
private Boolean JmxEnabled;
@Bean
public JedisPoolConfig jedisPoolConfigFactory() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
// 连接耗尽时是否阻塞, false报异常,true阻塞直到超时, 默认true
jedisPoolConfig.setBlockWhenExhausted(blockWhenExhausted);
// 是否启用pool的jmx管理功能, 默认true
jedisPoolConfig.setJmxEnabled(JmxEnabled);
jedisPoolConfig.setTestOnBorrow(true);
jedisPoolConfig.setTestOnReturn(true);
return jedisPoolConfig;
}
@Bean
public JedisSentinelPool JedisSentinelPoolFactory(JedisPoolConfig jedisPoolConfig){
Set<String> nodeSet = new HashSet<>();
//获取到节点信息
String nodeString = hosts;
//判断字符串是否为空
if(nodeString == null || "".equals(nodeString)){
throw new RuntimeException("RedisSentinelConfiguration initialize error nodeString is null");
}
String[] nodeArray = nodeString.split(",");
//判断是否为空
if(nodeArray == null || nodeArray.length == 0){
throw new RuntimeException("RedisSentinelConfiguration initialize error nodeArray is null");
}
//循环注入至Set中
for(String node : nodeArray){
System.out.println("Read node : "+node);
nodeSet.add(node);
}
//创建连接池对象
JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(master,nodeSet,jedisPoolConfig ,timeout);
return jedisSentinelPool;
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisSentinelPool;
/**
* 操作字符串类型
*/
@Component
public class RedisString {
public final static String RS_STR_NS = "rs:";
@Autowired
private JedisSentinelPool jedisSentinelPool;
/**
* 向Redis中存值,永久有效
*/
public String set(String key, String value) {
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.set(RS_STR_NS +key, value);
} catch (Exception e) {
throw new RuntimeException("向Redis中存值失败!");
} finally {
jedis.close();
}
}
/**
* 批量向Redis中存值,永久有效
*/
public String msetRaw(String... keysvalues) {
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.mset(keysvalues);
} catch (Exception e) {
throw new RuntimeException("批量向Redis中存值失败!");
} finally {
jedis.close();
}
}
/**
* 根据传入Key获取指定Value
*/
public String get(String key) {
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
return jedis.get(RS_STR_NS +key);
} catch (Exception e) {
throw new RuntimeException("获取Redis值失败!");
} finally {
jedis.close();
}
}
}
2、读写分离的实现
需要自己去封装代码实现。
待补充