- 巨大的突发流量
- 巨大的后端无效流量
网关层对除了userId做限流外,还要从商品skuid维度限流
在实际访问量超过预估访问量是,整体限流可以起到保护作用,避免系统被压垮
一旦秒杀开始,实际秒杀成功的用户只是库存的数量,在库存没有之后,将前端的秒杀入口关闭。
诀窍
- 有效流量过滤,过滤出有效请求
- 有效流量削峰,有效请求,达到或者超出下一层的能力瓶颈,同步处理,变成(降级为)异步处理
- 有效流量限流,1000qps,接入层,服务层,数据库
- 第一阶段为有效流量的锁定,将有效的流量识别出来,过滤掉无效的流量
- 第二阶段为有效流量落地,将有效流量,落地到服务层
秒杀系统是一个高并发系统,采用异步处理模式可以极大的提高系统并发量,其实异步处理就是削峰的一种实现方式。
场景, 10w人抢10000个商品
两段式操作,参考一下:
- 第一阶段为有效流量锁定,将有效的流量识别出来,过滤掉无效的流量
- 第二阶段为有效流量落地,将有效流量,落地到服务层
有效流量也很大,比如100w人抢10w商品,如何提升下单阶段的性能呢?
消息队列削峰,其集群吞吐量可以达到100wqps。
超出了用户的忍耐度,或者超出系统的承受能力。
可以使用redis分布式限流或者sentinel进行限流。
参加秒杀活动的商品是提前预知的,可以将参加秒杀的商品信息实现缓存到redis等缓存系统中,这样可以大大的提升系统的吞吐量,减少关系型数据库的读写压力。
为了极致的提高速度,最好是推送到ng的本地缓存
这中间的数据一致性,消息队列的作用,非常大
为了解决以上可能出现的问题,让缓存层更稳定,健壮,我们可以引入三级缓存架构。
- 一级缓存为本地缓存,或者进程内的缓存(如同时指出Ehcache2.X, Ehcache3.x,Guava,Caffeine)速度快,进程内可用
- 二级缓存为集中式缓存,如redis,可同时为多节点提供服务
- 三级缓存为接入层Nginx本地缓存,速度快,进程内可用
尽量命中Ng缓存,最坏也要命中redis分布式缓存
秒杀只是系统中的一部分
在秒杀系统中,这里需要区分为突发流量型和平缓流量型的功能,从业务上把秒杀和日常的售卖区分开来,对突发流量的功能做好隔离。
把秒杀作为营销活动,要参与秒杀的商品需要提前报名参加活动,这样我们就能提前知道哪些商家哪些商品要参与秒杀,对应于秒杀系统的核心功能,比如,商品详情,下单等。
- 客户端: 客户端层是浏览器或者手机应用app
- 接入层:系统入口,负载均衡,反向代理
- 服务层:实现核心应用逻辑,返回html或者json
- 缓存层:缓存加速访问存储
- 数据库层:结构化db和异构db
- 中间件:zk,xxl-job,rocketmq
漏斗型业务,指的是,用户的请求从客户端到db层,层层递减,递减的程度按照业务而定。
比如,10w人抢购100个商品,db层的请求在在为数量级1000内,这是比较理性的模型。
对于读请求,争取到接入层解决,比如商品静态处理,或者放到ng缓存中,流量走cdn。
亿级用户,10wqps,走到ng,那么就是 lvs + 10-20个ng,就可以搞定
接入层搞定,ng + 本地缓存/分布式缓存
前端: 做静态页面的缓存,禁止重复提交
秒杀开始后,可以对用户点击后响应前按钮置灰。
为啥要禁止重复提交呢?
如果用户秒杀失败了,频繁重试,会增加后端的压力,可能造成雪崩。
安全问题:
DDos攻击是通过大量合法的请求占用大量用户网络资源,以达到瘫痪网络的目的,一旦你的网站被人ddos攻击,网站就会无法访问,严重时服务器都能卡死。
使用场景: 秒杀商品动态数据的,读高并发
- 秒杀系统的商品是提前预知的,可以将参加秒杀的商品信息提前缓存到redis等缓存系统中,还可以先缓存到nginx的本地缓存(三级缓存),这样可以大大的提高系统的吞吐量
- 如果三级缓存没有,再从二级缓存中读取,会写到三级缓存
要点:
- 读请求尽量命中nginx的本地缓存
- Nginx还需要对商品详情接口做限流保护(根据商品限流),比如限制在1w qps,超过后降级,返回兜底的提示信息,前端可以做出重试,或者提示稍后重试
当用户流量远远大于ng瓶颈时,可以随机丢弃请求。
在网关层对下单等接口按照userid进行限流, (接口防刷)
假设限制同一个用户10分钟只能下一次单,一般情况下10分钟内,商品早就被抢光了,用户也就没有再次下单的机会了
可以结合风控系统,在网关层吧羊毛党等有问题的用户请求直接拒掉 (拦截恶意用户请求)
网关层除了对userId做限流之外,还有从商品skuid维度限流。
在实际访问量超过预估访问量时,整体限流可以起到保护作用,避免系统被压垮
一旦秒杀开始,实际秒杀成功的用户只是库存的数量,在库存没有之后,将前端的秒杀入口关闭。