我們以一個每日百萬級別的交易支付系統作爲背景,來分析一下,在線上部署一個系統時,應該如何根據系統的業務來合理的設置JVM對內存的大小。
系統整體架構
支付訂單
1、上述業務流程中,最核心的環節是在用戶發起支付請求的時候,會生成一個支付訂單
2、這個支付訂單需要記錄幾個核心要素:
-誰發起的支付?
-對那個商品的支付?
-通過那個渠道進行的支付?
-支付的時間
等等諸如此類的信息
如果每日有百萬筆交易,在JVM的角度來看,就是每天會在JVM中創建上百萬個新的支付訂單對象
1、假設每天有100萬個支付訂單一般用戶交易行爲會集中在幾個小時內的高峯期中。
2、對於高峯期而言,每秒需要能夠支持處理100筆訂單左右。
3、假設我們的支付系統部署了3臺機器,每臺機器實際上每秒需要處理30筆訂單。
支付訂單需求
1、一次支付請求,需要在JVM中創建一個支付訂單對象,填充數據,然後辦這個支付訂單寫入數據庫,進行付款等等。
2、假設一次支付請求的處理,從頭到尾,總共大概需要1秒的時間。
3、那麼對於每臺機器而言,一秒鐘接受到30筆支付的請求,然後在JVM的新生代理創建了30 個支付訂單對象。
4、1秒鐘之後,對這30個支付訂單進行處理,就可以對它們的引用進行回收,這些訂單對象就成爲JVM新生代裏面,沒人引用的垃圾對象了。
支付對象大小:
1、直接根據支付訂單類中的實例變量的類型來計算,比如:
-Integer類型的變量數據是4個字節
-Long類型變量數據是8個字節
2、一般來說,支付訂單這種核心累呢,按照20-30個實例變量來計算,一個對象大概也就是在1kb左右。
3、對於一臺機器來說,每秒鐘處理30筆支付訂單的請求,大概佔據的空間最多就是30*1kb而已。
運行過程
1、但是真實的支付系統在運行過程中,肯定每秒還會創建大量的其他對象。我們估算一下,每秒鐘除了支付訂單對象,還會創建其他對象
2、對於30個訂單對象,需要30*1KB=30KB的內存空間,算上其他對象,那麼每秒鐘創建出來的對象,一共大概需要接近1MB左右。
3、然後下一秒,對新的請求繼續創建大概1MB左右的對象,放在新生代裏面。
4、循環多次後,新生代垃圾太多,就會觸發Minor GC回收掉這些垃圾。
JVM堆內存設置
核心目的:減少Minor GC的出現。
1.其實一般來說線上業務系統,常見的機器配置是2核4G,或者是4核8G
2.如果用2核4G的機器來部署,機器4G內存,JVM進程估計最多也就是2G內存。
3.這2G還得分給元空間、棧內存、堆內存幾塊區域,那麼堆內存估計可能也就1個多G的內存空間。堆內存還分爲新生代和老年代,那麼新生代可能也就幾百MB的內存
4.整個系統每秒需要1MB左右的內存空間,新生代只有幾百MB,運行幾百秒也就是大概五六分鐘左右,新生代內存空間就滿了,肯定會觸發Minor GC。如果這麼頻繁的觸發Minor GC,必然會影響線上系統的性能穩定性