昨日,公司php調用redis報錯:read error on connection 2015-01-29 23:59:050.13330000,redis存放的是用戶session。php
在網上查詢,你們說法都比較一致,說是php.ini文件中的一個配置項致使:redis
default_socket_timeout = 60服務器
因爲redis擴展也是基於php 的socket方式實現,所以該參數值一樣會起做用。session
解決方法是:socket
一、直接修改php.ini,將其設置爲咱們想要的值(這個不推薦)日誌
二、在咱們的腳本中經過如下方式設置,這樣就比較靈活,不對其餘腳本產生影響blog
ini_set('default_socket_timeout', -1); //不超時內存
可是,一看,修改的兩個參數,一個是php的全局參數,一個是redis的超時操做,都應該按照實際狀況來修改,並且,設置超長超時時間或者不超時都是不合理的;資源
繼續檢查redis發現,/usr/local/redis_16379/src/redis-cli -p 16379 info(服務器配置的redis端口爲16379,分配內存爲8000M)同步
used_memory_human:7.49G,佔用內存已經7.49G
db10:keys=53090286,鍵值5000多萬
居然是鍵值佔滿了內存,檢查php的調用代碼,發現php居然沒有設置redis的鍵值過時時間,修改php代碼,對鍵值設置過時時間
設置完以後,發現以前的鍵值由於沒有設置過時時間,程序不會自動刪除,因而用腳本刪除主redis上對應的session,
/usr/local/redis_16379/src/redis-cli -p 16379 -n 10 keys "PHPSESSION_wc*" | xargs /usr/local/redis_16379/src/redis-cli -p 16379 -n 10 del
將大部分過時數據刪除掉,刪除必定數量的數據以後,報錯消失,redis鏈接正常。
可是,發現redis主從,在這樣刪除以後,從數據居然沒有同步,主的數據和從數據差距有400多萬不一致,也沒有再發現bgsave操做,查看從日誌Trying a partial resynchronization,發現由於過濾keys佔用太多資源,形成服務器負載飆升,slave斷開與主機的鏈接,須要從積壓空間中找回斷開期間的數據更新記錄。可是由於刪除數據太多,斷開的時間足夠長,master 拒絕 slave 的部分同步請求,從而 slave 只能進行全同步。
至此,在slave上對數據進行全量同步,數據恢復正常,業務正常。
須要注意幾點:
1.redis數據,正常狀況下,設置過時時間,不然可能出現,存儲鍵值過多,佔用完了預設內存,致使新的鍵值沒法存儲,調用redis失敗的;
2.超時時間必須根據實際業務來設置;
3.若是slave一直鏈接不上master,可能須要進行全量同步。