背景描述:
(1) 某項目,使用redis作存儲,用redis的set性質來作實時統計,同時也存放其餘統計數據;
(2) 用到的key很多,value集合量較多;
(3) 天天零點的時候,回清理當前redis中全部的數據;
(4) 異常都出如今 零點清理以後;java
異常現場:
2018/03/13 00:00:20 OSS INFO [com.xxx.RedisDAO] - error
redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
at redis.clients.util.RedisInputStream.ensureFill(RedisInputStream.java:202)
at redis.clients.util.RedisInputStream.readByte(RedisInputStream.java:40)
at redis.clients.jedis.Protocol.process(Protocol.java:151)
at redis.clients.jedis.Protocol.read(Protocol.java:215)
at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:340)
at redis.clients.jedis.Connection.getIntegerReply(Connection.java:265)
at redis.clients.jedis.Jedis.sadd(Jedis.java:1109)
at com.xxx.RedisDAO.setXXXKPI(RedisDAO.java:66)
at com.xxx.xxxRunnable.run(xxxRunnable.java:69)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.net.SocketInputStream.read(SocketInputStream.java:127)
at redis.clients.util.RedisInputStream.ensureFill(RedisInputStream.java:196)
... 9 more
2018/03/13 00:00:20 OSS INFO [com.xxx.RedisDAO] - error
java.lang.ClassCastException: java.lang.Long cannot be cast to [B
at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:239)
at redis.clients.jedis.Jedis.set(Jedis.java:121)
at com.xxx.RedisDAO.setXXXXXKPI(RedisDAO.java:100)
at com.xxx.xxxRunnable.run(xxxRunnable.java:70)
at java.lang.Thread.run(Thread.java:745)
2018/03/13 00:00:20 OSS INFO [com.xxx.RedisDAO] - error
java.lang.ClassCastException: [B cannot be cast to java.lang.Long
at redis.clients.jedis.Connection.getIntegerReply(Connection.java:265)
at redis.clients.jedis.Jedis.sadd(Jedis.java:1109)
at com.xxx.RedisDAO.setXXXXXKPI(RedisDAO.java:167)
at com.xxx.xxxRunnable.run(xxxRunnable.java:71)
at java.lang.Thread.run(Thread.java:745)git
(1) 若當前redis中的數據不少,FLUSHDB 操做,須要花費必定的時間,阻塞了redis的響應,因而先出現了SocketTimeoutException;
(2) 鏈接出現異常後,從日誌看,接着出現了ClassCastException,且後續一直報這個異常錯誤;
(3) 經搜索查詢, 找到以下兩個網頁:
ClassCastException - [B cannot be cast to java.lang.Long #186:
https://github.com/xetorthio/jedis/issues/186github
Jedis使用過程當中踩過的那些坑:
http://bert82503.iteye.com/blog/2184225redis
綜上, 查項目代碼,發現幾處問題:
a. redis鏈接操做出現異常後,應該關閉close, 歸還資源,從新去一個redis鏈接使用。程序寫的是:出了異常,記錄日誌,接着用這個redis鏈接,一直出異常。
b. 鏈接池設置過大,重啓項目的時候,本次初始化的加上以前未釋放的鏈接(直接kill的進程,關閉時未釋放),瞬間連接過大;
c. 程序設計不合理, 因爲數據天天是實時統計展現,能夠天天的key前綴不同,設置key的過時時間,這樣就不用天天FLUSHDB。socket