01高并发系统:通用设计方法
1 应对大流量的方法
1.1 横向扩展
分而治之的思想,采用分布式部署的方式把流量分开,让每个服务器都承担一部分并发流量。
如下图所示,server越多整个系统的处理能力就越强,在同一时刻能够处理的请求越多。(前提是server后端依赖的服务也是可以横向扩展来提高并发量的)
1.2 缓存
使用缓存来提高性能。 主要作用是提高单机处理能力。
比如,一台服务器的逻辑是返回视频的详情信息,正常处理逻辑是,1解析请求中的视频id,2通过视频id向redis或mysql中获取数据,3获取数据之后再返回给客户端。整个流程耗时最多的是第二步,因为涉及到网络的交互。
假设,整个请求耗时10ms,如果server是单进程单线程来处理请求,那么每秒钟可以处理100个请求。
那么如果把第二步的时间缩短呢?考虑到视频的信息变更不会很频繁,同时热门的视频可能比较集中(尤其是放在首页上方的焦点图中推荐的视频)。
可以将每次从redis或mysql访问到的视频的信息存放在本地的缓存中(获取是分布式缓存中),那么下次再来一个请求的时候就可以直接从本地缓存中获取(如果本地缓存没有,再请求redis或mysql获取数据),这样在单个视频请求并发量很大的情况下可以节省很多的时间)。
比如本地缓存超时时间是1秒,获取本地缓存的耗时是1ms,那么只有第一个请求耗时是10ms,剩下的请求都可以在1ms左右处理完,那么每秒可以处理(1000ms-10ms)/ 1ms + 1 = 991个请求。 单机的qps是不是在请求比较热门集中的情况下会提高很多嘛。
1.3 异步处理
当整个系统的处理能力有限,比如一个秒杀系统设计时每秒的并发量只能支持10000个。虽然系统可以支持横向扩展,通过扩容来提高并发量。但是如果秒杀前的一秒钟是无法预测到到底会有多大的并发请求量过来(只能根据历年的请求量的增加比例等因素来预估请求量)。
所以,可以将所有的请求消息都先放入到消息队列中(比如kafka),然后让整个系统按照自己可以处理的并发量来从消息队列中依次处理。 当然消息队列的并发量要满足,由于消息队列不会处理复杂的逻辑,所以通过部署多个节点是可以达到很高的并发量。但是后台系统就不是很容易,因为系统很可能涉及到mysql的读写,事务等操作,并发量有时候提高会比较麻烦,如果一味的提高后台系统的并发量最终可能会导致整个系统极其复杂。