1. 程式人生 > >一次伺服器效能瓶頸查詢和優化經歷。

一次伺服器效能瓶頸查詢和優化經歷。

10月份 公司伺服器頻繁出現問題,整個優化過程如下
最開始能所做的工作,為了應急只能頻繁重啟,頻繁重啟的原因只有一個,因為重啟無效只能暫時恢復,立馬又會因為伺服器記憶體爆掉而癱瘓,解決問題的方式只有頻繁重啟。高峰時期的請求數和資料庫處理能力不在一個平衡點。大量重啟之後,伺服器恢復正常。整個過程常常伴隨著阿里雲資料庫的主備切換。

公司業務架構比較古老,一臺windows(存在的原因是因為被部分終端指定了ip)+兩臺linux(其中一臺裝了nginx。通過域名訪問 到nginx 再分發到兩臺linux)+memcached快取session 沒了,外加一個sql server資料庫例項。伺服器和資料庫均掛靠在阿里雲上。

首先從公司的整個伺服器架構分析出問題的點有兩個
1. 伺服器記憶體爆掉,導致伺服器響應不了新的請求,特徵同步變得非常緩慢,再慢慢到同步不了
2. 資料庫死鎖異常嚴重。效能極差

觀察到
資料庫的各項指標
優化過程前的iops,以及 cpu 情況,資料庫連線數情況 分別取了17號到21號的資料

cpu 

這裡寫圖片描述
這裡寫圖片描述

iops

這裡寫圖片描述

這裡寫圖片描述

資料庫連線數

這裡寫圖片描述

這裡寫圖片描述

總結:iops 經常達到1W2的水平,之前一直在6K。公司對伺服器進行了硬體升級,6k–>12k 之後iops 又重原來的6k 直接衝到了現在允許的12k. 伺服器依然經常奔潰,說明應用確實存在非常大的問題。通過簡單的硬體升級 只能稍微提升些資料庫的效能。但是根本問題並沒有得到解決
cpu 在可以接受的範圍內。
連線數異常 非常不穩定。

脫離掉指標
多天觀察伺服器執行狀態。
對比伺服器正常執行時期,分析jvm 中各個類的佔用情況。
正常情況下:

這裡寫圖片描述

當伺服器癱瘓時 表現 [B 失控一直增長到撐爆 指定的jvm 4G記憶體大小。 [B 是bytes資料
伺服器正常執行時期並不會一直增長 大概在200多MB左右。高峰時期會在400~500Mb波動。由此可以基本排除是我們應用的啟動引數設定問題。正常執行的專案 連1.5g記憶體都沒有用到。

關於連線數
在一次伺服器癱瘓前夕,通過觀察日誌 看到連線池內連線數 被佔用完了,其他請求得不到相應的連線。檢查專案的連線池,發現伺服器正在執行的專案,五個專案,兩臺linux上分別有兩個,windows有一個。關於連線池的初始連線數,最大連線數不一樣。甚至有
開發環境的引數在正式上跑。我根據公司的業務分析,更改了所有專案最大連線數,初始連線數,之後資料庫連線數基本穩定在800 左右。•

拿到伺服器崩潰時候的dump.檔案
分析拿到的byte[] 資料的內容大部分都是終端 post過來的資料。結合資料庫死鎖的情況。可以得出這樣的結論 並不是程式碼導致的記憶體洩漏引發的伺服器oom, 而是資料庫效能
差,遠遠跟不上終端post過來的資料,資料大量堆積在伺服器正在處理,沒有返回導致GC 沒有辦法回收。記憶體越來越高,伺服器爆了。
之後10-24 的伺服器崩潰拿到相應的dump,又追蹤到了一些公司內部報表的功能。生成本來是應當凌晨五點執行,但是卻在白天執行。當晚我立即把更新報表功能去掉(介面依然存在)留著凌晨定時任務生成,並優化了下語句。
11 -3 web商家端和雲店出現短暫故障,分析dump得到再次由此更新報表功能引起。晚上我直接把介面去掉了。反覆確認正常使用不可能有調更新功能的介面,這次直接把更新介面下了。

關於阿里雲主備切換
因為伺服器崩潰往往伴隨這阿里雲資料庫發生主備切換。因為先後順序無法確定
無法判定是否是因為阿里雲導致。後來知道了因為我們應用的慢sql 在資料庫中發生了死鎖
導致資料記憶體也飆高 ,後來的請求也處理不完阻塞伺服器。就算重啟伺服器,資料庫死鎖依然存在,資料庫跟伺服器的處理速度完全不在一個點上。資料庫死鎖依然存在,才是導致伺服器重啟短暫有效的主要原因,還有一個原因伺服器重啟之後會被大量重複請求和正常請求阻塞。

所以目前的主要問題都是由於sql效率低,資料庫效能差,以及一些不合適的報表功能導致。最終決定採取資料庫優化的方案,下面是對資料庫的整體優化。由yydba大神陳暢亮主導,我個人配合實施ude資料庫優化方案一期,二期。方案的確定是陳暢亮在結合我對專案,以及業務的瞭解下做出的決策。一期效果不明顯。二期做完,截至到目前2016-12-20為止再未發生過伺服器宕機,可見二期效果非常明顯。
一期優化工作。
對我們現有業務的大表查詢sql語句中 rowlock 用nolock 進行替換,並且略微調整語句結構,現階段業務暫時還沒有牽涉到支付,並且還沒要到這麼嚴格的級別。所以並不需要rowlock 。特別業務可以特別調整。
分析阿里雲 所給出的慢sql 統計。包括業務sql,索引。
分析整個庫的各個表的各類指標。
確定二期執行方案

二期優化工作
對資料庫中最大的的八個表進行結構變更。
優化原理:
1. 資料庫表增加一列主鍵ID 並全部重新生成表的儲存結構和索引結構,(減少整個庫的資料所佔空間大小,原理所有的索引頁都有物理主鍵資訊,而主鍵欄位型別變更帶來佔用空間變少從而間接減少了對記憶體的壓力以及 iops等一系列影響)
2. 提高關於一頁8kb 的利用率(原有Kid是非順序儲存,而id是順序儲存)
注 kid即為uuid
可能引發的問題
1. 資料重整導致資料庫變更表記錄時間戳大批量資料需要下載(公司業務機制,sql server timestamp欄位為終端下載資料的判斷條件)
2. 資料遷移過程可能 會發生未知錯誤。
3. 整個表結構變更之後大部分索引需要重新調整,否則部分功能查詢會受到影響
實施可能性
1.專案大量原生sql 只有少量orm程式碼。使得不修改程式碼就可以完成優化。當然會有語句需要特別調整除外。
2.整個過程具有可逆性。發現未知情況可以回滾回來。
最後決定按業務分批
第一批 訂單模組
第二批 商品模組

用了一個週末兩天時間在測試庫上完成所有變更,並且在測試環境上跑了一個星期,並沒有明顯問題。最後開始實施到正式庫。
整個遷移過程指令碼之前和成果。 已經另外整理指令碼所以不在此重複下去。表結構變更以及索引調整給正式庫了大約 節約了250G 儲存空間,iops也下降明顯。

在第一批優化之後伺服器由於索引結構變更,已經我們修改的索引未覆蓋到所有的功能,出現了一些鎖表現象引發伺服器宕機的情況,在接下來的每天 我都抓出了一些慢查詢語句進行優化。伺服器也漸漸變穩定。

第二次優化之後伺服器 由於準備時間充分,所以這次索引調整覆蓋了大部分查詢。再未發生過宕機。一直穩定執行。

以下是二次優化 資料庫Iops,cpu,資料庫連線數的情況

分別取了 11-7 到11-9 三天的資料
cpu

這裡寫圖片描述

這裡寫圖片描述

iops
這裡寫圖片描述

這裡寫圖片描述

連線數

這裡寫圖片描述

這裡寫圖片描述

資料庫優化結果。
iops 下降效果尤為明顯。大概平均在2k~3k左右。
歸於以上工作,還有許多細節,脾氣不好的伺服器終於穩定下來,並且從大部分客戶反饋 各種操作都相比之前快了許多。