秒殺系統性能測試和優化

對於大併發量的系統,有幾個可能須要優化的點,下面咱們要一步步測試來優化這個系統。redis

測試目標

對於一個系統,幾個經常使用的評價指標是:平均響應時間、吞吐率、qps等。個人測試主要測試3個接口sql

主頁(訪問根路徑,沒有數據庫交互)
秒殺接口暴露(暴露秒殺接口,有後臺數據交互)
執行秒殺操做(插入秒殺成功記錄和減庫存一個完整的事務操做)
對於這三個接口,咱們主要的測試目標和優化目標是平均響應時間,固然這是創建在數據正確返回的基礎上的,失敗率過高那這個平均響應時間是沒有意義的。
這裏的優化側重於後端數據庫和內存方面的優化。數據庫

測試環境

我是在Windows10下用jmeter來進行負載測試和壓力測試,其餘環境以下,涉及具體配置再提。windows

Tomcat8.0.38
Jdk1.8 hotspot vm
Mysql 5.7
Redis 2.7.3後端

測試過程

首先進行主頁測試,咱們訪問tomcat的主頁,使用jmeter的線程組中的線程數模擬用戶數,不斷增長線程數對主頁進行性能測試
咱們將結果數據寫到一個xml文件中。首先咱們模擬5000個用戶同時請求主頁。緩存

5000個用戶同時請求主頁

設置循環次數爲2,即一共有10000個請求將被髮送。
tomcat

從響應的結果能夠看到,沒有錯誤數,這10000個請求所有返回成功了,只是有的請求慢有的請求快。平均的響應時間在300ms, 50%的請求的響應時間平均爲87ms。到後面愈來愈多的請求開始等待,這裏能夠想到的優化的點在於tomcat的線程池中線程的數量,愈來愈多的請求在等待隊列中。查看tomcat的配置後發現最大線程數爲maxThreads=」150」,好那咱們用150個線程,循環10次,也就是一共1500個請求,那結果會是什麼樣呢?
併發

平均相應時間爲5ms,前50%的請求的平均響應時間爲1ms。
可是這裏並不能直接修改tomcat的最大線程數來優化。複雜點說就是這是一個複雜的東西,線程數越大,你也要有相應的cpu來執行啊。直接點說就是,我不懂。。。
我把tomcat的線程數設置爲500,而後起5000個線程發送10000個請求,而後獲得了:
性能

 

 

 比以前的更差了。不管是平均相應時間仍是錯誤率。簡單粗暴的去改線程數是不可行的。這裏咱們不去管tomcat的線程數或者是其餘層面的優化,咱們只專一於後端數據庫層面的優化。測試

 

500個用戶同時請求暴露秒殺接口

爲何用500個,是爲了減小由於tomcat請求等待帶來的數據偏差。 
直接向MySQL請求數據 
先模擬500個用戶,每一個用戶發送10次請求。該請求相應的操做爲根據id向數據庫查詢一條記錄。獲得了這樣的數據。

 

 

 期間打開windows的性能監控器,發現磁盤IO有變化,IO百分比最高的時候也不超過15%。 
這樣的操做,錯誤率爲0,至關穩定,平均響應時間爲1406ms。 

模擬5000個用戶,每一個用戶發送一次請求

 

 

 磁盤的IO百分比一度達到了100%。從數據的絕對值來看,這樣的測試沒有意義了,由於瓶頸不在MySQL瓶頸是tomcat的鏈接池最大線程數爲maxThreads=」150」 愈來愈多的請求在等待隊列中,由於咱們前面分析過的tomcat。可是數據的相對值是有意義的。

 

 

使用redis緩存數據 


仍是模擬500個用戶,每一個用戶發送10次請求。

 

 

 響應速度顯著提升,注意一個值,Min=1,有些請求幾乎不足1ms,由於redis直接從內存讀取數值,很是快若是不是tomcat的請求在排隊,我想平均響應時間是個位數。 

Redis下模擬5000個用戶,每一個用戶發送一次請求。會是什麼結果呢?

 

 能夠看到:模擬5000個用戶比模擬500個用戶的響應時間要慢不少,平均響應時間大概是8倍

 

使用150個線程,循環100次,即發送15000次請求,獲得:

 

 能夠看到,150個用戶的話這種響應速度是比較快的,所以能夠初步判定:響應的瓶頸在於tomcat的請求排隊等待

 

這個優化的過程我想到了不少東西,感受就是,優化是無止盡的。
好比,我想到了內存回收那一塊。選用合適的垃圾收集器,儘量地減小GC時stop the world的時間和次數顯然對於一個秒殺系統來講是很是對的優化方向。這裏我嘗試用過幾款垃圾收集器好比parNew,G1來對比他們的平均響應時間,可是屢次測試後沒有明顯的差距。有兩個緣由,一是這個接口沒有產生太多的大對象,二是這個優化並不太明顯。後面有機會的話仍是但願繼續在內存方面進行優化,感受內存回收方面有點神祕,很想試一試。

能夠看到redis的使用很大程度上提升了響應的時間。上面那個接口只是暴露一個地址,這些地址每一個產品都只有一個,那這樣的場景是能夠用redis的。可是有些操做並無辦法使用緩存。好比執行秒殺這個操做。
這個操做是個事務型操做。若是其中一個操做失敗了,我就讓他rollback,這樣的話,應該會有更多的併發問題。
見下篇。

原文連接:https://blog.csdn.net/OWEN_7/article/details/78319115

相關文章
相關標籤/搜索