1.redis批量删除key redis-cli keys '*' | xargs redis-cli del
2.从连接池获取jedis链接,不需要进行关闭操作,如果关闭会报redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool异常,原因是多个线程会用同一个pedis连接,如果其中一个关闭了,另外一个还在用,那么会出错。
jedis=jedisConnectionFactory.getConnection().getNativeConnection();
3.could not get a resources from the pool
连接池的资源用完了,无法获取链接了,原因是没有归还的原因。
实际上使用jedisPool不需要进行归还资源,只需要在有异常的时候quit()或者disconnect();
4.redis java.lang.Long cannot be cast to [B
这是因为多个线程同时使用一个jedis连接导致
具体原因:假设jedis在执行这个命令的时候,因为redis超负荷,jedis可能返回超时的异常,这个时候发生了什么,没有处理这个异常,直接将这个jedis的链接返回到了连接池,这样有没有问题呢?
查看jedis源码发现他的connection中对网络输出流做了一个封装,其中自建了一个buffer,所以当发生异常的时候,这个buffer里还残存着上次没有发送或者发送不完整的命令,这个时候没有做处理,直接将该连接返回到连接池,那么重用该连接执行下次命令的时候,就会将上次没有发送的命令一起发送过去,所以才会出现上面的错误“返回值类型不对”;
所以正确的写法应该是在发送异常的时候,销毁这个连接,不能再重用!
5.redis中保存的key-set形式的都不需要设置过期时间,并且update之前要先删除,并且保存进redis时必须原子性,即要不全都保存,要不全都不保存进去。
6.Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
使用jedis的时候,没有将jedis return,导致过多的client连接
8.Request processing failed; nested exception is com.alibaba.fastjson.JSONException: syntax error, expect {, actual error, pos 0
jedis不是线程安全的,当多个线程使用同一个jedis链接的时候,返回值就会发生混乱。
jedis使用的时候应该每个线程都有自己独立的jedis对象,利用jedispool配置,在pool中获取jedis对象,在出错的时候应该将jedis释放,不出错的时候不需要释放,新版本已经做了自动释放。
以上各种异常总结,使用redis时需要使用连接池,并且在连接错误或发生失败时释放该连接池。并且每个线程的链接要独立。
从jedis源码中,我们可以看出,当链接异常时调用的是:jedisPool.returnBrokenResource(jedis);
当链接正常返回时调用的是:jedisPool.returnResource(jedis);
继续跟进去可以看到returnBrokenResource()方法最终调用的是GenericObjectPool.invalidateObject(),
源代码如下:
public void invalidateObject(T obj) throws Exception {
PooledObject p = allObjects.get(obj);
if (p == null) {
if (isAbandonedConfig()) {
return;
} else {
throw new IllegalStateException(
"Invalidated object not currently part of this pool");
}
}
synchronized (p) {
if (p.getState() != PooledObjectState.INVALID) {
destroy(p);
}
}
}
最终实际处理销毁的代码就是de
story()方法,跟进去可以看到逻辑很清晰:
private void destroy(PooledObject toDestory) throws Exception {
toDestory.invalidate();
idleObjects.remove(toDestory);
allObjects.remove(toDestory.getObject());
try {
factory.destroyObject(toDestory);
} finally {
destroyedCount.incrementAndGet();
createCount.decrementAndGet();
}
}
如果是正常返回的链接,调用的returnResource()方法,实际上最终执行的方法是:
resource.resetState();
returnResourceObject(resource);
主要做如下处理:把链接返回到连接池,如果连接池设置了maxIdle最大空闲连接数,如果连接池中最大空闲连接数已经等于maxIdle,则会销毁这个链接;如果连接池设置了testOnReturn=true,则在返回前会先校验这个链接有效性,如果无效会被销毁。