【项目】SpringCloud+Nginx+Redis+RabbitMQ秒杀系统

文章目录

  • 秒杀系统
    • 前言
    • 系统架构图
    • 难题
      • 限流(一般都在接入层)
        • 三大接口限流算法
          • 计算器
          • 漏桶
          • 令牌桶
        • 其他限流策略
      • 分布式缓存
      • 可扩展
      • 超卖少卖(分布式锁)
      • 削峰
    • 遇到的问题
      • 前后端交互问题
        • 1.跨域问题
        • 2.前后端数据交换精度缺失问题
      • JSON转换问题
        • 1.Redis中实体类和JSON互转问题
      • 消息中间件问题
        • 1.添加消息中间件的话,如何将秒杀系统处理的消息返回给用户?
      • 数据库问题
        • 1. 不能使用关键字做表名!

秒杀系统

前言

我的电脑配置:i5 、16G (8G电脑扛不住,但你可以多个一起搭建)
github项目地址
码云项目地址

当时写这个项目也只是一时兴起,后面看着性能不断的提高,测的QPS和延迟都不断的变优,发现还挺有意思的,感觉找到了乐趣所在。不过还是得更深入底层了解点优化的策略吧。就比如说连接池,相信很多人连接池的配置都是网上搬的模板吧,没有去详细的了解该如何就我们自己的服务器去配置。这里我就不多去说了,网上一大堆。大类是两方面:

  1. IO密集型任务:本机服务器CPU核数*2

  2. CPU密集型任务:本机服务器CPU核数+1

  3. 混合型密集任务(其实就是上两种混合)

    …(其他)

系统架构图

【项目】SpringCloud+Nginx+Redis+RabbitMQ秒杀系统_第1张图片

难题

限流(一般都在接入层)

概述

​ 只有少部分的用户能秒杀成功,所以要限制大部分的用户流量,只允许少部分的进入服务后端

三大接口限流算法

计算器

概述

​ 在一段时间间隔内,处理请求的最大数量固定,超过部分不处理。

确定方法的最大并发量MAX,每次进入方法前计数器+1,将结果和最大并发量MAX比较,如果大于等于MAX,则直接返回;如果小于MAX,则继续执行;退出方法后计数器-1。
比如限制服务的并发访问数是100,而服务处理的平均耗时是10毫秒,那么1分钟内,该服务平均能提供( 1000 / 10 ) * 60 * 100 = 6000 次

漏桶

概述

​ 漏桶大小固定,处理速度固定,但请求进入的速度不固定(在突发情况请求过多时,会丢弃过多的请求)

令牌桶

概述

​ 令牌桶的大小固定,令牌的产生速度固定,但是消耗令牌(请求)的速度不固定(可以应对某些事件请求过多的情况)。每个请求都会从令牌桶中取出令牌,如果没有令牌,则丢弃这次请求。

其他限流策略

  • 用户维度的限流:某一段时间只允许用户提交一次请求

  • 商品维度的限流:对于同一个抢购商品,某个时间段内只允许一定数量的请求接入

分布式缓存

概述

​ 由于数据库读写属于磁盘IO,性能很低,如果能够把部分数据或业务逻辑转移到分布式缓存,效率就会有极大的提高

可扩展

概述

​ 秒杀系统的服务节点一定是可以弹性扩展的。比如淘宝双十一,就会增加大量的机器应对交易高峰。

超卖少卖(分布式锁)

概述

​ 比如10万次请求同时秒杀,正常需要进行10万次库存扣减,但是由于某种原因,往往会造成多减库存或者少减库存,就会出现超卖或少卖的问题。

解决办法

  • 分布式锁:Zookeeper(性能不高)、Redis

分布式锁应具备的条件:

  1. 一个方法在同一时间只能被一个机器的线程执行
  2. 高可用的获取锁和释放锁
  3. 高性能的获取锁和释放锁
  4. 具备可重入特性
  5. 具备锁失效特性,防止死锁
  6. 具备非阻塞特性,即没有获取到锁将直接返回获取锁失败

削峰

概述

​ 秒杀系统是一个高并发系统,采用异步处理模式可以极大的提高系统并发量,实际上**削峰的典型实现方式就是通过消息队列实现异步处理。限流完成之后,对于后端系统而言,秒杀系统仍然会瞬时涌入大量请求,所以在抢购一开始会有很高的瞬时峰值。高峰值流量是压垮后台服务和数据库的很重要的原因,秒杀后端需要将瞬间的高流量变成一段时间平稳的流量,常用的方法是利用消息中间件进行异步处理**

遇到的问题

前后端交互问题

1.跨域问题

【项目】SpringCloud+Nginx+Redis+RabbitMQ秒杀系统_第2张图片

解决方法:

1. 在相应的controller层上添加@CrossOrigin(origin = “*”)注解即可

2. 在zuul的配置文件中加上

zuul:
  sensitive-headers: Access-Control-Allow-Origin
  ignored-headers: Access-Control-Allow-Origin,H-APP-Id,Token,APPToken

2.前后端数据交换精度缺失问题

前端Long(17)的与后端的Long(20位)不同

【项目】SpringCloud+Nginx+Redis+RabbitMQ秒杀系统_第3张图片

JSON转换问题

1.Redis中实体类和JSON互转问题

JSON转实体

Object o = redisUtil.getCacheByKey(seckillDto.getGoodId().toString());
GoodDto goodDto = JSONObject.toJavaObject(JSONObject.parseObject(String.valueOf(o)), GoodDto.class);

实体转JSON

jedis.set(key, JSONObject.toJSONString(value));

消息中间件问题

1.添加消息中间件的话,如何将秒杀系统处理的消息返回给用户?

解决方法:前端不断长轮询(不断的发送请求?)当前服务。

WebSocket呢?

【项目】SpringCloud+Nginx+Redis+RabbitMQ秒杀系统_第4张图片

数据库问题

1. 不能使用关键字做表名!

order是mysql的关键字,不能做表名,不然对表进行操作会报错!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xNj0xKpY-1617801287108)(C:\Users\赵陌陌丶\AppData\Roaming\Typora\typora-user-images\image-20210324215415612.png)]

你可能感兴趣的:(项目,微服务,分布式,java)