取自:https://wx.zsxq.com/group/15552551584552/topic/814811112852482
一个请求如果需要消耗 10ms,但是其中 9 毫秒是 CPU 调用查 DB,实际这个请求需要消耗本机 CPU 1ms,也就是单核 QPS = 1000ms/1ms=1000,8 核机器理论支撑最大 QPS 为 8000。
如果用单线程去压这个服务,RT(Reaction Time)是 10ms(1ms+9ms DB),那么 QPS 是 100,但是其中 CPU 有 90% 的时间在等待 DB 返回,相当于 90% 的时间在休息,那么需要用 10 个并发一起来压,刚好填满休息的 9ms,这样让 CPU 跑到 100%,RT 还是 10ms,但是 QPS 会提升到 1000。
如果 10 个并发,QPS 提升到 1000 后,继续加并发到 20,因为 CPU 负载已经 100% 了,你可以理解这个时候前 10 个并发跑着的时候,后面 10 个并发都要等 10ms,然后再轮到自己,所以 RT=10ms(等待CPU调度时间)+1ms(CPU 实际处理时间)+9ms(DB 处理时间)=20ms,QPS 仍然是 1000。
几个扩展场景:
场景:
还是上面的例子,如果 9ms 访问 DB 改成需要访问两次 DB,分别为 4ms、5ms,那么我们可以将代码重构,两次 DB 访问不用串行改成并行(业务允许这么做),那么总 RT=1ms(本机 CPU 耗时)+max(4,5)ms = 6ms。RT 从 10ms 优化到了 6ms,减少了 40%,是个很了不起的改进,如果还是用 10 并发来压那么总 QPS 变了吗?
没有。CPU 依然只能够执行 1000 个请求每秒,因为每个请求需要 1ms 的 CPU 时间,这是硬瓶颈。并且如果未来进一步提高并发,QPS 不会变化,RT 会继续增大。
最简单计算 CPU time 和 CPU wait time 的方法
一个并发跑的时候,如果 RT=1000ms,一次业务请求调用了 MySQL 10 次,每次 10ms 总共 100ms;
调用了服务 B 2 次分别为 100/400ms,2 次总共 500ms,那么对于这个业务 CPU time=1000(总RT)-100(MySQL)-500(服务B)=400ms,wait time=1000-400=600ms