秒杀专题

如何设计一个秒杀程序及避免超卖问题

2018-06-08  本文已影响3086人  时之令

很多的电商平台,在节假日如双十一,618等都会有商品描述的活动,今天和大家讨论一下,如何设计一个秒杀系统。

什么是秒杀
在一定的时间内几秒或者几分钟,对一定数量的库存进行出卖。

场景分析:

1,在秒杀之前,比如上午十点开始秒杀,很多用户可能在九点五十左右就开始访问自己心仪的秒杀商品,这样就会出现在秒杀之前用很多的并发量,所以在秒杀之前的半个小时之前,是否可以将参加秒杀活动商品的一些信息缓存起来,这样就可以减小因为高并发访问,给数据库带来的压力。

2,有的用户为了抢到商品可能利用第三插件,去频繁的访问接口,这样给接口会带来很大的压力,为了避免这种刻意的刷单问题,可以在后台对同一个用户的访问频率做限制,可以预测接口的实际访问频率,然后对不同的接口,同一个用户做频率限制,如某个抢购入口,可以设置一个用户一分钟不能访问超过60次,10秒内不能超过20次等不同时段不同访问频率策略,这个可以通过redis等缓存框架做到,列入以某个接口+用户唯一性标准为key,可以选择value为string类型,如果缓存更多数据,value可以选择hash类型,value的值是int类型,这样用户每次访问接口,可以先判断该值有没有达到预设的访问频率限制的值,如果达到了,就告诉用户,你的访问太过频繁,请多长时间后再试,或者要求用户输入验证码(图片验证码或者短信验证码)。如果没有达到预设值,就给int值技术加一,在第一次访问的时候,即查询的前exist判断,如果不存在,插入第一条数据,并且设置过气时间,这个时间就是访问频率的时间限制例如一分钟只能访问60次,那么这里的过期时间就是60秒,预设值就是60次。这样就可以从一定程度上避免刷单问题。

3,一个用户可能当初注册了很多的账号,平时不用,专门用来参加秒杀活动,这样其实也会造成系统压力。解决方式和上述差不多,只是对ip做限制,但是怎样做可能伤到真实的用户,因为有的场合如网吧,里面人购物其实是同一个ip出口,这个时候,其实也可以对用户的等级做限制,只有多高的等级才可以参加秒杀活动。

秒杀场景的特点

秒杀设计思路

前端页面静态化,禁止重复提交

后端可拓展,缓存,限流,削峰,异步处理

数据库层特点

数据库层是最脆弱的一层,一般在应用设计时在上游就需要把请求拦截掉,数据库层只承担“能力范围内”的访问请求。所以,上面通过在服务层引入队列和缓存,让最底层的数据库高枕无忧。

案例:利用redis+mysql实现简单的秒杀系统

Redis是一个分布式key-value缓存系统,value支持多种数据结构,这里value可以选择两种类型,String(或者hash):主要用于记录商品的库存,对商品减库存。Set集合(这里不要用list集合,list集合是可重复的,set是不可重复的,可以保证一个用户只卖一次,如果一个用户可以买多次那么可以使用list集合):用于存储用户的id获取其他唯一确定一个用户的值。

在秒杀开始的前:可以使用批处理,将参加秒杀的产品信息缓存到redis中。这里将产品的业务唯一字段作为key,库存作为value。这里的key要和前端缓存的key一致。
在秒杀开始时::用户大量提交。根据用户提交的产品信息,获取到redis中需要的key值,查询缓存(为了保证缓存有效,如果第一次没有查询到,可以到数据库查询,然后在缓存一下,不过一般不会出现),得到库存量,判断当前库存是否大于零,如果大于零,判断当前的set集合中是否用该用户ID,如果没有,减库存并且将用户的ID放入集合中,并对库存减一,如果库存为0,提示用户,商品已售完等文案信息,如果集合中已经存在该用户id,则不做任何处理,直接处理下一个请求。直到最后库存售完,上面的过程可以利用redis事务和watch功能完成对数据一致性的控制即超卖问题
库存售完后:程序开始启动一个有个后台线程,可以阻塞等待商品库存售完的通知,在上面一步,库存一旦售完,后台进程获取set集合中的用户信息,异步处理需要操作的购买等后续操作。

这只是一个简单的秒杀系统,实际的秒杀系统,还要考虑到很多的真实场景需要很多完善的地方,希望大家一起讨论如何设计一个秒杀系统。

上一篇 下一篇

猜你喜欢

热点阅读