一、并发量预估
作为后端的程序开发人员,经常听到高并发,但是高并发到底有多高?其实是没有数值定义的
但是如果在面试的过程中,或者跟别人沟通的过程中,有人提到百万级并发那么可能三种情况
- 他在吹牛皮
- 他没有用对并发这个词
- 他真的很NB(例如:天猫双11关联项目组的)
截至2019/11/11,支付宝双11订单峰值是 54.4W笔/秒,单个服务的集群的QPS破百万的应该也很少
要应对多少并发,我们要看一天有多少访问量/请求量,假如是一个每天有1亿请求的网站/服务
那么:
- 平均QPS=100000000 / (24 60 60)≈1158
- 峰值QPS=10,000,000 0.8/(24 60 60 0.2)≈4630
峰值的计算逻辑是根据二八原则,80%的请求集中在20%的时间段内。
这只是通用的计算方式,如果涉及到秒杀或者其他特殊的场景就要用其他的方式来预估了。
所以,高并发的程序,一定是要看自己要实际的用户数跟访问需求
二、服务器预估
1、应用服务器
如果接口响应耗时的99线在100ms以内,单次返回内容<=1KB,那么4C8G的通用虚拟机,通常可以承受300QPS,4630/300≈16,16台应用服务器做负载均衡,分摊请求压力
2、数据库服务器
数据库服务器阿里云8核32GB,扛个1.5W+IOPS都是没问题的,只要没有长事务,easy
根据数据量以及索引的情况,预估好磁盘空间即可
3、负载均衡服务器&带宽
负载均衡服务器通常就NGINX,按照NGINX官方的介绍,志强CPU,18核36线程,请求<=1KB静态资源,只用1个核心,就可以支撑7W+连接
那么2台计算型4C8G云服务器搭建两个NGINX服务器基本上也OK了,服务器带宽的话,46301KB8≈37MB,考虑到冗余,50M带宽也基本够用了
3、其他服务器
缓存服务器,阿里云、腾讯云有成熟服务,根据用量购买即可
CDN服务器,七牛、又拍云有成熟服务,根据用量购买即可
服务器都是钱,所以,有多少的量估多少,估多了,老板也不愿意出这个钱的。
三、缓存方案和场景
1、工具
1、外部缓存:浏览器缓存、NGINX缓存、CDN缓存
2、本地缓存:MemoryCache(.NET)、Caffeine(Java)
3、分布式缓存:Redis、Memcached、MongoDB
2、场景
查询类页面,例如商品介绍,博客文章,都可以用浏览器缓存、CDN
对数据一致性要求不高的,可以用本地缓存,比如站点访问量信息(需要NGINX配合做iphash负载均衡)
对于重要的信息,查询两大,且需要更新的,建议放在Redis,最好要做缓存预热
3、注意事项
一定要做好缓存容量的预估,不要把缓存服务器搞崩了
如果是Redis,要控制好单Key存储的值大小,因为Redis6.0之前都还是单线程设计,但Key值太大会影响性能,通常但Key值控制在1M以内
四、数据库拆分
如果是百万级的数据,单库单表就扛得住,前提是不能有过多的字段,或者是varchar>1000的这种大字段建议做垂直拆分,大字段拆分到扩展表里面。如果数据超千万,会有一定的读写压力,建议做水平拆分
1000W<数据量<10*1000W,2库8表,平均每张表1250W数据
101000W<数据量<1001000W,4库64张表,平均每张表1500W数据
无论拆几个库几张表,表名都应该是连续的且不重复的,例如2库8表,那么:
db0中包含表t0-t3,db1中包含表t4-t7
1、拆分之后的好处
- 单个数据库承受的连接数都是有限的,分开后可以分摊查询压力,读写是在太频繁还可以拆分服务器升配置
- 拆表之后可以提升查询效率,单表数据少了扫描磁盘的次数减少了,压力减少性能提升
2、拆分的纬度
- 按照用户ID取模,比如 uid%4=0/1/2/3,数据分别放在 user_0、user_1、user_2、user_3这4个表
- 按照时间切分,每三个月1个数据库
3、分片(Sharding)工具
分库后,CRUD需要指定库名表名,部分查询场景还需要从多个表查询后聚合查询结果,需要有工具支持,可以自己写,也可以用现成的:
Sharding-JDBC(Java),EFCore.Sharding(.NET Core)
4、全局唯一ID
分库分表之后,以订单数据为例,就不能用各个表的自增列作为订单ID了,会重复,就算把自增的种子分段设置,也是有个明显缺陷的方案,所以还是需要有办法可以生成全局唯一ID,通常有
- 基于Redis生成全局唯一ID
- 使用雪花算法生成全局唯一ID
- 利用数据库即时单个/批量/预先生成