项目|【项目】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秒杀系统
文章图片

难题 限流(一般都在接入层)
概述
? 只有少部分的用户能秒杀成功,所以要限制大部分的用户流量,只允许少部分的进入服务后端
三大接口限流算法 计算器
概述
? 在一段时间间隔内,处理请求的最大数量固定,超过部分不处理。
确定方法的最大并发量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秒杀系统
文章图片

解决方法:
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秒杀系统
文章图片

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秒杀系统
文章图片

数据库问题
1. 不能使用关键字做表名! order是mysql的关键字,不能做表名,不然对表进行操作会报错!
【项目|【项目】SpringCloud+Nginx+Redis+RabbitMQ秒杀系统】项目|【项目】SpringCloud+Nginx+Redis+RabbitMQ秒杀系统
文章图片

    推荐阅读