1.如果让你设计一个秒杀系统,你会怎么设计?

答:

(1)秒杀活动通常时间很短,并发很高,如果跟原网站部署在一起,可能让原网站瞬间瘫痪。所以我会单独部署秒杀程序,分配独立的域名。

(2)在秒杀之前,为了不错过秒杀活动,用户会频繁的刷新画面,这对后台系统来说造成很大的负担压力。所以在使用数据库集群、redis集群、以及负载均衡之外,秒杀页面要实现静态化。避免后台系统渲染动态页面消耗过多的资源。

(3)秒杀的时候要在短时间增加网络带宽,一方面可以在云端租用临时的带宽资源。另一方面可以把秒杀页面放在CDN节点上。这样就可以节省秒杀服务器的带宽了。

(4)为了避免秒杀之前用户提前获取下单页面的URL路径,所以我们需要对下单页面实现动态化,例如在秒杀开始之后,服务端生成特殊规格的随机数,然后把这些随机数保存在redis上面。那么秒杀的时候,URL地址就要带上这些随机数,才能进入到下单的页面。这样就可以避免秒杀之前出现提前下单的问题了。如果秒杀没有开始,任何人不得进入到下单页面。

(5)秒杀倒计时也需要特殊的设计。秒杀开始之前,CDN节点上的JS文件,他的功能是先获取北京时间,然后再HTML页面上生成倒计时的时钟,直到秒杀开始的时候,刷新页面重现加载到JS文件,也就是在秒杀开始的那一刻,后台程序在CDN节点上面跟新了JS文件的内容,秒杀开始的时候,用户浏览器会自动刷新,就能加载到最新的js文件,于是js文件生成秒杀按钮,用户点击按钮之后,js就会向后台程序发出秒杀请求。

这么说吧,在秒杀之前,任何顾客都不能发起秒杀请求。

(6)扣减库存的方式,也需要合理的设计。目前有两种扣减库存的方案:第一种方案是:在支付之后才扣减库存,但是会出现问题。比如华为手机有100补库存,但是在秒杀的时候,有2000人成功的下单。然后100人成功的支付,剩下的1900人,这些1900人在付款的时候会提示没有库存,明明是是用户下单成功了,支付的时候提示没有库存,导致客户体验度非常不好。所以这种方案不可取。另外一种的库存扣减方案是下单就扣减库存。这种情况意味着用户下单成功,支付的时候一定会有货。不会出现提示没有库存的现象。所以我采用的是这种方案。再有就是,用户下单之后在10分钟内没有付款,系统就是自动释放订单占有的库存。

(7)有关超售现象的设计。在数据库层面可以使用乐观锁来解决。在redis中可以使用事务来解决。

(8)集群方面的设计。秒杀的时候,虽然用都了数据库集群、redis集群和负载均衡,以及CDN加速等技术,但是面对海量的请求,我们还是要做好限流,比如:比如在后台系统中引入消息队列。拦截大量的请求。

以上模块就是我对秒杀模块的设计了。

2.商品秒杀活动很容易出现超售现象,你会怎么解决?

1.秒杀活动开始之前,我们先用程序(可以看我上一个文章写的秒杀程序)创建在redis中的库存记录。接下来的秒杀程序,首先先watch一下,redis 里面的库存和成功抢到商品的用户列表记录,然后开启redis事务扣减库存和记录下成功抢购商品的用户ID,最后提交redis的事务。如果事务提交的批处理指令送达给redis没有被其他秒杀程序插队执行。于是redis单线程就会执行当前事务提交的批处理指令,扣减库存就不会出现超售的现象。