文章目录
- 秒杀系统
-
- 前言
- 系统架构图
- 难题
-
- 限流(一般都在接入层)
-
- 三大接口限流算法
-
- 计算器
- 漏桶
- 令牌桶
- 其他限流策略
- 分布式缓存
- 可扩展
- 超卖少卖(分布式锁)
- 削峰
- 遇到的问题
-
- 前后端交互问题
-
- 1.跨域问题
- 2.前后端数据交换精度缺失问题
- JSON转换问题
-
- 1.Redis中实体类和JSON互转问题
- 消息中间件问题
-
- 1.添加消息中间件的话,如何将秒杀系统处理的消息返回给用户?
- 数据库问题
-
- 1. 不能使用关键字做表名!
秒杀系统 前言 我的电脑配置:i5 、16G (8G电脑扛不住,但你可以多个一起搭建)
github项目地址
码云项目地址
当时写这个项目也只是一时兴起,后面看着性能不断的提高,测的QPS和延迟都不断的变优,发现还挺有意思的,感觉找到了乐趣所在。不过还是得更深入底层了解点优化的策略吧。就比如说连接池,相信很多人连接池的配置都是网上搬的模板吧,没有去详细的了解该如何就我们自己的服务器去配置。这里我就不多去说了,网上一大堆。大类是两方面:
- IO密集型任务:本机服务器CPU核数*2
- CPU密集型任务:本机服务器CPU核数+1
- 混合型密集任务(其实就是上两种混合)
…(其他)
文章图片
难题 限流(一般都在接入层)
概述? 只有少部分的用户能秒杀成功,所以要限制大部分的用户流量,只允许少部分的进入服务后端
三大接口限流算法 计算器
概述? 在一段时间间隔内,处理请求的最大数量固定,超过部分不处理。
确定方法的最大并发量MAX,每次进入方法前计数器+1,将结果和最大并发量MAX比较,如果大于等于MAX,则直接返回;如果小于MAX,则继续执行;退出方法后计数器-1。漏桶
比如限制服务的并发访问数是100,而服务处理的平均耗时是10毫秒,那么1分钟内,该服务平均能提供( 1000 / 10 ) * 60 * 100 = 6000 次
概述? 漏桶大小固定,处理速度固定,但请求进入的速度不固定(在突发情况请求过多时,会丢弃过多的请求)
令牌桶
概述? 令牌桶的大小固定,令牌的产生速度固定,但是消耗令牌(请求)的速度不固定(可以应对某些事件请求过多的情况)。每个请求都会从令牌桶中取出令牌,如果没有令牌,则丢弃这次请求。
其他限流策略
- 用户维度的限流:某一段时间只允许用户提交一次请求
- 商品维度的限流:对于同一个抢购商品,某个时间段内只允许一定数量的请求接入
概述? 由于数据库读写属于磁盘IO,性能很低,如果能够把部分数据或业务逻辑转移到分布式缓存,效率就会有极大的提高
可扩展
概述? 秒杀系统的服务节点一定是可以弹性扩展的。比如淘宝双十一,就会增加大量的机器应对交易高峰。
超卖少卖(分布式锁)
概述? 比如10万次请求同时秒杀,正常需要进行10万次库存扣减,但是由于某种原因,往往会造成多减库存或者少减库存,就会出现超卖或少卖的问题。
解决办法
- 分布式锁:Zookeeper(性能不高)、Redis
- 一个方法在同一时间只能被一个机器的线程执行
- 高可用的获取锁和释放锁
- 高性能的获取锁和释放锁
- 具备可重入特性
- 具备锁失效特性,防止死锁
- 具备非阻塞特性,即没有获取到锁将直接返回获取锁失败
概述? 秒杀系统是一个高并发系统,采用异步处理模式可以极大的提高系统并发量,实际上**削峰的典型实现方式就是通过消息队列实现异步处理。限流完成之后,对于后端系统而言,秒杀系统仍然会瞬时涌入大量请求,所以在抢购一开始会有很高的瞬时峰值。高峰值流量是压垮后台服务和数据库的很重要的原因,秒杀后端需要将瞬间的高流量变成一段时间平稳的流量,常用的方法是利用消息中间件进行异步处理**
遇到的问题 前后端交互问题
1.跨域问题
文章图片
解决方法:2.前后端数据交换精度缺失问题 前端Long(17)的与后端的Long(20位)不同
1. 在相应的controller层上添加@CrossOrigin(origin = “*”)注解即可
2. 在zuul的配置文件中加上
zuul: sensitive-headers: Access-Control-Allow-Origin ignored-headers: Access-Control-Allow-Origin,H-APP-Id,Token,APPToken
文章图片
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呢?
文章图片
数据库问题
1. 不能使用关键字做表名! order是mysql的关键字,不能做表名,不然对表进行操作会报错!
【项目|【项目】SpringCloud+Nginx+Redis+RabbitMQ秒杀系统】
文章图片
推荐阅读
- #|「SpringCloud」09 Bus消息总线
- kubernetes|【Kubernetes的开放接口】
- 网络|谈谈对K8S CNI、CRI和CSI插件的理解
- mybatis|java计算机毕业设计-数字相册管理系统-源码+数据库+系统+lw文档+mybatis+运行部署
- spring|SSM基于微信小程序的外卖点餐系统 毕业设计-附源码2711704
- MySQL数据库|MySQL高级篇之索引结构
- java|springboot和springmvc的区别
- 瑞吉外卖|猿创征文|瑞吉外卖——移动端_笔记
- 瑞吉外卖|猿创征文|瑞吉外卖——移动端_订单明细