# 基于Springboot+Redis+RabbitMQ的高并发选课系统 **Repository Path**: java-233/second ## Basic Information - **Project Name**: 基于Springboot+Redis+RabbitMQ的高并发选课系统 - **Description**: 本系统是使用 Spring Boot 开发的支持高并发的选课系统,除了能实现基本的登录,查看课表,查看选修课程这些功能之外,项目还针对选课时的高并发情况实现了系统缓存,流量削峰。 - **Primary Language**: Java - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 11 - **Created**: 2021-12-09 - **Last Updated**: 2021-12-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 项目源码 托管在Gitee上 [https://gitee.com/RaceK/second](https://gitee.com/RaceK/second) 目前仍处于开发阶段,现仅作学习测试用,有兴趣的小伙伴可以一起探讨一下怎么完善这个系统,后续将会持续增删一些模块,系统大概的架构和技术点都写在下面了 # 项目安装 ## 环境准备 1. 需要RabbitMQ的环境,[安装教程](https://blog.csdn.net/x7536987/article/details/106162040) 2. 需要Redis [安装教程](https://www.jianshu.com/p/7f5ecfc388a0) 3. 下载源码 4. 新建 SpringBoot 项目 5. 将源码复制进刚刚新建的项目中 6. 刷新 maven 的 pom.xml 导入依赖 7. 查看 maven 的依赖是否已经导入了 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200517124221215.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0tvYmVfaw==,size_16,color_FFFFFF,t_70) 8. 开启 Redis 和 RabbitMQ 的服务 Redis目录下 `redis-server.exe` 和 RabbitMQ的`sbin`目录下的`rabbitmq-server.bat` 9. 运行项目 # 项目介绍 # 1. 系统介绍 本系统是使用 Spring Boot 开发的支持高并发的选课系统 除了能实现基本的登录,查看课表,查看选修课程这些功能之外,项目还针对选课时的高并发情况实现了系统缓存,流量削峰。 # 2. 压测工具 JMeter # 3. 开发技术 前端技术 :Bootstrap + jQuery + Thymeleaf 后端技术 :SpringBoot + MyBatisPlus + MySQL + Shiro 中间件技术 : Druid + Redis + RabbitMQ # 4. 高并发时优化方向 1. 与秒杀商城不同,选课要求每个同学都能选取到自己钟爱的课程,那么就不存在秒杀中读多写少的情况,针对这种情况,可以通过限流,流量削峰等措施最大化降低服务器宕机的概率,从而保证系统能够稳定运行 2. 充分利用缓存:尽管不是读多写少的应用场景,但是降低对数据库的访问也能够提高服务器的效率,充分利用缓存能大大降低服务器性能的消耗 3. 充分利用消息队列:高并发时,利用队列对流量进行削峰 # 5. 实现技术点 ## Shiro 安全框架 1. 对未进行登录的用户进行拦截,首页即为登录页,必须登录了才可以进入,否则将会被拦截 2. 账户授权和认证 3. Session的管理 ## MD5加密 将用户输入的密码和固定 Salt 通过 MD5加密 生成第一次加密后的密码,再将该密码和随机生成的 Salt 通过 MD5 进行第二次加密,最后将第二次加密后的密码和第一次的固定 Salt 存数据库 好处: 1. 第一次作用:防止用户明文密码在网络进行传输 2. 第二次作用:防止数据库被盗,避免通过MD5反推出密码,双重保险 ## JSR303自定义参数验证 使用JSR303自定义校验器,实现对用户账号、密码的验证,使得验证逻辑从业务代码中脱离出来。 ## 全局异常统一处理 通过拦截所有异常,对各种异常进行相应的处理,当遇到异常就逐层上抛,一直抛到最终由一个统一的、专门负责异常处理的地方处理,这有利于对异常的维护。 ## 对象缓存 对象缓存:包括对用户信息、课程信息和 token 等数据进行缓存,利用缓存来减少对数据库的访问,大大加快查询速度。 ## 本地标记 + redis预处理 + RabbitMQ异步提交 + 客户端轮询获取处理状态 描述:通过三级缓冲保护,1、本地标记 2、redis预处理 3、RabbitMQ异步提交,最后才会访问数据库,这样做是为了最大力度降低服务器宕机的概率。 实现: 1. 在选课阶段使用本地标记对用户已经选了的课程做标记,若被标记过直接返回重复提交,未被标记才查询 redis,通过本地标记来减少对redis的访问 2. 选课开始前,将课程的数据同步到redis中,所有的选课操作都在redis中进行处理,通过Redis预减少课程已选人数减少数据库访问 3. 为了保护系统不受高流量的冲击而导致系统崩溃的问题,使用RabbitMQ用异步队列处理提交,实际做了一层缓冲保护,做了一个窗口模型,窗口模型会实时的刷新用户选课的状态。 4. client 端用 js 轮询一个接口,用来获取处理状态 ## 解决超选 描述:比如某课程剩余可选数量为1,此时用户1和用户2并发选择该课程,用户1提交后该课程剩余可选数量被修改为0,而此时用户2并不知道的情况下提交订单,该课程剩余可选数量再次被修改为-1,这就是超选。 实现: 1. 对课程剩余可选数量更新时,先对其进行判断,只有当大于0才能更新处理 2. 对用户id和课程id建立一个唯一索引,通过这种约束避免同一用户同时发两个请求选到两个相同的课程 3. 实现乐观锁,给选课信息表增加一个version字段,为每一条数据加上版本。每次更新的时候version+1,并且更新时候带上版本号,当提交前版本号等于更新前版本号,说明此时没有被其他线程影响到,正常更新,如果冲突了则不会进行提交更新。当课程剩余可选数量是足够的情况下发生乐观锁冲突就进行一定次数的重试,不够则返回失败信息。 ## 使用数学公式验证码 描述:选好课程点击提交前,先让用户输入数学公式验证码,验证正确才能进行提交。 好处: 1. 防止恶意的机器人和爬虫或者一些脚本 2. 分散用户的请求 实现: 1. 利用JQuery的插件,点击提交之前需要进行验证操作 ## 在某一时间段才开启选课界面 描述:打开链接的时候通过服务器判断是否在正选时间段内,若不在则返回一个空界面; # 6. 压测效果 目前仍处于开发阶段,尚未进行压测