測試環境
應用結構:
JWS(基於Play定製)+2次庫表寫入+分庫分表
目標:TPS=5000
測試工具:Jmeter、Sysbench
併發線程:16
性能目標
TPS>=5000
現狀
採用Jmeter在16併發場景下測試2分鐘,最終併發在1200-1300之間,距離性能目標比較遙遠。
優化過程
- 首先考慮可能是代碼某個地方有問題,暫時沒有考慮數據庫,因爲根據經驗不應該這麼低。所以,開始反覆註釋懷疑代碼(不包括訪問數據庫的代碼),但實際測試發現數據並無任何改變。
- 開始懷疑可能是數據庫插入操作比較耗時。註釋數據庫插入代碼後,發現TPS明顯提升至14000左右,因此可以斷定瓶頸是在數據庫插入造作。
- 採用Jmeter對MySQL進行基準測試,測試得出當前MySQL的插入TPS<2800,並且觀察數據庫服務器IO uitil保持在80%以上,因此斷定當前MySQL配置已經達到頂峯。
- 檢查MySQL配置。根據《MySQL配置原理和技巧(ver 0.2).ppt》檢查關鍵配置項,最終發現general-log配置爲1,修改爲0後,性能提升300左右,達到3100多。
- 擔心Jmeter測試數據不準,採用Sysbench對MySQL做性能測試,發現TPS依然是3100,最終說明現有MySQL最高性能也就是3100了。
- 應用每次調用會做兩次數據庫插入操作,因此按照3100換算後,可以推算出應用的TPS不會高於1500,和測試情況相符。向DBA詢問線上MySQL的寫入性能數據爲5000,則推算線上應用TPS應低於2500,依然無法達標。
- 採用異步隊列+批量插入的方式,最終將TPS提升到8000以上。
優化方案
- 應用內部構建異步隊列,用於存儲請求消息。所有的請求,提交到異步隊列即立刻返回。
- 構建調度線程,調度頻率爲100毫秒;調度線程負責計算每個工作線程需要處理的請求消息數,並提交工作任務到工作線程池,並同步等待其完成。
- 工作線程池負責消費異步隊列中的消息,其線程數是3。
- 每條工作線程根據其要處理的請求消息數,決定批量進行Insert操作的數量,而不是一個請求Insert一次。
注:MySQL插入性能優化可參見:http://tech.uc.cn/?p=634