php+redis在實際項目中HTTP 500: Internal Server Error故障排除的方法

來源:互聯網
上載者:User
使用者量快速增長,訪問量在短時間內翻倍,由於前期容量規劃做得比較好,硬體資源可以支撐,可是軟體系統方面出現了大問題:40% 的請求都會返回 HTTP 500: Internal Server Error

問題描述
使用者量快速增長,訪問量在短時間內翻倍,由於前期容量規劃做得比較好,硬體資源可以支撐,可是軟體系統方面出現了大問題:
40% 的請求都會返回 HTTP 500: Internal Server Error
通過查看日誌,發現錯誤是在 PHP <-> Redis 的串連處理上
調試處理

第1次
剛開始時並沒有找到根本原因,只能嘗試各種與錯誤相關的辦法,例如:
增加 PHP 串連數,並把逾時時間從 500ms 增加到 2.5s
禁止掉 PHP 設定中的 default_socket_timeout
在主機系統中禁止掉 SYN cookies
檢查 Redis 和 Webservers 的檔案描述符數量
增加主機系統的 mbuffer
調整 TCP backlog 數量
……

嘗試了很多方法,但全部無效

第2次
想在預發布環境中重現這個問題,可惜,還是沒成功,應為流量不夠大,無法複現

第3次
會不會是代碼中沒有關閉 Redis 串連呢?
正常來講,PHP在執行結束時會自動關閉資源串連,但老版本中會有記憶體流失的問題,保險起見,把代碼都修改一遍,手動關閉串連
結果還是無效

第4次
懷疑目標:phpredis 這個用戶端庫
做 A/B 測試,替換回 predis 這個庫,部署到資料中心中 20% 的使用者量上
得益於良好的代碼結構,替換工作很快完成
可結果依舊是無效,但也有好的一面,可以證明 phpredis 沒問題嘛

第5次
查看了一下 Redis 的版本,是 v2.6,當時最新版本是 v2.8.9
升級 Redis 試一下吧,升完後還是不行
沒事兒,要保持樂觀,這不順便把 Redis 版本升為最新的了

第6次
通過尋找大量文檔,在官方文檔中發現了一個調試好方法 Redis Software Watchdog,開啟後執行:

$ redis-cli --latency -p 6380 -h 1.2.3.4min: 0, max: 463, avg: 2.03 (19443 samples)

查看 Redis 日誌:

...[20398] 22 May 09:20:55.351 * 10000 changes in 60 seconds. Saving...[20398] 22 May 09:20:55.759 * Background saving started by pid 41941[41941] 22 May 09:22:48.197 * DB saved on disk[20398] 22 May 09:22:49.321 * Background saving terminated with success[20398] 22 May 09:25:23.299 * 10000 changes in 60 seconds. Saving...[20398] 22 May 09:25:23.644 * Background saving started by pid 42027...

發現了問題:
每隔幾分鐘就向硬碟儲存一次資料,fork 一個後台儲存進行為什麼需要大概 400ms(通過上面日誌的第1條和第2條的時間可以看出來)

到這兒,終於找到問題的根源了,因為 Redis 執行個體中有大量的資料,導致每次持久化操作 fork 後台進程時非常耗時,並且在他們的業務中經常修改key,又導致了頻繁觸發持久化,也就經常產生對 Redis 的阻塞

處理辦法:使用單獨的 slave 來做持久化

這個 slave 不處理真實的流量請求,唯一的作用就是處理持久化,把之前 Redis 執行個體上的持久化操作轉移到這個 slave 上

效果非常明顯,問題基本解決,但有的時候還是會報錯

第7次
排查可能阻塞 Redis 的慢查詢,發現有地方使用了 keys *

因為 Redis 中的資料越來越多,這個命令自然會產生嚴重阻塞

可以使用 scan 進行替換

第8次
經過前面的調整,問題已經解決,隨後的幾個月,即使流量在不斷增長,也都抗住了

但他們意識到了新的問題:

現在的方式是,來一個請求就建立一個 Redis 串連,執行幾個命令,然後再中斷連線,在請求量很大時,這個方式產生了嚴重的效能浪費,一半以上的命令是用來處理串連操作的,這都超過了商務邏輯上的處理,也使 Redis 變慢

解決方案:引入 proxy,他們選擇了 twitter 的 twemproxy,只需要在每個 webserver 上安裝代理,twemproxy負責與 Redis 執行個體進行持久串連,這樣就大大減少了串連方面的操作

twemproxy還有兩個方便的地方:

支援 memcached
可以阻止非常耗時或者危險的命令,例如 keys、flushall
效果自然很完美,再也不用擔心之前的串連錯誤

第9次
通過資料分區來繼續最佳化:

對不同內容相關的資料拆分隔離
對相同內容相關的資料進行一致性雜湊分區
效果:

減少了每台機器上的請求、負載
提升了緩衝的可靠性,不擔心節點故障

以上就是本文的全部內容,希望對大家的學習有所協助。


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.