實(shí)例基礎(chǔ)信息:
redis版本:redis-cli 3.2.5
架構(gòu):傳統(tǒng)主從架構(gòu)
背景
一天開(kāi)發(fā)人員通過(guò)kibana查看tomcat日志時(shí),發(fā)現(xiàn)以下錯(cuò)誤
RedisMessageListenerContainer 643 - Connection failure occurred. Restarting subscription task after 5000 ms

-問(wèn)題分析
1)百度查看該報(bào)錯(cuò),很多帖子解釋原因如下:
client-output-buffer-limit pubsub 32mb 8mb 60 # Redis訂閱客戶(hù)端訂閱buffer超過(guò)32M或持續(xù)60秒超過(guò)8M,訂閱立即被關(guān)閉!(意思是說(shuō)客戶(hù)端消費(fèi)速度比較慢,導(dǎo)致產(chǎn)生的消息大量堆積超過(guò)了限制客戶(hù)端被關(guān)閉)
2)根據(jù)該解釋查看redis服務(wù)器,通過(guò)client list查看信息如下,通過(guò)截圖信息可以看出這次發(fā)現(xiàn)的錯(cuò)誤于網(wǎng)上的描述并不符合,因?yàn)榇藭r(shí)client-output-buffer-limit pubsub是空的說(shuō)明不是這個(gè)參數(shù)限制導(dǎo)致的

3)為了進(jìn)一步確定是否是該參數(shù)限制導(dǎo)致的錯(cuò)誤,通過(guò)服務(wù)器手動(dòng)設(shè)置client-output-buffer-limit參數(shù),將其改為不受限制:
127.0.0.1:6379> config set client-output-buffer-limit "normal 0 0 0 slave 268435456 67108864 60 pubsub 0 0 0"
繼續(xù)觀察一段時(shí)間發(fā)現(xiàn)錯(cuò)誤仍然以一定的頻率出現(xiàn),這充分說(shuō)明了這次錯(cuò)誤不是client-output-buffer-limit pubsub造成的;
4)通過(guò)帖子發(fā)現(xiàn)一個(gè)有用信息是client-output-buffer-limit pubsub如果達(dá)到限制會(huì)關(guān)閉客戶(hù)端,然后客戶(hù)端會(huì)報(bào)此次這個(gè)錯(cuò)誤,那是不是有可能是其他地方將這個(gè)客戶(hù)端關(guān)閉了造成這個(gè)錯(cuò)誤;
5)仔細(xì)觀察錯(cuò)誤發(fā)生的頻率,發(fā)現(xiàn)這應(yīng)該是2組發(fā)布訂閱產(chǎn)生的錯(cuò)誤,第一張截圖紅框和綠框標(biāo)出,每組發(fā)生的頻率是3min鐘,分析整個(gè)線(xiàn)路server端不會(huì)主動(dòng)關(guān)閉client,jedis連接池配置的idle空閑斷開(kāi)是30min與報(bào)錯(cuò)也不符合,突然想起tomcat連接redis是通過(guò)haproxy代理的,是不是haproxy將客戶(hù)端殺掉了,查看haproxy配置文件發(fā)現(xiàn):

timeout client:客戶(hù)端非活動(dòng)狀態(tài)的超時(shí)時(shí)長(zhǎng)
timeout server:客戶(hù)端與服務(wù)器端建立連接后,等待服務(wù)器端的超時(shí)時(shí)長(zhǎng)
發(fā)現(xiàn)這個(gè)3分鐘idle將會(huì)斷開(kāi)連接,很有可能是這兩個(gè)參數(shù)造成的;
6)將haproxy的timeout client、timeout server改成10min reload后等待一段時(shí)間發(fā)現(xiàn)報(bào)錯(cuò)的頻率成了10min鐘,問(wèn)題找到了,此次這個(gè)錯(cuò)誤是由于haproxy將idle客戶(hù)端殺掉了,造成程序客戶(hù)端報(bào)錯(cuò);
7)與開(kāi)發(fā)人員溝通他們代碼的邏輯是訂閱時(shí)發(fā)生連接錯(cuò)誤會(huì)繼續(xù)嘗試連接,也就是說(shuō)消息產(chǎn)生端頻率太低超出了haproxy設(shè)置端idel時(shí)間,haproxy將訂閱客戶(hù)端連接關(guān)閉了,訂閱端客戶(hù)端收到client被關(guān)閉后會(huì)拋出錯(cuò)誤并重新建立連接,這就是錯(cuò)誤產(chǎn)生端原因。
- 暫時(shí)解決方案
1)haproxy超時(shí)時(shí)間仍改回3min,因?yàn)楹蠖舜砹薽ysql等服務(wù);
2)暫時(shí)繼續(xù)沿用目前這種方案,因?yàn)槌绦蚓邆鋽嚅_(kāi)重連機(jī)制,雖然redis發(fā)布訂閱不能持久化,斷開(kāi)連接期間發(fā)布的消息訂閱端有可能丟失,但是目前業(yè)務(wù)發(fā)布消息很少,幾個(gè)月發(fā)布一次消息,在發(fā)布消息的時(shí)候連接斷開(kāi)的概率還是比較小的,所以暫不處理。 - 永久解決方案
1)采用Rabbit Mq取代redis
2)tomcat直連redis
3)代碼處增加額外的發(fā)布信息,確保連接idle時(shí)間不會(huì)超過(guò)3min