秒杀系统学习记录
整体学习架构图
MD5二次加密
定义返回状态码
设置cookie
在浏览器中可以查看到登录的cookie
分布式session
单台tomcat的QPS只能达到几百。
nginx默认的负载均衡策略:轮询。
这样会出现什么问题?
当user进行登录时,将请求发送到第一台tomcat,然后第一台机器上拥有了user的登录信息,但是当用户的其他请求发送到第二台tomcat时,因为没有user的信息,因此需要重新登录。
有什么解决方案?
1、 session复制
具体方法就是将session复制发送到其他的tomcat容器中。
优点
只需要修改tomcat的配置,而不需要修改原来的代码。
缺点
- 发送session占用了带宽;
- 集群同步置数下降;
- session占用内存,无法水平拓展。
2、前端存储
不占用服务器内存
缺点
不安全
如何通过redis实现分布式session
方式一:使用spring session
1、pom.xml中导入包
2、application.yml中配置redis
重启项目,用户登录时redis就会保存session
原本登录的用户信息存储在session中,现在系统加入redis数据库,转移到redis中。
方式二:自己写方法存储到redis中
1、自定义RedisTemplate的序列化方式
2、添加将用户信息存入redis数据库中的语句
3、添加一个从redis中获取用户信息的方法
总结
以上两种方式都可以实现分布式session,其原理:将原本存在session中的用户信息存储到统一的redis服务器中。
秒杀商品为什么不在原有的商品添加字段,而是使用秒杀商品表?
每一种活动需要在商品表添加字段,一件商品可能正在秒杀同时也在以正常价格出售,数量不好控制。
因此,我们需要一张秒杀商品表,与商品主键关联。
综合分析,我么需要几张表
商品表、秒杀表、秒杀订单表、订单表
创建商品表(t_goods)
创建订单表(t_order)
创建秒杀商品表(t_seckill_goods)
创建秒杀订单表(t_seckill_order)
添加秒杀商品数据
商品页面表需要有哪些属性?
定义GoodsVo实体类(这个类就是商品页面需要展示给用户看的属性)
1、继承Goods实体类;
2、添加秒杀商品类的属性。
sql查询语句,联表查询GoodsVo信息
前端商品展示未出现图片?
springboot默认配置静态资源位于resource下的static文件夹下,但是因为本项目中配置了webMvcConfig所以必须要手动配置静态资源所处在的位置。
商品页面如下:
秒杀商品详情页面
如何判断秒杀的状态
1、获取当前的时间,使用before和after函数比较当前时间和秒杀开始和结束的时间,将秒杀的状态发送到前端页面去。
当秒杀未开始的时候,需要设置秒杀倒计时
页面显示的时间是静态的,需要手动刷新才能获取到剩余的时间
秒杀的按钮处理是怎么样的?
当秒杀前和秒杀后,按钮是disabled,只有处于秒杀时间才能够点击。
核心功能:秒杀功能
秒杀模块控制层(SeckillController)
1、判断用户是否登录,没有登陆返回登录界面,登陆成功将用户添加到属性中。
2、如果发现库存不足,返回秒杀失败信息,页面跳转。
3、判断是否重复抢购,去订单表中查询用户id和商品id是否已经存在。
秒杀模块service层(OrderServiceImpl)
1、通过id寻找到商品,将库存-1
2、生成订单和秒杀订单
如果没有出现库存不足和重复订单的情况,就为用户创建订单。
使用Jmeter进行压力测试
QPS:服务器每秒请求的数量
1、创建线程组
2、设置Http请求默认值
3、设置Http请求
单个用户压力测试和多个用户压力测试
秒杀功能的测试:
Qps明显低于其他的接口,因为秒杀接口需要对数据进行更新,更新的熟读是慢于查询的。
windows下的QPS是735,在Linux下只能达到170。
在压测下接口出现超卖的问题。
37、页面缓存
如何去对秒杀接口进行优化?
首先想到的方式就是添加缓存,考虑到影响QPS最重要的一个原因就是对数据库的操作,有就是秒杀接口的瓶颈所在。
以下是商品列表页面添加缓存的流程:
1、首先从redis数据库中获取页面,如果不为空,直接返回页面即可。
2、如果结果为空,需要使用thymeleaf的视图解析器手动渲染页面,接着将页面添加到redis数据库中去。
3、设置也免得生效时间为1min。
4、返回渲染成功的页面。
38、对象缓存
之前的分布式session其实就是对象缓存
通过使用缓存技术,QPS从1千多提升到了两千多。
39、商品详情页面静态化
为什么需要使用页面静态化?
页面缓存导致数据传输量非常的大,因此我们需要将页面进行拆分,静态的页面部分放在浏览器中缓存,数据部分通过后端进行传输。
如何实现页面静态化
前端修改为静态页面跳转,通过ajax获取后端发送来的数据。
后端的控制层原本返回的是Model对象,现在修改为ResponseBean的公共返回对象,将返回的json对象和状态信息包裹进去。
42、库存超卖问题
在服务层减库存时添加判断条件
数据库添加用户ID和商品ID的索引。
重复用户订单查询:将用户ID和商品ID放入redis数据库中。
出现问题:商品没有超卖,但是订单中出现超卖的情况
添加判断如果修改库存失败,返回空,不允许添加订单。
43、接口优化
因为没有解决秒杀所带来的的高并发问题,使用RbbitMQ
解决超卖问题的步骤是什么样的?
1、数据库添加唯一索引;
2、对sql语句添加库存数量的判断;
46、RabbitMQ控制台详解
主要就是一个权限管理
47、SpringBoot集成RabbitMQ
配置文件
监听器配置
47、SpringBoot集成RabbitMQ
第一步,配置rabbitMQ的配置文件
创建一个队列,命名为“queue”,并且设置它可以持久化。
第二步,创建一个消息的发送者,使用RabbitTemplate对象仿宋消息到一开始创建好的队列中。