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<T> 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);
}
}
}
最終實際處理銷燬的代碼就是destory()方法,跟進去可以看到邏輯很清晰:
private void destroy(PooledObject<T> 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,則在返回前會先校驗這個鏈接有效性,如果無效會被銷燬。