秒杀项目的思考
我再刷面经的时候看到好多对于秒杀系统的问题,自己就捣鼓了一个。
思路图
我们就从最差的情况一步一步解决。
1.数据库直接被穿?
当我们秒杀系统的数据库被打穿以后,我们一定不要影响到其他系统。将秒杀系统数据库独立出来。
不然你的业务不仅不行,还把其他人搞砸了,你要被祭天了。
2.我们怎么防止我们数据库被打穿?
数据库扛不住,就用它兄弟redis来抗,一个扛不住,咱们就加集群,加主从,加哨兵无脑高可用。
3.那怎么让我们系统处理的并发量少点呢(限流)?
我们可以把请求全部放到mq中,这样达到了削峰的目的,减轻了下游的并发量。
4.消费者是用来做业务逻辑的,我们尽量不要打崩到这一层
我们把发送者和消费者分成两个系统,最多把发送者打崩,不能影响到mq和消费者。
5.但是我们也不能这么轻易的让他把发送方打坏?
我们可以通过nginx+集群来提高并发量。
6.我们可不可以在前端就限制一部分?
我们可以把那个按钮他连着按几次就给他整灰了,让他那么频繁的请求。
7.我们可不可以在nginx中先限制一部分呢?
我们可以在nginx把那些机器人或者代理服务器给他屏蔽掉。
好了屁话说完了,开始正经说。
首先我们在nginx中通过限制user-agent来限制一些看起来就不是正常人的用户浏览器,然后看看日志找出恶意ip。
然后进入前端,这时候我们在秒杀前保持按钮是灰色的,等到时间到了以后才能打开。并且可以当收到库存不足的响应以后直接把按钮去掉,提示用户已经卖完了。
然后请求就可发送方这里了,我们接收到请求,把请求进行解析好,存到mq中去,这块可能会有一个丢数据的可能,应该可以通过分布式事务解决(还没来的及看),这样我们的请求就到了mq中。
到了mq中,我们的mq是有挂掉的可能的,那我们持久化????
当然不能这样做,mq是内存中的,如果我们持久化的跟直接写磁盘有什么区别呢?我们要配置主从同步,并且哨兵机制那种思想也可以用在这里。
可能有小伙伴就问了,问什么你redis中 就 用持久化呢?
因为redis的数据是主要用来读取的,不是频繁写入和删除的。
言归正传,下面消费者开始读取mq中数据,因为mq中确保了消费(返回给他ack标志)所以不会发生丢数据的情况。
然后消费者拿到了请求,首先先去redis中看看库存量是不是还有,如果有的话,那么减一然后进入下游。
那么这里就可能会发生超卖的问题,我的思路是通过分布式锁来保证不会发生超卖(欢迎大佬提新的思路)。
那如果我要的商品没有在redis中里边呢?那么就直接打通db,开启事务去减减,这样如果你的商品是热点数据没有在里边这样是有问题的(打崩数据库的风险),其实我们可以把读redis的锁直作为操作数据库的锁。
下边就是生成订单开启支付这一系列的功能了。
细心的朋友可能发现我少说了一个问题,那就是我怎么保证我redis中的数据都是热点数据?这个还请观众老爷们给点建议。