秒杀系统设计
- 一键秒杀引导
一键秒杀引导设置后无需在结算页面填写/修改收获地址、优惠、发票等元素,减少结算新再次计算和调用操作
- 验证码输入
该验证码为图形验证码,是用户在点击“一键秒杀”后进行的一次交互操作。因为无业务牵涉,该验证码秒杀系统自己生成,
- 下单页面防恶意请求
为了防止获取秒杀下单地址进行恶意请求,将秒杀商品的下单地址动态化,动态地址在商品秒杀开始时返回给页面
- 秒杀商品库存预冻结
为了避免同步调用库存中心带来的预估之外的故障,秒杀活动创建生效时会将该商品的库存冻结,库存中心增加一种冻结类型;秒杀成功会直接使用该库存生成订单,订单中心增加一种秒杀订单类型
- 库存释放
因为客户秒杀后可能不付款或者取消订单,关于秒杀不支付的订单是否释放有两种选择方案:
一:订单中心将秒杀成功不支付或者取消的订单通知秒杀系统进行本系统和库存中心的库存释放,让客户可以再次抢购(秒杀系统调用库存中心释放库存)
二:秒杀程序在设置库存计数器时可以进行溢出设置,但还是有可能出现实际秒杀交易成功数小于秒杀下单成功数
- 数据交互全内存操作
为了提高执行效率,程序会提前将数据预加载到redis缓存中,比如库存计数器、用户违规操作(同IP 时间内访问频率过高、同用户时间内访问频率高、黑名单),redis表的键值设置会尽量遵从最短执行/扫描路径设计
- 内存操作的数据对象
库存计数器、服务器节点接受的请求计数器、用户参与秒杀记录(针对商品、活动、时间段)、预生成订单VO、秒杀商品信息(起始标记、下单动态URL)、访问控制数据。
除访问控制数据,其他内存数据对象在redis的有效期时间为秒杀活动时间。
- 数据的预加载到内存时机
库存计数器——秒杀活动创建,递减
服务器节点接受的请求计数器——递减
用户参与秒杀记录(针对商品)——秒杀成功
用户参与秒杀记录(针对活动)——秒杀成功
用户参与秒杀记录(时间段)——秒杀成功
预生成订单VO —— 秒杀活动创建后
用户-验证码——用户点击“一键秒杀”
秒杀商品(活动)信息——秒杀活动创建
访问控制数据——请求进入
- 系统隔离
第一期需要依赖的模块:
活动运行时依赖:支付中心、库存中心、订单中心(库存释放)
活动开始前依赖:商品中心、会员中心、商家后台
第一期需要依赖的交互页面:商品详情页面
- 秒杀库存计数器
通过redis的原子自增锁实现,关键字: DECR 、INCR
- 请求的四次拦截,除此之外前段js也需要做高频率点击限制
第一次拦截(请求错流):秒杀验证码输入,将流量错开,减小并发;
第二次拦截(恶意流量拦截):访问控制将恶意/违规流量拦截,过滤掉恶意请求(部分);
第三次拦截(服务节点拦截): 每个服务节点允许下单的流量等于商品的库存数,其他请求提示秒杀已抢完;
达到秒杀持久化层的流量等=服务器节点*库存数
第四次拦截:到达秒杀持久层的请求等于库存数+N(N为溢出值),其他请求提示秒杀已抢完;
- 秒杀页面独立
增加秒杀详情页,该页面只调用秒杀系统,减少营销接口的压力
- 秒杀成功后的订单持久化操作
因为4次请求拦截,真正到达持久层的请求=秒杀商品数量*秒杀商品库存数,所以目前的设计是整个秒杀流程从前端提交请求到持久化为一步操作,如果后续持久化的量非常高再考虑消息队列的引入
转载自:https://juejin.cn/post/7069416737669644318