秒杀抢购思路解析

秒杀描述:

网上竞拍的一种新方式。所谓“秒杀”,就是网络卖家发布一些超低价格的商品,所有买家在同一时间网上抢购的一种销售方式。由于商品价格低廉,往往一上架就被抢购一空,有时只用一秒钟。

常见秒杀方式:

1、限时,例如:小米手机 限时、限量抢购,还有淘宝、京东等电商平台等。

2、一元抢购  例如:例如:1元抢购手机、电器等。

3.限时、限量抢购  例如:12306 抢票 还有部分电商平台等。

秒杀抢购的特征:

1、短时间内并发量非常大,高并发问题

Java实现微服务秒杀抢购思路分析

  1. 秒杀抢购前端优化方案
  2. 秒杀抢购如何防止超卖问题
  3. 基于MQ和Redis实现秒杀抢购
  4. 秒杀抢购如何防止伪造

秒杀过程中常见问题:

前端问题:

1、前端服务器带宽增加

2、用户重复提交订单。将提交按钮置灰色,不可点击。

秒杀前端优化方案:

1、把静态资源(css\js\img\mp4)存放到第三方静态服务器上面,例如:七牛云、腾讯云ONS、阿里云等。

2、增加服务器的带宽,确保网站的加载速度。1兆带宽=128kb/s   

举栗子:假如现在网站是1兆带宽,加载一个页面需要640kb  加载网页的时间:640/128=5s。加载网页需要5秒的时间,这样导致用户体验肯定不好,所有如果想要1s 内加载处理这个页面 需要将带宽增加 到 5兆带宽。但是这样成本过高,而且治标不治本。可以使用动静分离、CDN加速等方式。

3、使用CDN加速,提高网站访问速度。CDN好处:遵循就近访问原则,减少客户端与服务器端的带宽传输。

4、使用动静分离,核心

后端问题:

1、商品库存超卖问题   解决方案:使用redis 分布式锁、乐观锁、MQ 实现 。

方案1:根据 商品Id、库存>0 修改库存数量,防止超卖问题。
update seckill set inventory=inventory-1, version=version+1 where productId=#{productId} and inventory>0

不使用 版本号,解决超卖问题,使用了 MySql 自带的行锁机制。属于悲观锁

方案2:乐观锁:使用 version 版本号。需要在执行 修改 库存之前,先查询一下该商品库存的版本号,然后在根据版本号 商品Id库存>0 为条件修改库存的数量,防止超卖问题。

select id ,productId ,productName , inventory , startTime , endTime , createTime , version from seckill where productId=#{productId};

update seckill set inventory=inventory-1, version=version+1 where productId=#{productId} and inventory>0 and version=#{version};

使用 version 版本号解决超卖问题,属于乐观锁。

方案1与方案2 比较:

1、推荐使用方案2解决超卖问题。

2、场景比较:

方案1:200个请求,100库存,100个请求都能够抢购成功。

方案2:200个请求,100个库存,可能只有68个请求抢购成功,还剩余32个商品库存。还可以进行第二次抢购。防止一次性被抢完,可以使用这种方案。

2、单台服务器扛不住大量请求  解决方案:使用集群部署

3、如何限制用户的操作频率,如何防止用户作弊行为,利用工具进行秒杀抢购。

方案:redis 是单线程的 线程安全的。基于Redis 的 setNx(key,value,timtout);解决,如果key 存在,则返回 false,如果key 不存在则返回 true。

秒杀服务为什么需要以微服务方式单独部署:

目的:与其他服务互不影响、可以使用 docker部署实现快速扩容。

当修改商品库存的请求过多时,数据库访问压力过大,如何解决:

1、使用分表分库

2、使用MQ异步实现修改库存数量

3、如果秒杀的请求过多,对数据库频繁的进行IO操作,可能会导致数据库崩溃的问题。

解决方案:使用令牌桶提前生成好对应库存的令牌,存放在令牌桶中谁能抢到token,就放入到 MQ 中 实现异步修改库存。

服务限流、服务保护、安全性问题。可以使用验证码进行验证。

秒杀抢购中修改库存数量如何减少数据库IO操作?

在高并发情况下,如果突然有10w个不同的用户请求进行秒杀,但是商品的库存数量只有100个,那么这个时候可能会出现10w个请求执行修改秒杀库存的sql语句,这时候可能会出现数据库访问压力承受不了,导致数据库爆掉。

解决方案:数据库分表分库、读写分离、使用redis 缓存减少数据库的访问压力

推荐秒杀方案:基于MQ+库存令牌桶实现。

同时有10w个请求实现秒杀,商品库存只有100个 实现只需要修改库存100次就可以了。

方案实现流程:提前对商品库存生成好令牌(100个令牌),在10w个请求中,只要谁抢到了令牌谁就能够秒杀成功。获取到秒杀令牌后,在使用MQ异步实现减库存的操作。

如果采用 MQ 实现秒杀抢购,秒杀接口不能立刻的拿到秒杀结果,因为MQ 是异步形式的。

1、前端调用秒杀接口如果秒杀成功的话,返回正在派对中......

2、前端写一个定时器使用 秒杀 token 查询秒杀是否成功,如果MQ 消费的速度非常快的话,1-2s 就可以拿到结果。

需要为商品库存生成对应库存数量的 token,key 为 商品Id,value 为 list集合。使用的是 redis 的lList集合方式。

如何防止库存超卖问题

1、使用数据库乐观锁(CAS无锁机制)

2、使用 Redis实现分布式锁,因为 Redis 天然的线程安全(原子性)。不建议使用 zookeeper ,因为zookeeper无法保证数据原子性问题。

3、使用MQ异步形式实现修改库存(用户等待时间过长)。推荐

 

 

该博客内容来自蚂蚁课堂:http://www.mayikt.com/

转载于:https://www.cnblogs.com/ming-blogs/p/11297539.html

你可能感兴趣的:(秒杀抢购思路解析)