redis 集群主从复制+哨兵,当主服务器宕机时,可以自动将从服务器切换为主服务器。提高系统的稳定性。
1.配置基本参数
需要的依赖:
<!-- springBoot 整合 redis 依赖 -->
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
- 在 yml 文件中配置基本参数
myjedis:
redis:
config:
#哨兵集群节点
nodes: 172.21.1.111:26379,172.21.2.111:26379
masterName: mymaster
password: 123456
database: 8
#总数
maxTotal: 100
#最大空闲数
maxIdle: 50
#最小空闲数
minIdle: 10
timeout: 60000
maxWaitMillis: 5000
- 创建配置类,使用
@ConfigurationProperties(prefix = "")
注解读取yml 中配置,参数名称和路径要与yml文件中配置的对应。
@ConfigurationProperties(prefix = "")
@Component
@Data
public class RedisConfigProperties {
private String nodes;
private String masterName;
private String password;
private int database;
private String maxTotal;
private String maxIdle;
private String minIdle;
private String timeout;
private String maxWaitMillis;
//以下单机redis配置信息
private String mode;
private String host;
private String port;
private String pass;
}
2.配置redis哨兵模式
@Configuration
public class RedisPoolConfig {
/** 配置类信息 */
@Autowired
RedisConfigProperties redisConfigProperties;
/** 初始化 jedis 连接池的配置 */
@Bean
public JedisPoolConfig getJedisPoolConfig(){
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(Integer.parseInt(redisConfigProperties.getMaxTotal()));
jedisPoolConfig.setMaxIdle(Integer.parseInt(redisConfigProperties.getMaxIdle()));
jedisPoolConfig.setMinIdle(Integer.parseInt(redisConfigProperties.getMinIdle()));
jedisPoolConfig.setMaxWaitMillis(Integer.parseInt(redisConfigProperties.getMaxWaitMillis()));
jedisPoolConfig.setTestOnReturn(true);
jedisPoolConfig.setTestOnBorrow(true);
return jedisPoolConfig;
}
/** 根据 jedis 连接池配置创建连接池 */
@Bean
public Pool<Jedis> getJedisPool(JedisPoolConfig jedisPoolConfig){
//集群部署
Set<String> nodeSet = new HashSet<>();
String[] nodeStr = redisConfigProperties.getNodes().split(",");
for(String node:nodeStr){
nodeSet.add(node);
}
return new JedisSentinelPool(redisConfigProperties.getMasterName(), nodeSet, jedisPoolConfig, 2000,
2000, redisConfigProperties.getPassword(), redisConfigProperties.getDatabase());
}
/** 通过连接池获取 jedis 实例 */
@Bean
public Jedis getJedis(Pool<Jedis> jedisPool){
return jedisPool.getResource();
}
}
3.配置 ApplicationContextAware 实现类,获取spring容器中的实例 Bean。
@Component
public class ApplicationContextProvider implements ApplicationContextAware {
/**
* 上下文对象实例
*/
public static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
ApplicationContextProvider.applicationContext = context;
}
/**
* 获取applicationContext
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 通过class获取Bean.
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
/**
* 通过name获取 Bean.
* @param name
* @return
*/
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
}
4.创建 JedisUtil 工具类,使用哨兵模式连接池。
public class JedisUtil {
private static Pool<Jedis> jedisSentinelPool = ApplicationContextProvider.getBean(JedisSentinelPool.class);
public static Pool<Jedis> getJedisSentinelPool() {
if (jedisSentinelPool == null) {
jedisSentinelPool = ApplicationContextProvider.getBean(JedisSentinelPool.class);
}
return jedisSentinelPool;
}
public static String get(String key) {
String value = null;
Jedis jedis = getJedisSentinelPool().getResource();
if (jedis.exists(key)) {
value = jedis.get(key);
value = StringUtils.isNotBlank(value) && !"nil".equalsIgnoreCase(value) ? value : null;
}
jedis.close();
return value;
}
public static long del(String key) {
long result = 0;
Jedis jedis = getJedisSentinelPool().getResource();
if (jedis.exists(key)){
result = jedis.del(key);
log.debug("del {}", key);
}else{
log.debug("del {} not exists", key);
}
jedis.close();
return result;
}
/**
* 设置缓存
* @param key 键
* @param value 值
* @return
*/
public static String set(String key, String value) {
return setex(key, value, 0);
}
/**
* 设置缓存
* @param key 键
* @param value 值
* @param cacheSeconds 超时时间,0为不超时
* @return
*/
public static String setex(String key, String value, int cacheSeconds) {
Jedis jedis = getJedisSentinelPool().getResource();
String result = null;
if (cacheSeconds != 0) {
jedis.setex(key, cacheSeconds, value);
}else{
result = jedis.set(key, value);
}
log.debug("set {} = {}", key, value);
jedis.close();
return result;
}
/**
* 以秒为单位返回 key 的剩余过期时间
* @param key 键
* @return
*/
public static long ttl(String key) {
Jedis jedis = getJedisSentinelPool().getResource();
long time = jedis.ttl(key);
jedis.close();
return time/1000;
}
}