1. 程式人生 > >記一次Redis的異常分析

記一次Redis的異常分析

最近線上環境偶爾在零點過後的時候就會報Redis的異常,出現好幾種錯誤,並且持續時間在1-3分鐘之間,並不固定,報的錯誤也有3種,表現各不相同,很是詭異。

(1)錯誤一

redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
        at redis.clients.util.RedisInputStream.ensureFill(RedisInputStream.java:201)
        at redis.clients.util.RedisInputStream.readByte(RedisInputStream.java:40)
        at redis.clients.jedis.Protocol.process(Protocol.java:132)
        at redis.clients.jedis.Protocol.read(Protocol.java:196)
        at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:288)
        at redis.clients.jedis.Connection.getBinaryMultiBulkReply(Connection.java:224)
        at redis.clients.jedis.Jedis.hgetAll(Jedis.java:780)
(2)錯誤二
2015-12-12 00:01:39,825 ERROR [com.lazyaudio.yyting.cache.protobuf.ProtobufFactory:224] [KryoError]errorMsg=Protocol message end-group tag did not match expected tag.
com.google.protobuf.InvalidProtocolBufferException: Protocol message end-group tag did not match expected tag.
        at com.google.protobuf.InvalidProtocolBufferException.invalidEndTag(InvalidProtocolBufferException.java:73)
        at com.google.protobuf.CodedInputStream.checkLastTagWas(CodedInputStream.java:124)
        at com.google.protobuf.AbstractMessageLite$Builder.mergeFrom(AbstractMessageLite.java:163)
        at com.google.protobuf.AbstractMessage$Builder.mergeFrom(AbstractMessage.java:716)
        at com.google.protobuf.AbstractMessage$Builder.mergeFrom(AbstractMessage.java:238)
        at com.google.protobuf.AbstractMessageLite$Builder.mergeFrom(AbstractMessageLite.java:153)
        at com.google.protobuf.AbstractMessage$Builder.mergeFrom(AbstractMessage.java:709)

(3)錯誤三
2015-12-12 00:01:39,824 ERROR [com.lazyaudio.yyting.cache.protobuf.ProtobufFactory:224] [KryoError]errorMsg=Protocol message tag had invalid wire type.
com.google.protobuf.InvalidProtocolBufferException: Protocol message tag had invalid wire type.
        at com.google.protobuf.InvalidProtocolBufferException.invalidWireType(InvalidProtocolBufferException.java:78)
        at com.google.protobuf.UnknownFieldSet$Builder.mergeFieldFrom(UnknownFieldSet.java:498)
        at com.google.protobuf.GeneratedMessage$Builder.parseUnknownField(GeneratedMessage.java:438)
 


近一年來我們線上環境使用Redis效果都好得出奇了,極少有超時的情況發生,這次已經持續1個多星期,說不定哪天零點以後,就會出現Redis的上述錯誤,故障時間也不確定(通常在1-3分鐘以內),其它時間段就一切良好,我從業務上到處找可能的原因,快2周過去了,一點眉目沒有,google/baidu都沒有找到有價值的參考資料。

不經意之間,我想起來比較下該機器Load的變化情況,一看下來就什麼都知道了,不明原因Load從0點開始就會升高,知道問題了就好辦了,就是等著看什麼東東導致Load高就得了,事情就這麼簡單的解決了!

一直沒有朝redis本身去找問題,太信任它了,最後的結果證明我是錯的!

我們的Redis採用sentinel 5個節點,Redis 2 個節點的方式部署,其中主節點採用快取模式,都不寫磁碟純粹作為一個快取,備節點則寫AOF和RDB,所以一直沒有朝Redis本身去追問題。事實上最後看來是由於切換過Redis的主備,結果變成主在寫AOF和RDB,備作為快取在運行了,以至於在主庫上的磁碟IO壓力比較高的時候,導致Redis每秒一次的寫磁碟超時,影響了線上應用伺服器去讀取和寫入資料,這就有超時Timeout發生了。