从异常信息来看,首先是在'zadd'操作时出现"Socket读取超时异常",具体异常信息"JedisConnectionException: java.net.SocketTimeoutException: Read timed out"。
出现异常后,会销毁这个阻塞的Jedis连接池对象(CustomShardedJedisPool.returnBrokenResource(CustomShardedJedisPool.java:121)),但在请求Redis服务端关闭连接时,出现"强制类型转换异常",具体异常信息"ClassCastException: java.lang.Long cannot be cast to [B"。
网上的大神说:
查看 Jedis 源码发现它的Connection中对网络输出流做了一个封装(RedisInputStream),其中自建了一个buffer。当发生异常的时候,这个buffer里还残存着上次没有发送或者发送不完整的命令。这个时候没有做处理,直接将该连接返回到连接池,那么重用该连接执行下次命令的时候,就会将上次没有发送的命令一起发送过去,所以才会出现上面的错误“返回值类型不对”。、
解决的办法:
jedispool资源释放
public void close() {
if (dataSource != null) {
if ( client.isBroken()) {
this.dataSource.returnBrokenResource(this);
} else {
this.dataSource.returnResource(this);
}
} else {
client.close(); //2.9 以后的版本
}
}
所以对使用到jedis的地方进行一场捕获 进行资源的释放
try{
if (userName != null && jedis.exists(userName) && jedis.get(userName).equals(token)) {
return true;
}
}catch (Exception e){
jedis.close();
}
添加synchronized关键字
jedis不支持多线程的原因,在你调用del等方法时,在调用方法申明前加上关键字 synchronized就可以解决问题。比如delkey调用del方法,在delkey方法前加synchronized就可以了