背景
一個多線程的消費任務,從kafka讀數據放到LinkedBlockingQueue,另一個線程消費此鏈表數據。
在消費的時候本意期望用redis實現一個鎖。
java中有對應的包jedisLock。
從Jedispool中獲取一個連接去進行redis操作。
代碼
Jedis jedis = jedisPool.getResource();
JedisLock lock = new JedisLock(jedis, key, 10000, 30000);
try {
lock.acquire();
//
} catch (Exception e) {
logger.error("redis connect failed");
logger.error(e.getMessage());
}
} finally {
lock.release();
}
現象
在測試環境沒有問題。
在線上消費一段時間就停止消費。程序處於假死狀態。
而且有些時候很長時間不會假死,有些時候一會就會假死。
於是開始排查。
日誌
開始消費正常。之後線程開始sleep。程序卡死狀態。
jedis源碼分析
爲了追蹤這個數目,設置了一個變量sum,消費一條數據sum++,發現每次都是消費1024個就開始阻塞。
繼續跟蹤,發現在jedispool獲取資源的時候阻塞,也即獲取不到資源,阻塞住在獲取資源處。
redis配置爲最大連接數1024個。
開始思考,爲什麼獲取不到資源不會拋異常,會阻塞,進而去看Jedis源碼。
maxWaitMillis默認爲-1。
繼續追進代碼。
到這裏,線程就鎖住了,獲取不到資源。
這時候,我又有一個問題,爲什麼之前的redis資源不會自己釋放呢,之前用線程池的時候,會自己回收,爲什麼jedisPool沒有。必須要手動jedis.close,我去看jedis.close的代碼。
結論
1.在使用jedispool的時候一定要注意資源的釋放。
2.一定要注意maxWaitMillis的設置。
否則會出現阻塞的問題。一定注意!!!!!!