一、秒杀业务为什么难做

1)im系统,例如QQ或者微博,每个人都读取自己的数据(好友列表、群列表、个人信息);

2)微博系统,每个人读关注人的数据,一个人读多个人的数据

3)秒杀系统,库存只有一份,所有人会在集中的时间读和写这些数据,多个人读一个数据。

例如:小米手机每周二的秒杀,可能手机只有1万部,但瞬间进入的流量可能是几百几千万。

又例如:12306抢票,票是有限的,库存一份,瞬间流量非常多,都读相同的库存。

读写冲突,锁非常严重,这是秒杀业务难的地方。

二、优化方向

优化的方向有两个:

(1)将请求尽量拦截在系统上游(不要让锁冲突到数据库上去)

传统秒杀系统之所以挂,请求都压到了后端数据库,数据读写锁冲突严重,并发高相应慢,几乎所有请求都超时,

流量虽大,下单成功的有效流量甚小。以12306为例,一趟火车其实只有2000张票。200W个人来买,

基本没有人能买成功,请求有效率为0.

(2)充分利用缓存

秒杀买票,这是一个典型的读多写少的应用场景,读:(大部分请求时车次查询,票查询),写(下单和支付才是写请求。)一趟火车只有2000张票,200W个人来买,最多只有2000个人下单成功,其他人都是查询库存,写比例0.1%,读比例占99.9%.这种场景就非常合适使用缓存来优化

三、常见秒杀架构

常见的站点架构基本是这样的

(1)浏览器端,最上层,会执行到一些JS代码

(2)站点层,这一层会访问后端数据,拼html页面返回给浏览器;web-Server层,典型的是tomcat或者apache;

(3)服务层,向上游屏蔽底层数据细节,提供数据访问。Service层,典型的是dubbo或者thrift等提供RPC(远程过程调用)调用的后端服务。

(4)数据层,最终的库存在这里,mysql是一个典型(当然还有缓存);包含db(数据库)和cache(高速缓冲存储器-存储在CPU和主板),典型的是主从复制读写分离的db架构。

这个图虽然简单,但能形象的说明大流量高并发的秒杀业务架构,大家要记得这一张图。后面细细解析各个层级怎么优化

四、各层次优化细节。

第一层,客户端怎么优化(浏览器,APP层)

(a)产品层面:用户点击“查询”或者“购票”后,按钮置灰,禁止用户重复提交请求;

(b)JS层面:限制用户在X秒之内只能提交一次请求

第二层,站点层的请求拦截

在站点层,对uid进行请求计数和去重。直接存入到站点层内存存储中(redis)。一个uid,5秒只准透过1个请求。页面缓存同一个uid限制访问频度,做页面缓存,x秒内到达站点层的请求,均返回同一页面。如此限流,既能保证用户有良好的用户体验(没有返回404)又能保证系统的健壮性(利用页面缓存,把请求拦截在站点层。)

第三层 服务器层拦截(反正就是不要让请求落到数据库上去)

请求队列:

读请求---》缓存 cache抗,不管是memcahed还是redis,单秒抗10W应该是没有什么问题的。

写请求---》
请求队列:例如:买票: 分时分段售票,数据颗粒优化(有票,无票),下单业务与支付业务分离;

 

一切脱离业务的架构设计都是耍流氓,架构的优化也要针对业务

第四层:最好是数据库层

(1)浏览器层拦截80%----》JS
(2)站点层拦截了99.9%---》UID
(3)服务层-----》请求队列与数据缓存

(4)数据库--》正常读写。

 

总结:

(1)尽量将请求拦截在系统上游(越上游越好)

(2)读多写少的常用读多使用缓存(缓存读)