美文网首页
8、每日百万交易的支付系统,如何设置JVM堆内存大小

8、每日百万交易的支付系统,如何设置JVM堆内存大小

作者: 呢看了看 | 来源:发表于2020-11-22 11:12 被阅读0次

        首先用户在商城系统提交支付一个订单的请求,接着商城系统把这个请求提交给支付系统,支付系统就会生成一个支付订单,此时订单状态可能是“待支付”的状态。

        然后支付系统指引用户跳转到付款页面,选择一个付款方式。然后用户发起实际支付请求,支付系统把实际支付请求转交给第三方支付渠道,比如微信或者支付宝,他们会去处理支付请求进行资金转移。如果微信或者支付宝处理完支付之后,就会返回支付结果给支付系统,支付系统可以更新自己本地的支付订单状态变成“已经完成”。


每日百万交易的支付系统的压力在哪里?

        每日百万交易的支付系统,最核心的环节就是,在用户发起支付请求的时候,会生成一个支付订单。在JVM的角度来看,就是每天会在JVM中创建上百万个支付订单对象。所以支付系统,压力来自很多方面,包括高并发访问、高性能处理请求、大量的支付订单数据需要存储等。

        从JVM层面来讲,支付系统的最大压力,就是每天JVM内存里会频繁的创建和销毁100万个支付订单。所以核心问题是:

    【1】我们的支付系统需要部署多少台机器?

    【2】每台机器需要多大的内存空间。    

    【3】每台机器上启动的JVM需要分配多大的堆内存空间?

    【4】给JVM多大的内存空间才能保证可以支撑这么多的支付订单内存里的创建,而不会导致内存不够直接崩溃。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

支付系统每秒钟需要处理多少笔支付订单?

        线上系统最核心的一个参数,也就是JVM堆内存大小的合理配置,第一个要计算的,就是每秒钟我们的系统要处理多少笔支付订单?假设每天100万个支付订单,那么一般用户交易行为都会发生在每天的高峰期,比如中午或者晚上。假设每天高峰期大概是几个小时,用100万平均分配到几个小时里,大概是每秒100笔订单左右,假设支付订单部署了3台机器,每台机器实际上每秒大概处理30笔订单。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

每个支付订单处理要耗时多久?

        如果用户发起一次支付请求,那么支付需要在JVM中创建一个支付订单对象,填充进去数据,然后把这个支付订单写入数据库,还可能会处理一些其他的事情。就假设一次支付请求的处理,包括一个支付订单的创建,大概需要1秒钟的时间。可以出现一个流动的模型,应该是每台机器一秒钟接收到30笔支付订单的请求,然后在JVM的新生代里创建了30个支付订单的对象,做了写入数据库等处理。接着1秒之后,这30个支付订单就处理完毕,然后对这些支付订单对象的引用就回收了,这些订单在JVM的新生代里就是没人引用的垃圾对象了。接着再是下一秒来30个支付订单,重复这个步骤。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

每个支付订单大概需要多大的内存空间?

        我们来计算一下,每个支付订单对象大概需要多大的内存空间?可以直接根据支付订单类中的实例变量的类型来计算就可以了。比如支付订单,一个Integer类型的变量数据是4个字节,Long类型的变量数据是8个字节,还有别的类型的变量数据占据多少字节,可以计算出每个支付订单对象大致占据多少字节。一般来说,比如支付订单这种核心类,你就按照20个实例变量来计算,大概一个对象也就在几百字节的样子。算他大一点好了,就算一个支付订单对象占据500字节的内存空间,不到1Kb。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

每秒发起的支付请求对内存的占用?

        假设有3台机器,每秒钟处理30笔支付订单的请求,那么在这1秒内,肯定是有方法里的局部变量在引用这些支付订单的,那么30个支付订单,大概占据的空间是30*500字节=15000字节,大概其实也就是15Kb而已。其实是非常非常小的。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

让支付系统运行起来分析一下?

        目前我们已经把整个系统运行的关键环节的数据都分析清楚了,每秒30个支付请求,创建30个支付订单对象,也就占据Kb级别的内存空间而已。然后接着1s过后,这30个对象就没有人引用了,就成为了新生代里的垃圾了。下一秒请求过来,我们的系统持续的创建支付订单对象,不停的在新生代里放入30个支付订单,然后新生代里的对象会持续的累计和增加。直到有一刻,发现可能新生代里都有几十万个对象了,此时占据了几百MB的空间了,可能新生代空间就快满了,然后就会触发Minor GC,就把新生代里的垃圾对象都给回收掉了,腾出内存空间,然后继续在内存里分配新的对象。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

对完整的支付系统内存占用需要进行预估

        真正的支付系统线上运行,肯定每秒会创建大量其他的对象,但是我们结合这个访问压力以及核心对象的内存占据,大致可以来估算一下,整个支付系统每秒钟大致会占据多少内存空间。其实如果你要估算的话,可以把之前的计算结果扩大10倍~20倍。也就是说,每秒钟除了在内存里创建支付订单对象,还会创建其他数十种对象。那么每秒钟创建出来的被栈内存的局部变量引用的对象大致占据的内存空间就在几百KB~1MB之间。然后下一秒继续来新的请求创建大概1MB的对象放在新生代里,接着变成垃圾,再来下一秒,循环多次之后,新生代里垃圾太多,就会触发Minor GC回收掉这些垃圾,这就是一个完整系统的JVM层面的内存使用模型。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

支付系统的JVM堆内存应该怎么设置?

        其实一般来说,这种线上业务系统,常见的机器配置是2核4G,或者是4核8G。如果我们用2核4G的机器来部署,那么还是有点儿紧凑的,因为机器有4G内存,但是机器本身也要用一些内存空间,最后你的JVM进程最多就是2G内存。然后这2G还得分配给方法区、栈内存、堆内存几块区域,那么堆内存可能最多就是1G多的内存空间。然后堆内存还分为新生代和老年代,你的老年代对象总需要放置系统的一些长期存活的对象吧,怎么也得给几百MB的内存空间,那么新生代可能也就是几百MB的内存了。

        这样的话,可以看到,我们上述的核心业务流程,只不过仅仅是针对一个支付订单对象来分析的,但是实际上如果扩大到10倍~20倍换成完整系统的预估之后,大致每秒会占据1MB的内存空间。那么如果你新生代就几百MB的内存空间,是不是会导致运行几百秒之后,新生代内存就满了,此时是不是就得触发Minor GC了。如果频繁的触发Minor GC,会影响线上系统的性能稳定性。

       因此可以考虑采用4核8G的机器来部署支付系统,那么你的JVM进程至少可以给4G以上的内存,新生代在里面至少可以分配到2G内存空间,这样子就可以做到将近半个小时到1小时才会让新生代触发Minor GC,这就大大降低了GC的频率。

    举个例子,机器采用4核8G,然后-Xms和-Xmx设置为3G,给整个堆内存3G内存空间,-Xmn设置为2G,给新生代2G内存空间。而且假设你的业务量如果更大,你可以考虑不只部署3台机器,可以横向扩展部署5台机器,或者10台机器,这样每台机器处理的请求更少,对JVM的压力更小。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

SpringBoot是启动的时候可以加上JVM参数,Tomcat其实就是bin目录下的catalina.sh可以加入JVM参数。

相关文章

网友评论

      本文标题:8、每日百万交易的支付系统,如何设置JVM堆内存大小

      本文链接:https://www.haomeiwen.com/subject/ewzyxktx.html