秒杀项目的思考

我再刷面经的时候看到好多对于秒杀系统的问题,自己就捣鼓了一个。

思路图

我们就从最差的情况一步一步解决。

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中的数据都是热点数据?这个还请观众老爷们给点建议。

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
慕课网Java高并发秒杀(课程) 很好的spring,springMVC,mybatis,bootstrap,jQuery,mysql,Restful学习案例 SQL脚本 CREATE DATABASE seckill; USE seckill; -- todo:mysql Ver 5.7.12for Linux(x86_64)中一个表只能有一个TIMESTAMP CREATE TABLE seckill( `seckill_id` BIGINT NOT NUll AUTO_INCREMENT COMMENT '商品库存ID', `name` VARCHAR(120) NOT NULL COMMENT '商品名称', `number` int NOT NULL COMMENT '库存数量', `start_time` TIMESTAMP NOT NULL COMMENT '秒杀开始时间', `end_time` DATETIME NOT NULL COMMENT '秒杀结束时间', `create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (seckill_id), key idx_start_time(start_time), key idx_end_time(end_time), key idx_create_time(create_time) )ENGINE=INNODB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 COMMENT='秒杀库存表'; -- 初始化数据 INSERT into seckill(name,number,start_time,end_time) VALUES ('3000元秒杀iphone6',100,'2016-01-01 00:00:00','2016-12-31 00:00:00'), ('2000元秒杀ipad',100,'2016-01-01 00:00:00','2016-05-01 00:00:00'), ('6000元秒杀mac book pro',100,'2016-07-01 00:00:00','2016-12-31 00:00:00'), ('7000元秒杀iMac',100,'2016-05-01 00:00:00','2016-12-31 00:00:00') -- 秒杀成功明细表 -- 用户登录认证相关信息(简化为手机号) CREATE TABLE success_killed( `seckill_id` BIGINT NOT NULL COMMENT '秒杀商品ID', `user_phone` BIGINT NOT NULL COMMENT '用户手机号', `state` TINYINT NOT NULL DEFAULT -1 COMMENT '状态标识:-1:无效 0:成功 1:已付款 2:已发货', `create_time` TIMESTAMP NOT NULL COMMENT '创建时间', PRIMARY KEY(seckill_id,user_phone),/*联合主键*/ KEY idx_create_time(create_time) )ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='秒杀成功明细表' SHOW CREATE TABLE seckill\G;#显示表的创建信息 Mybatis两个问题?①sql写在哪里?②怎么实现DAO接口?第一个问题:注解或者XML选择XML.第二个问题:Mapper自动实现DAO接口或者API编程方式实现DAO接口.选择Mapper.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值