zoukankan      html  css  js  c++  java
  • 秒杀抢购思路解析

    秒杀描述:

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

    常见秒杀方式:

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

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

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

    秒杀抢购的特征:

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

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

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

    秒杀过程中常见问题:

    前端问题:

    1、前端服务器带宽增加

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

    秒杀前端优化方案:

    1、把静态资源(cssjsimgmp4)存放到第三方静态服务器上面,例如:七牛云、腾讯云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/

  • 相关阅读:
    maven_Error building POM (may not be this project's POM)错误
    jmeter经验---java 追加写入代码一例
    java I/O Stream 代码学习总结
    java 布尔值一种赋值方法
    Spring cloud config 使用gitHub或者gitee连接
    linux/mac下一键删除下载失败的maven jar包
    MYSQL主从复制制作配置方案
    centos7 下解决mysql-server找不到安装包问题
    基于存储过程的百万级测试数据自动生成
    mysql慢查询,死锁解决方案
  • 原文地址:https://www.cnblogs.com/ming-blogs/p/11297539.html
Copyright © 2011-2022 走看看