背景
几十万甚至更多人抢几百件商品
问题
1、高并发
时间极短,瞬间用户量大
单机Redis最多3-4W,5W左右,QPS
缓存雪崩、击穿、穿透
2、超卖
使用Lua脚本解决,使用事务解决
分布式锁信号量机制
悲观锁、FIFO队列、乐观锁(版本号、Redis的watch)、
3、恶意请求
1)同一个账号,一次性发出多个请求
在程序入口处,一个账号只允许接受1个请求,其他请求过滤。不仅解决了同一个账号,发送N个请求的问题,还保证了后续的逻辑流程的安全。实现方案,可以通过Redis这种内存缓存服务,写入一个标志位(只允许1个请求写成功,结合watch的乐观锁的特性),成功写入的则可以继续参加。
2)多个账号,同一IP,一次性发送多个请求【检测频率,加验证码】
这种场景,可以通过检测指定机器IP请求频率就可以解决,如果发现某个IP请求频率很高,可以给它弹出一个验证码或者直接禁止它的请求
3)多个账号,不同IP发送不同请求
通常只能通过设置业务门槛高来限制这种请求了,或者通过账号行为的”数据挖掘“来提前清理掉它们。
网关,nignx,验证码
4、链接暴露
5、数据库问题
每秒上万甚至几十万的QPS直接打到数据库,数据库基本会崩溃。
6、重复订单
前端用户点提交订单后禁用按钮。
使用Redis的set结构
设置联合主键(用户id + 商品id)。
解决
1、按钮控制
按钮置灰
2、秒杀链接加盐
光做时间校验还是不行,别人可以通过程序获取最新的北京时间,在00毫秒的时候请求,程序比人工快多了。
把URL动态化,通过MD5之类的加密算法加密,然后通过前端代码获取url后台校验才能通过。
3、资源静态化
静态资源存储在Nginx或CDN服务器上,保证只有秒杀和商品详情页的动态请求才打到后端的服务器集群
4、Nginx
Nginx性能高
使用Nginx负载均衡
拦截恶意请求
5、限流
前端限流
控制点击频率
后端限流
一旦产品卖光了,return了一个false,前端直接秒杀结束,后端也关闭。
限制次数,限制总量(峰值处理10W,就在网关层限制)
限流组件
阿里的Sentinel,Hystrix等
5、限流&降级&熔断&隔离
6、服务单一职责
给秒杀开一个单独的服务,建立一个单独的数据库
7、Lua脚本
Redisson(分布式锁)所有锁都保证原子性(使用脚本),信号量
类似Redis事务,有一定的原子性,不会被其他命令插队,可以完成一些Redis事务性的操作。这点是关键。
8、Redis集群
秒杀读多写少,Redis集群,主从架构加哨兵模式,并开启持久化。
9、库存预热
库存提前加到Redis中去
限流->降级->熔断->隔离
10、削峰填谷
使用MQ,把请求放消息队列慢慢消费,当很多商品进行秒杀时才有必要(比如1W件商品,每个秒杀1000件),几个商品没必要
购物车机制,验证码
简单的流程图
秒杀商品定时上架
秒杀流程一:加入购物车
秒杀流程二:快速创建秒杀单子