## 系统介绍
本系统是使用SpringBoot开发的高并发限时抢购秒杀系统,除了实现基本的登录、查看商品列表、秒杀、下单等功能,项目中还针对高并发情况实现了系统缓存、降级和限流。
## 开发工具
IntelliJ IDEA + Navicat + Sublime Text3 + Git + Chrome
## 压测工具
JMeter
## 开发技术
前端技术 :Bootstrap + jQuery + Thymeleaf
后端技术 :SpringBoot + MyBatis + MySQL
中间件技术 : Druid + Redis + RabbitMQ + Guava
## 秒杀优化方向
1. 将请求尽量拦截在系统上游:传统秒杀系统之所以挂,请求都压倒了后端数据层,数据读写锁冲突严重,几乎所有请求都超时,流量虽大,下单成功的有效流量甚小,我们可以通过限流、降级等措施来最大化减少对数据库的访问,从而保护系统。
2. 充分利用缓存:秒杀商品是一个典型的读多写少的应用场景,充分利用缓存将大大提高并发量
## 实现技术点
### 1. 两次MD5加密
将用户输入的密码和固定Salt通过MD5加密生成第一次加密后的密码,再讲该密码和随机生成的Salt通过MD5进行第二次加密,最后将第二次加密后的密码和第一次的固定Salt存数据库
好处:
1. 第一次作用:防止用户明文密码在网络进行传输
2. 第二次作用:防止数据库被盗,避免通过MD5反推出密码,双重保险
### 2. session共享
验证用户账号密码都正确情况下,通过UUID生成唯一id作为token,再将token作为key、用户信息作为value模拟session存储到redis,同时将token存储到cookie,保存登录状态
好处: 在分布式集群情况下,服务器间需要同步,定时同步各个服务器的session信息,会因为延迟到导致session不一致,使用redis把session数据集中存储起来,解决session不一致问题。
### 3. JSR303自定义参数验证
使用JSR303自定义校验器,实现对用户账号、密码的验证,使得验证逻辑从业务代码中脱离出来。
### 4. 全局异常统一处理
通过拦截所有异常,对各种异常进行相应的处理,当遇到异常就逐层上抛,一直抛到最终由一个统一的、专门负责异常处理的地方处理,这有利于对异常的维护。
### 5. 页面缓存 + 对象缓存
1. 页面缓存:通过在手动渲染得到的html页面缓存到redis
2. 对象缓存:包括对用户信息、商品信息、订单信息和token等数据进行缓存,利用缓存来减少对数据库的访问,大大加快查询速度。
### 6. 页面静态化
对商品详情和订单详情进行页面静态化处理,页面是存在html,动态数据是通过接口从服务端获取,实现前后端分离,静态页面无需连接数据库打开速度较动态页面会有明显提高
### 7. 本地标记 + redis预处理 + RabbitMQ异步下单 + 客户端轮询
描述:通过三级缓冲保护,1、本地标记 2、redis预处理 3、RabbitMQ异步下单,最后才会访问数据库,这样做是为了最大力度减少对数据库的访问。
实现:
1. 在秒杀阶段使用本地标记对用户秒杀过的商品做标记,若被标记过直接返回重复秒杀,未被标记才查询redis,通过本地标记来减少对redis的访问
2. 抢购开始前,将商品和库存数据同步到redis中,所有的抢购操作都在redis中进行处理,通过Redis预减少库存减少数据库访问
3. 为了保护系统不受高流量的冲击而导致系统崩溃的问题,使用RabbitMQ用异步队列处理下单,实际做了一层缓冲保护,做了一个窗口模型,窗口模型会实时的刷新用户秒杀的状态。
4. client端用js轮询一个接口,用来获取处理状态
### 8. 解决超卖
描述:比如某商品的库存为1,此时用户1和用户2并发购买该商品,用户1提交订单后该商品的库存被修改为0,而此时用户2并不知道的情况下提交订单,该商品的库存再次被修改为-1,这就是超卖现象
实现:
1. 对库存更新时,先对库存判断,只有当库存大于0才能更新库存
2. 对用户id和商品id建立一个唯一索引,通过这种约束避免同一用户发同时两个请求秒杀到两件相同商品
3. 实现乐观锁,给商品信息表增加一个version字段,为每一条数据加上版本。每次更新的时候version+1,并且更新时候带上版本号,当提交前版本号等于更新前版本号,说明此时没有被其他线程影响到,正常更新,如果冲突了则不会进行提交更新。当库存是足够的情况下发生乐观锁冲突就进行一定次数的重试。
### 9. 使用数学公式验证码
描述:点击秒杀前,先让用户输入数学公式验证码,验证正确才能进行秒杀。
好处:
1. 防止恶意的机器人和爬虫
2. 分散用户的请求
实现:
1. 前端通过把商品id作为参数调用服务端创建验证码接口
2. 服务端根据前端传过来的商品id和用户id生成验证码,并将商品id+用户id作为key,生成的验证码作为value存入redis,同时将生成的验证码输入图片写入imageIO让前端展示
3. 将用户输入的验证码与根据商品id+用户id从redis查询到的验证码对比,相同就返回验证成功,进入秒杀;不同或从redis查询的验证码为空都返回验证失败,刷新验证码重试
### 10. 使用RateLimiter实现限流
描述:当我们去秒杀一些商品时,此时可能会因为访问量太大而导致系统崩溃,此时要使用限流来进行限制访问量,当达到限流阀值,后续请求会被降级;降级后的处理方案可以是:返回排队页面(高峰期访问太频繁,等一会重试)、错误页等。
实现:项目使用RateLimiter来实现限流,RateLimiter是guava提供的基于令牌桶算法的限流实现类,通过调整生成token的速率来限制用户频繁访问秒杀页面,从而达到防止超大流量冲垮系统。(令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务)
## 压测效果
优化前 :开启1000个线程循环10次同时访问,QPS = 423
![优化前](https://github.com/zaiyunduan123/jesper_seckill/blob/master/src/main/resources/static/img/stress-test/goodsList_test_3.png)
优化后:QPS = 2501
![优化后](https://github.com/zaiyunduan123/jesper_seckill/blob/master/src/main/resources/static/img/stress-test/optimised_goodslist.png)
## 关于项目运行的步骤
1. 把sql目录下的seckill.sql脚本在你MySQL跑一遍,生成数据库表和数据
2. 启动项目需要用到的组件Redis和RabbitMQ
3. 直接运行启动类MainApplication.java
4. 访问localhost:8080/login/to_login
5. 登录的用户名是18181818181,密码是123456
-----
本项目是学习了imooc网视频之后的个人理解和知识汇总,学习链接:https://coding.imooc.com/class/168.html
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
本系统是使用SpringBoot开发的高并发限时抢购秒杀系统,除了实现基本的登录、查看商品列表、秒杀、下单等功能,项目中还针对高并发情况实现了系统缓存、降级和限流。 开发工具 IntelliJ IDEA + Navicat + Sublime Text3 + Git + Chrome 压测工具 JMeter 开发技术 前端技术 :Bootstrap + jQuery + Thymeleaf 后端技术 :SpringBoot + MyBatis + MySQL 中间件技术 : Druid + Redis + RabbitMQ + Guava 把sql目录下的seckill.sql脚本在你MySQL跑一遍,生成数据库表和数据 启动项目需要用到的组件Redis和RabbitMQ 直接运行启动类MainApplication.java 访问localhost:8080/login/to_login 登录的用户名是18181818181,密码是123456
资源推荐
资源详情
资源评论
收起资源包目录
基于SpringBoot + MySQL + Redis + RabbitMQ + Guava开发的高并发商品限时秒杀系统 (109个子文件)
bootstrap.css 143KB
bootstrap.min.css 118KB
bootstrap-theme.css 26KB
bootstrap-theme.min.css 23KB
layer.css 14KB
layer.css 5KB
glyphicons-halflings-regular.eot 20KB
loading-0.gif 6KB
loading-2.gif 2KB
loading-1.gif 701B
goods_detail.htm 6KB
order_detail.htm 3KB
goods_detail.html 4KB
login.html 3KB
order_detail.html 3KB
goods_list.html 2KB
hello.html 1024B
seckill_fail.html 246B
GoodsController.java 5KB
SeckillController.java 5KB
RedisService.java 5KB
UserService.java 4KB
UserUtil.java 3KB
DemoController.java 3KB
UserArgumentResolver.java 3KB
CodeMsg.java 2KB
OrderInfo.java 2KB
OrderService.java 2KB
MQReceiver.java 2KB
OrderController.java 2KB
SeckillService.java 2KB
MQConfig.java 2KB
GoodsService.java 2KB
User.java 2KB
RedisConfig.java 1KB
GlobalExceptionHandler.java 1KB
Goods.java 1KB
MD5Util.java 1KB
GoodsMapper.java 1KB
OrderMapper.java 1KB
MQSender.java 1KB
LoginController.java 1KB
SeckillGoods.java 1KB
GoodsVo.java 1KB
RateLimiterDemo.java 1KB
WebConfig.java 992B
IsMobileValidator.java 952B
Result.java 936B
RedisPoolFactory.java 932B
GoodsDetailVo.java 892B
DBUtil.java 865B
LoginVo.java 858B
UserController.java 842B
IsMobile.java 755B
SeckillOrder.java 745B
BasePrefix.java 694B
ValidatorUtil.java 595B
UserMapper.java 560B
UserKey.java 522B
GlobalException.java 495B
SeckillMessage.java 494B
OrderDetailVo.java 488B
GoodsKey.java 383B
MainApplication.java 305B
KeyPrefix.java 296B
OrderKey.java 275B
SeckillKey.java 267B
UUIDUtil.java 266B
bg.jpg 3.62MB
bg2.jpg 80KB
jquery.min.js 82KB
bootstrap.js 68KB
bootstrap.min.js 36KB
layer.js 21KB
jquery.validate.min.js 21KB
additional-methods.min.js 17KB
md5.min.js 10KB
layer.js 3KB
common.js 1KB
messages_zh.min.js 1KB
npm.js 484B
bootstrap.min.css.map 529KB
bootstrap.css.map 380KB
bootstrap-theme.css.map 47KB
bootstrap-theme.min.css.map 25KB
README.md 7KB
iphone8.png 340KB
mi6.png 74KB
meta10.png 41KB
userinfo_test_2.png 30KB
userinfo_test_1.png 29KB
userinfo_test_5.png 28KB
goodsList_test_2.png 27KB
goodsList_test_3.png 26KB
optimised_goodslist.png 26KB
optimised_userinfo.png 25KB
userinfo_test_4.png 25KB
goodslist_test_1.png 24KB
iphonex.png 23KB
icon.png 11KB
共 109 条
- 1
- 2
资源评论
余十步
- 粉丝: 1677
- 资源: 172
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功