redis连接池:连接异常处理机制实现
背景:redis哨兵连接池,redis服务器全部宕机
结果:如果请求还是继续调用redis,则每个请求都会等待超时,高并发情况下容易造成线程阻塞
解决思路:加开关,获取连接异常时,关闭开关,并启动异步线程,尝试重新获取连接
1.Redis管理类
public class RedisManager {
/**
* redis连接异常
* redis使用过程中,如遇连接异常,则将该值改为true,在重新建立连接成功前,不再提供redis服务
*/
private static Boolean redisConnExceeption = false;
/**
* 用于设置redis连接异常,以及出现异常时尝试重新获取连接
* @param isConnException
*/
public static synchronized void setIsConnException(boolean isConnException) {
//只有当前模块异常标记与传入参数不一致时,才进行后续操作
if(redisConnExceeption!=isConnException) {
redisConnExceeption = isConnException;
//如果出现连接异常,则尝试重新连接
if(isConnException) {
retryConn();
}
}
}
/**
* 尝试重新获取连接
* 启动线程,重新进行redis连接的获取
*/
private static void retryConn() {
new RedisReTryConnThread().start();
}
/**
* 判断redis是否可用
* @return
*/
public static boolean isUseRedis() {
return !redisConnExceeption;
}
}
2.尝试重新获取连接的异步线程
public class RedisReTryConnThread extends Thread{
public void run() {
RedisCommonDataSource redisDataSource = RedisCommonDataSourceFactory.instanceRedisDataSource();
Jedis jedis = null;
//如果还存在连接异常,则尝试继续获取
while(!RedisManager.isUseRedis()){
try {
jedis = redisDataSource.getRedisClient();
//获取连接正常,则跳出
if(jedis!=null) {
RedisManager.setIsConnException(false);
break;
}
} catch (Exception e) {
} finally {
if (jedis != null) {
jedis.close();
}
}
//每五秒尝试一次
try {
Thread.sleep(5*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
3.异常触发
public RedisResult set(String key, String value) {
Jedis jedis = null;
RedisResult result = null;
//如果redis开关关闭或不可用,则直接返回null
if(!RedisManager.isUseRedis(sysFlag)) {
return result;
}
try {
jedis = redisDataSource.getRedisClient(sysFlag);
result = new RedisResult(jedis.set(key, value));
} catch (JedisConnectionException e) {
e.printStackTrace();
RedisManager.setIsConnException(true);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}
}
return result;
}
写在最后
学习路上,就是不断过关打怪,坚持学习,终将胜利
感谢各位大大的耐心阅读,咋们下次再会~
创作不易,大侠请留步… 动起可爱的双手,来个赞再走呗 (๑◕ܫ←๑)