分析和解決方案
1,情況描述:網站發標后,出現卡頓,最后出錯。
2,問題排查:最后一個版本的更新是在兩個星期前,照理來說,應該不是代碼的問題。但是一時找不到問題所在,還是先對代碼進行測試。使用排除法,修改數據后,在測試環境,生產環境測試,均正常。既然測試正常,那么排除代碼的問題。那懷疑可能是服務器的問題,接下來查看Linux環境的運行情況。
3,linux系統,命令top可以查看系統資源使用情況。最近兩次查看 ,如圖一,圖二。

圖一

圖二
由這兩個圖,可以看出來,mysql的服務幾乎把資源耗盡。
ps:發標前的兩三分鍾,CPU就已經高達140%,在60 - 140震盪。
第一行的 load average 表示系統負載,即任務隊列的平均長度,3個數值分別統計最近1,5,15分鍾的系統平均負載
- 系統平均負載:單核CPU情況下,0.00 表示沒有任何負荷,1.00表示剛好滿負荷,超過1側表示超負荷,理想值是0.7;
- 多核CPU負載:CPU核數 * 理想值0.7 = 理想負荷,例如:4核CPU負載不超過2.8何表示沒有出現高負載。
系統是2核,理想值是2 * 0.7 =1.4 。圖一的3.46,圖二的7.69,明顯大於理想值。
進程信息
- K:
%CPU= (CPU usage) 上次更新到現在的CPU時間占用百分比 - 圖二的將近200%,兩核的最高是200%,因此系統CPU是滿負載運行。
因此在圖二的時候,系統卡頓了一段時間。如果再多些訪問量,系統應該就會出錯。
常見原因
系統執行應用提交查詢(包括數據修改操作)時需要大量的邏輯讀(邏輯 IO,執行查詢所需訪問的表的數據行數),所以系統需要消耗大量的 CPU 資源以維護從存儲系統讀取到內存中的數據一致性。
4,mysql分析數據運行狀態:show processlist;
在數據庫,執行上面語句,如圖

可以看出,這個查詢語句有問題。state為sending data。單獨拿出來在數據庫執行,時間有點久。當集中訪問時,數據庫占用資源飆升。
5,查看NGINX日志,訪問量並不多,訪問的比較多的鏈接和show processlist;查詢的情況基本吻合。
6,查看系統日志。圖二的時候,自動投標部分用了14秒。而測試的時候是2秒(測試時候,只是單獨發標)。真實發標時,訪問比較多,兩種情況的結合,影響變大了。單獨發標,或者單獨訪問多時,影響比較小。
7,解決方案
1,優化數據庫語句
2,增加資源,采用緩存,分布式等。這個方案保留。
7.1,優化數據庫語句
7.1.1 查看查找項目的查詢語句,投標表關聯的項目表的項目ID,即投標表的項目ID,pid加上索引(index)。

圖:沒有索引時

圖:加上索引時
由上面兩個圖可以看出來,加上索引后,訪問的時間變為幾十毫秒。時間快了15- 20倍。
這樣訪問首頁和“我要投資”頁面的時候,系統資源壓力大大降低。
7.1.2 查詢公告
首頁只要顯示5條數據,現在是查詢出了全部。在數據庫執行語句,查詢全部時,是100多ms,查詢限制5條時,是10多ms,時間快了10倍。

圖:content查詢修改前。

圖:content查詢修改后。
運行時間快了好幾倍。
7.1.3 查詢投資排行榜
換種查詢方式,在數據庫里執行,由80ms到40ms,時間提高一倍。
由
SELECT sum(money)
as investSum ,(select lname from P_user p1 where p1.id = userId ) as lname FROM personTransactionDetail where type = 4 and state in (1,3) GROUP BY userId,lname ORDER BY sum(money) DESC limit 5
改為:
SELECT sum(money)
as investSum ,lname FROM personTransactionDetail a, P_user b where a.userId = b.id and type = 4 and state in (1,3) GROUP BY userId,lname ORDER BY sum(money) DESC limit 5

圖:投資排行榜修改前

圖:投資排行榜修改后
由200多ms到70ms,時間快了3倍。
連接查詢的效率比子查詢的高。
執行子查詢時,MYSQL需要創建臨時表,查詢完畢后再刪除這些臨時表,所以,子查詢的速度會受到一定的影響,這里多了一個創建和銷毀臨時表的過程。
因此,盡量用連接查詢。
參考:子查詢和關聯查詢 效率 ,表連接查詢與where后使用子查詢的性能分析
結合自己的實驗,和別人的經歷,確實是連接查詢的效率比子查詢的高。
7.1.4 自動投標插入方面,先保留修改,看后面執行情況。
后續
修改后的運行情況:發標前,mysql服務,cpu的占用2%左右。發標中,不超過10%。自動投標部分,用時2m,正常了。
經過上述調整后,系統運行正常了。
對於訪問比較頻繁的首頁的每個連接做了數據庫查詢優化后,訪問數據都有所提升,因此效率大大提高了。
現在的網站主要的壓力都來自於數據庫,頻繁的數據庫訪問經常會使服務器死機。良好的數據庫設計和優化查詢語句是很重要的。
網站架構先是小型架構,逐漸演變成大型架構的。大型網站由小型網站演化而來,隨着業務發展,逐漸發展。
參考:大型網站技術架構 ,個人GitHub筆記
