当前位置:   article > 正文

秒杀系统优化方案

秒杀系统优化方案

秒杀接口的简单流程

  • 1.用户是否登陆,没有登陆返回失败
  • 2.用户是否有收货地址
  • 3.库存是否充足,没有库存返回失败
  • 4.用户是否重复秒杀,秒杀过了返回
  • 5.减库存,库存是否改变,没有改变返回失败
  • 6.下订单,写入秒杀订单
  • 7.秒杀成功进行支付

页面优化技术

  • 1.页面缓存+ URL缓存+对象缓存
  • 2.页面静态化,前后端分离
  • 3.静态资源优化
  • 4.CDN优化
页面缓存

如前端页面使用的是Thymeleaf这类模板引擎,可以直接在服务器渲染,然后把整个html页面当作string返回放入redis中进行缓存,把高并发的页面进行缓存(如秒杀商品列表,秒杀的商品信息),像这种页面的话缓存的时间不能设置太长,否则数据库修改后不能及时展示。

对象缓存

把需要用到的对象放到redis中进行缓存,如秒杀用户,秒杀的商品信息。

页面静态化

把静态页面放到静态资源里面,前端使用ajax来请求需要的数据。

多次访问页面的时候页面返回的状态会变为304,不在是200,并且会向服务端传入下图的参数,服务端收到这个参数后会检查这个接口的返回数据是否有发生改变,如果没有的话就会给客户端返回304,表示浏览器可以直接使用缓存的数据。
在这里插入图片描述

这个请求的方式还是会向服务端发生请求,如果不需要向服务器请求直接使用的话可以参考springboot的官方文档

  • spring.resources 的相关配置

https://docs.spring.io/spring-boot/docs/2.1.13.BUILD-SNAPSHOT/reference/htmlsingle/

#static
spring.resources.add-mappings=true
spring.resources.cache-period= 3600
spring.resources.chain.cache=true 
spring.resources.chain.enabled=true
spring.resources.chain.gzipped=true
spring.resources.chain.html-application-cache=true
spring.resources.static-locations=classpath:/static/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
超卖问题的解决思路
  • 1.数据库加唯一索引:防止用户重复购买(秒杀表里面把用户和商品ip作为唯一索引,在加上事物发生错误进行回滚)
  • 2.SQL加库存数量判断:防止库存变成负数(在where 条件里面判断下库存是否>0,数据库本身在更新的时候会有锁,只能一个线程修改)
  • 3.减少库存的时候update语句判断下返回值是否大于0,如果大于0说明修改数据库成功,才可以创建订单

秒杀接口优化

  • 1.Redis预减库存减少数据库访问
  • 2.内存标记减少Redis访问
  • 3.请求先入队缓冲,异步下单,增强用户体验
    对于高并发的访问解决数据库的瓶颈是最为重要的
思路:减少数据库访问
  • 1.系统初始化,把商品库存数量加载到Redis

  • 2.收到请求,Redis预减库存,库存不足,直接返回,否则进入3

  • 3.请求入队,立即返回排队中

  • 4.请求出队,生成订单,减少库存

  • 5.客户端轮询,是否秒杀成功

具体实现方式

在项目中引入消息队列如RabbitMq,kafka等,在秒杀过程中分为两部分,消息入队前的操作和消息入队后的操作,入队前需要使用到的数据都从redis中取,入队后消费才正常的对数据库进行减库存,生成订单等操作。

项目初始化

  • 把秒杀商品的库存放入redis中缓存,并把每件商品可以做一个标记是否秒杀完(可以使用Map进行标记)
  • 秒杀接口具体实现
  • 1.判断用户相关信息(是否登陆,是否填写收货地址等)
  • 2.判断商品是否秒杀完(Map),秒杀完返回失败信息
  • 3.预减库存可以使用redis的decr方法(原子操作),如果库存小于0标记一下该商品买完(Map标记),返回秒杀失败
  • 4.判断商品是否重复秒杀(从redis中取相关信息)
  • 5.把相关信息(用户信息以及商品id)发送到消息队列中,发送完就可以直接返回状态给给前端展示(排队中)

消费端消费信息

  • 6.根据传来商品id从数据库中查找库存
  • 7.大于0进行从数据库中进行减库存操作,小于0返回
  • 8.判断减库存是否成功,成功的话生成订单并把秒杀成功信息放入redis中,失败的话把该商品秒杀完的信息存入redis中

前端页面处理

  • 9.如果返回的是排队中的状态就轮询去查是否秒杀成功的接口
  • 10.从秒杀订单表查找相关信息如果有订单的话就返回秒杀成功,如果没有订单信息的话有两种情况(1.消费端还没有消费,继续轮询,2.已经没库存了,可以从redis中取)

还可以使用nginx进行负载均衡配置

安全优化

  • 1.秒杀接口地址隐藏
  • 2.数学公式验证码
  • 3.接口限流防刷
隐藏秒杀地址

思路:秒杀开始之前,先去请求接口获取秒杀地址

  • 1.点击秒杀按钮的时候先去后端生成一个随机的字符串,存入redis,然后返回给前端,前端在根据这个字符串拼接成一个秒杀接口的后端路径,进行验证。
  • 在点击秒杀按钮前可以用图形验证的方式来分散用户的请求,该方法对于减少并发量是十分有效的。

在这里插入图片描述

接口限流防刷

可以使用拦截器或者aop来实现减少对业务代码的侵入

使用注解的方式来设置时间,最大访问次数等

在需要控制的接口上面使用注解,获取接口路径的时候把用户、商品id、路径作为key,并设置初始次数。

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号