轉載請注明出處哈:http://carlosfu.iteye.com/blog/2254154
?? ?
1. 背景:
大部分互聯網公司都會有Mysql或者Oracle的DBA,但是在Nosql方面一般不會設置專門的DBA。不過對于一些知名的互聯網公司來說,Nosql的使用量是巨大的,所以通常讓Mysql的DBA或者單獨聘請工程師來維護一些Nosql數據庫,比如:
Redis, Hbase, Memcache(其實嚴格講不是nosql), Mongodb, Cassandra。從講座看美團網應該是有專職的Redis DBA。所以作為業務開發人員不需要自己安裝、配置、運維Redis,只需要找Redis DBA來申請就可以了。
這里為了簡化說明:Redis DBA提供的服務叫做Redis云,業務開發人員叫做業務端(redis的使用者)
2. 現象: 業務端在使用redis云提供的redis服務后,經常出現connect timeout: Java代碼??
redis.clients.jedis.exceptions.JedisConnectionException?? java.net.SocketException?? java.net.SocketTimeoutException:connect?time?out?? ? ? 3. 分析和懷疑: 業務端一般認為redis出現問題,就是redis云有問題,人的“正常”思維:看別人錯誤容易,發現自己難,扯多了, 出現這個有很多原因: (1).?網絡原因:比如是否存在跨機房、網絡割接等等。 (2). 慢查詢,因為redis是單線程,如果有慢查詢的話,會阻塞住之后的操作。? (3).?value值過大?比如value幾十兆,當然這種情況比較少,其實也可以看做是慢查詢的一種 (4). aof重寫/rdb fork發生?瞬間會堵一下Redis服務器。 (5). 其他.................. 4.?查詢原因 演講者一開始懷疑是網絡問題,但是并未發現問題,觀察各種對比圖表,tcp?listenOverFlow和timeout經常周期出現。(贊一下這個監控,我們監控現在還沒有這個層面的) 有關listenOverFlow: 查看現有的連接數是否大于設置的backlog,如果大于就丟棄,并相應的參數值加1。其中backlog是由程序和系統參數net.core.somaxconn共同設置,當backlog的值大于系統設置的net.core.somaxconn時則取net.core.somaxconn的值,否則取程序設置的backlog值。這種出錯的方式也被記錄在TcpListenOverflows中(其只記錄了連接個數不足而產生溢出錯誤的次數!)。 覺得可能和TCP相關,于是分析了Tcp三次握手:最后一次握手客戶端的請求會進入服務器端的一個隊列(可以認為是下三圖)中,如果這個隊列滿了,就會發生上面的異常。(accept) (1) TCP三次握手:? (2) redis客戶端與redis服務器交互的過程(本質就是TCP請求) (3)?I/O 多路復用程序通過隊列向文件事件分派器傳送套接字的過程 (4) 和redis有什么關系呢? 由于Redis的單線程模型(對命令的處理和連接的處理都是在一個線程中),如果存在慢查詢的話,會出現上面的這種情況,造成新的accept的連接進不了隊列。 如果上面的圖沒法理解的話,看看這張圖: 5. 解決方法: (1) 對慢查詢進行持久化,比如定時存放到mysql之類。(redis的慢查詢只是一個list,超過list設置的最大值,會清除掉之前的數據,也就是看不到歷史) (2) 對慢查詢進行報警(頻率、數量、時間)等等因素 (3) 打屁股,哈哈: (4) 其實應該做的是:對業務端進行培訓,告訴他們一下redis開發的坑,redis不是萬金油,這個和Mysql DBA要培訓Mysql使用者一樣,否則防不勝防。 比如他執行了 monitor, keys *, flushall, drop table, update table set a=1; 這種也是防不勝防的(
當然也可以做限制,利用rename-command一個隨機數),但是提高工程師的水平才是關鍵。 參考文獻:redis 如何處理客戶端連接
總結
以上是生活随笔為你收集整理的美团在Redis上踩过的一些坑-1.客户端周期性出现connect timeout的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。