秒杀系统设计

秒杀系统背景
秒杀现在基本是电商的标配,京东、淘宝、小米电商等,为了增加gmv,促进用户活跃度,各大电商平台都会在搞一些秒杀促销活动。
秒杀活动一般会限制时间,在限制的时间内,对秒杀商品给出极具诱惑的价格,吸引买家消费,事前一般还会进行广告引流来增加影响力。
主要挑战
基于秒杀的业务特征,秒杀对于技术侧的挑战一般具有下面几个特征:
1·超大带宽:秒杀商品的价格诱惑往往带来巨大的访问量,从而带来超高的带宽需求
2·商品限量:秒杀商品一般都会限量,而秒杀的特点又容易引起商品超卖
3·访问量超高:会吸引特别多的用户参与
4·并发超高:秒杀开始后一段时间,是并发访问的高峰期,会比平时高出几个量级
挑战应对方案
商品限量
一般商品参与秒杀活动都有数量限制,不允许在活动中出现超卖现象,但是面对秒杀时候的超大并发量,又容易出现商品超卖的现象。
出现超卖的问题,一般是因为读取商品可售数量的时候,直接读取db存储中的数据。由于并发的存在,导致并发的请求读取到相同的可售数量,而且在扣减可售数量时没有有效拦截,进而导致商品超卖。
针对这种现象,如果请求量是在数据库可承受范围内,可以在扣减商品可售数量的时候,sql直接判断可售数量是否满足之前查到的销售数量,如果不满足,则sql执行失败,重新发起。
这种处理方式适用于并发数没达到巨量的程度,通过升级数据库配置能承受预期的请求。
但是秒杀期间,往往并发数是巨量的,请求直接访问数据库,大部分时候都是不可行的。
这个时候可以考虑引入redis缓存和队列。
提前将可售商品数量存入缓存当中,当秒杀请求到来的时候,先扣减缓存中的数量,能扣减成功再执行下单处理。由于redis是单线程操作,可以避免并发问题,也没有数据库主从延迟带来的数据脏读问题,可以避免避免数据超卖。
并发超高和访问超高
应对巨大的并发数和访问量,主要是依靠cdn和数据缓存,静态资源通过cdn缓存来缓解服务的压力。
动态数据请求,通过将商品数据、开始时间等存储到缓存中,减轻对数据库的压力。
用户的购买请求到来后,将请求转入到队列中。在后端开启多个进程消费队列数据,生成订单,将订单结果存入数据库和缓存。用户发起请求结果查询,可以直接从缓存中读取结果。
当有足够的用户购买请求放入到队列中后,后续的购买请求就直接返回已售完,不再转入队列。
限流
秒杀中商品的的销量是有限的,但是希望购买的用户数量会远超过商品可售数量。
这种情况下,为了保护后端的下单系统。可以在前端做一个流量漏斗。
秒杀页面本身用cdn做静态加速,所有用户均可以访问到该静态页面。当秒杀开始后,允许用户访问商品详情页,给进入到商品详情页的人数做一个计数器,当进入到页面的人数超过阈值的时候,可以给用户一个友好的提示,不再允许用户进入秒杀商品详情页。
在用户下单的接口处,也做一个计数器,当已经提交订单的用户数量超过一定的阈值,可以直接提示用户商品已经秒杀完毕,不再执行生成订单处理。
总结
总的来说,因为秒杀的高并发和大请求量的特征,首先要保证用户请求不要直接落到数据库,防止超高的用户请求直接打到数据库上导致数据库宕机,静态资源尽可能装入cdn,动态数据装入缓存集群,提高抗并发能力,也能提高用户请求的响应速度。其次,因为秒杀的商品都是有数量限制的,在进入商品页和下单操作前添加限流操作,可以避免服务器接收到过多无效的请求,也能提高用户体验。
秒杀系统架构举例


评论