在《这垃圾 APP,差点毁了 70 万高考生》一文中,我们的报考 app 是用 5W rmb 向供应商采购。在报名当天涌入海量考生,并发数飙升至 34W,导致系统宕机,拒绝服务,导致考生无法报名,舆情哗然。
那么 5W rmb 能否支持 34W 并发呢?
先不考虑服务器资源是否够,瓶颈会首先出现在数据库读写,假设现在有 34W 并发,而且根据访问性质来看应该是报名操作,而报名操作是带有数据库 CRUD 的,Mysql 的最大连接数是 2000(假设没做分库分表,5W rmb 让开发商做分库分表显然是不可能的),一般用到 80% 就很不错了,所以连接数用 1600 来算。然后假设数据库能在 100ms 内返回 (想必也不是什么好机器),那么一个连接 1s 能进行 10 次操作,那么 1600 连接用满,能进行 1.6W 次数据库操作。
但这个也只是理论上的峰值,在实际项目中,单库是绝达不到 1.6W 写入的,并且还是涉及到多表操作的情况下。
实际上根据《高性能 MySQL》第三版 1.5 小节,在如下的测试环境中
测试机器 Cisco UCSC250 内存 384GB 存储引擎是 InnoDB 测试的数据集 2.5GBMySQL 的 buffer pool 设置为 4GB
所以在内存为 384G 的机器上,吞吐量不会超过 8000。那么 384G 机器要多少钱呢?
这是 64G 机器的价格,因此 384=646 61.8W=10.8W/ 年
因此,如果要并发支持到 8000,光数据库就至少需要 10W/Y。当然,这是假设请求在 1s 内返回的情况,假设我们允许服务能在 5s 内返回,那么此时并发能支持到 4W。还是在不考虑服务器,网络损耗的情况下,实际上是远远达不到的。
所以,用 5w 来支持 38w 并发,是绝不可能的。
回到我们刚才的计算,假设数据库吞吐量到达理论峰值,能支持 8000 用户同时访问,如果每个客户能等待 5s 的化,能支持 4w 用户 (前提是这些用户不可以同时访问,需要在 5s 内做到均匀分布,此时需要通过限流等手段来实现)
要支持 8000 用户同时访问,又需要多少个应用服务器呢?
假设我们使用 tomcat 服务,每个线程所占空间为 8M,那么光 tomcat 线程就需要: 80008=64000=64G,当然还需要有主机内存,损耗啥的,按照一倍计算就是 128G,那么需要是 21.8W=3.6W
所以,如果需要支持 4w 个用户 5s 延时的访问,需要 3.6+10.8= 14.4w rmb
这还只是服务器的钱,不算开发成本在内
那么,如果要支持 38w 的并发报名呢?这已经是一个相当大的并发量了,首先需要考虑的是抛弃掉一部分流量,可以在 cdn 就直接抛弃,或是 nginx,或者直接在应用服务器上,比如在这种情况下就只能保持 8000/380000 = 2%,只能有 2% 的请求允许进来。
可以通过 nginx+redis 的方式抛弃掉 98% 的请求,这样可以不用浪费应用服务器资源。或者直接在应用服务器上做操作,抛弃掉无法响应的请求,避免流量拖垮整个系统。