VPS系統后台性能優化實戰


作者: 劉用, 現任新東方APP團隊高級軟件工程師

2019年開始,新東方APP團隊啟動了長達半年以上的穩定性建設工作,為什么穩定性如此重要?因為隨着每年30%以上的高速增長,現有的后端服務完全扛不住日益增多的用戶帶來的高並發,高可用場景。所以優化工作勢在必行。

如果你是一名java程序員的話,相信你也會很清楚,有時候,在研發功能的時候,僅僅是貼着產品的需求在做開發,功能是都實現了,但是沒有考慮到功能在高並發下面是否可用,響應是否及時。這就給以后的線上運行留下很多隱患。

我們做穩定性建設的原因就是要解決這些隱患,提高系統穩定性,提高單台機器的QPS性能。加快接口響應速度,優化數據庫的sql查詢。

下面看一下優化后的效果圖:

 

 以上是單獨一台服務器的吞吐率和響應時間曲線圖,從圖中可以看到,暑期吞吐率增長5倍,服務響應時間從最長的50多秒大幅度減少到0.4秒。優化效果明顯。

以下從3方面闡述優化方法:

1、如何定位后端問題

2、如何解決數據庫問題

3、如何分析和解決程序問題

一、定位后端問題的方法:

 

 kibana。可以還原線上有問題的接口的參數列表(實時性比較好,統計多台服務器的日志,統一處理)。

 聽雲  用聽雲監測慢事務,慢接口比較詳細,能准確定位接口是sql慢,還是代碼哪里慢。 

 二、數據庫知識點和優化

1、2種存儲引擎

在MySQL中,索引屬於存儲引擎級別的概念,不同存儲引擎對索引的實現方式是不同的,本次主要討論MyISAM和InnoDB兩個存儲引擎的索引實現方式。
    1.1、MyISAM引擎使用B+Tree作為索引結構,葉節點的data域存放的是數據記錄的地址,在MyISAM中,主索引和輔助索引(Secondary key)在結構上沒有任何區別,只是主索引要求key是唯一的,而輔助索引的key可以重復。

     1.2、雖然InnoDB也使用B+Tree作為索引結構,但具體實現方式卻與MyISAM截然不同。第一個重大區別是InnoDB的數據文件本身就是索引文件。MyISAM索引文件和數據文件是分離的,索引文件僅保存數據記錄的地址。而在InnoDB中,表數據文件本身就是按B+Tree組織的一個索引結構,這棵樹的葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。
聚集索引這種實現方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄。

輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄。

2、關於索引:
索引並不是越多越好,要根據查詢有針對性的創建,考慮在 WHERE 和 ORDER BY 命令上涉及的列建立索引,可根據 EXPLAIN 來查看是否用了索引還是全表掃描。
應盡量避免在 WHERE 子句中對字段進行 NULL 值判斷,否則將導致引擎放棄使用索引而進行全表掃描。
值分布很稀少的字段不適合建索引,例如“性別”這種只有兩三個值的字段。
字符字段最好不要做主鍵。
不用外鍵,由程序保證約束。
使用多列索引時注意順序和查詢條件保持一致,同時刪除不必要的單列索引。
最左前綴匹配
當查詢條件精確匹配索引的左邊連續一個或幾個列時,索引可以被用到,但是只能用到一部分,即條件所組成的最左前綴
查詢 SQL
3、關於查詢 SQL:
可通過開啟慢查詢日志來找出較慢的 SQL。
不做列運算:SELECT id WHERE age + 1 = 10,任何對列的操作都將導致表掃描,它包括數據庫教程函數、計算表達式等等,查詢時要盡可能將操作移至等號右邊。
SQL 語句盡可能簡單:一條 SQL只能在一個 CPU 運算;大語句拆小語句,減少鎖時間;一條大 SQL 可以堵死整個庫。
不用SELECT *。
IN 的個數建議控制在 200 以內。
不用函數和觸發器,在應用程序實現。
不用 JOIN。
使用同類型進行比較,比如用 '123' 和 '123' 比,123 和 123 比。
盡量避免在 WHERE 子句中使用!=或<>操作符,否則引擎將放棄使用索引而進行全表掃描。
列表數據不要拿全表,要使用 LIMIT 來分頁,每頁數量也不要太大。
4、升級硬件
根據 MySQL 是 CPU 密集型還是 I/O 密集型,通過提升 CPU 和內存、使用 SSD,都能顯著提升 MySQL 性能。
5、讀寫分離
也是目前常用的優化,從庫讀主庫寫,一般不要采用雙主或多主引入很多復雜性,盡量采用其他方案來提高性能。

6、原則上索引個數不大於3個。條件復雜的情況,用復合索引代替多個單獨索引。

三、程序問題

優化程序的前提是你必須先把接口代碼完整讀一遍,深刻理解業務,然后根據聽雲定位接口慢的地方。

vps系統里面有很多循環查詢數據庫的地方,以及in后面一個很大的集合的情況。這種情況可以采用多線程並行處理,加快速度。

1、In語句后面的參數集合太大,怎么辦?
把數據庫壓力轉移到程序中,拆分in后面的參數,采用多線程循環獲取數據,用countDownLatch計數,等待所有返回。
2、第三方接口返回速度太慢,怎么辦?
接口熔斷機制,設置超時時間為6秒,加上3次重試機制。對於6秒以內的慢請求,添加緩存
3、對於復雜的join group by等操作,數據庫返回慢怎么辦?
把復雜的sql用java代碼來實現邏輯,數據庫只是執行簡單的查詢,后面的處理都交給代碼來實現。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM