1、如何使用Redis和RabbitMQ实现一个学生抢课系统(可类比商品秒杀系统)

  • 电商项目中的秒杀场景我们都很常见,不只是京东和淘宝现在很多的小程序公众号也有做现时限购的秒杀场景,那么如何做一个秒杀系统呢?
  • 把数据全部放在MySQL数据中,这显然是不现实的,因为在秒杀开始时会有大量的请求涌进来,如果直接访问数据库,我们的MySQL很容易崩点,我们就应该做一层过滤。

如下就是实现一个抢课系统的来类比一个秒杀系统。

我们这里引入Redisson,介绍如下:

  • Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service) Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。

详细文档链接

而在我们的这个秒杀程序中主要运用了Redisson中的信号量(Semaphore)

在抢课之前我们先将课程进行一个上架操作,主要就是将课程的最高选课人数作为信号量存入redis中。关键代码如下:

@Autowired
private CourseMapper courseMapper;
@Autowired
private RedissonClient redissonClient; private final String COURSE_SEMAPHORE = "subject:course:num:";// @Test
public void contextLoads() {
log.info("开始上架课程");
List<Course> sessions = courseMapper.selectOkCourse();
sessions.stream().forEach(session ->{
String jsonString = JSON.toJSONString(session);
//引入分布式的信号量 用信号量控制并发数,限流
RSemaphore semaphore = redissonClient.getSemaphore(COURSE_SEMAPHORE + session.getId());
//课程的最大人数作为信号量
semaphore.trySetPermits(session.getNum()); });
}

在学生抢课的过程中,我们会做一下几步操作:

1、校验该学生是否已经讲过该课程

2、校验该课程是否已经达到最大选课人数

3、该学生的选课信息放入倒RabbitMQ中,由其他模块进行异步处理学生选课入库

代码如下:

public String subject(String studentId, String courseId) {
log.info("抢课任务开始{},{}",studentId,courseId);
Long ttl = 24*3600L; //过期时间根据具体情况配置,这里为了简便写了两天
//2.4验证学生是否已经抢过该课(幂等性)
//setnx不存在的时候才占位
String redisKey = studentId+"_"+courseId;
Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(redisKey, "1".toString(), ttl, TimeUnit.SECONDS);
if(aBoolean) {
//成功表示该学生第一次选课
//3.获取信号量tryAcquire()非阻塞方法
RSemaphore semaphore = redissonClient.getSemaphore(COURSE_SEMAPHORE + courseId);
    //获取信号量,同一个课程,同一个学生只能选一次,故这里获取一个信号量,若是商品可根据限购几件来设定
        boolean b = semaphore.tryAcquire(1);
if(b){
//还有信号量,抢课信息入库 MQ登场
log.info("抢课完成");
SubjectTo subjectTo = new SubjectTo(studentId,courseId);
rabbitTemplate.convertAndSend("course-event-exchange","course.seckill.course",subjectTo);
log.info("发送完成");
return "1";
}else {
//该课程已经被抢完
log.error("该课程已经被抢完");
return "3";
}
}else{
//已经选过该课程
log.error("该过程已经抢过");
return "2";
}
}

监听MQ的入库程序如下:

@RabbitListener(queues = "seckill.course.queue")
public void handleSecKillOrderCreate(SubjectTo to) {
try {
log.info("---------抢课信息准备入库-----------");
//加入课程学生表中
courseService.makeItCoures(to);
//该课程剩余可选人数减少1(主要是为了展示课程剩余人数来使用)
courseService.changeNowNum(to.getCourseId());
} catch (Exception e) {
e.printStackTrace();
}
}

以上就上学生抢课系统的主要思路,比较简介。其中步骤主要分为如下:

    1、课程上架

    2、学生抢课模块,抢课校验,课程信息放MQ中

   3、监听MQ中的选课信息,进行入库操作。

个人公众号 :hellotqq,坚持原创输出,坚持分享学习感悟,下方扫码关注,与您共同成长!

如何使用Redis和RabbitMQ实现一个学生抢课系统(可类比商品秒杀系统)的更多相关文章

  1. 用Redis轻松实现秒杀系统

    秒杀系统的架构设计 秒杀系统,是典型的短时大量突发访问类问题.对这类问题,有三种优化性能的思路: 写入内存而不是写入硬盘 异步处理而不是同步处理 分布式处理 用上这三招,不论秒杀时负载多大,都能轻松应 ...

  2. 缓存、队列(Memcached、redis、RabbitMQ)

    本章内容: Memcached 简介.安装.使用 Python 操作 Memcached 天生支持集群 redis 简介.安装.使用.实例 Python 操作 Redis String.Hash.Li ...

  3. 缓存、队列(Memcached,Redis,rabbitMQ)

    一.Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的 ...

  4. Python之路【第十篇】Python操作Memcache、Redis、RabbitMQ、SQLAlchemy、

    Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...

  5. 缓存大全(Memcached、redis、RabbitMQ )

    Memcached: 简介.安装.使用 python操作Memcached Memcached天生支持集群 Redis: 简介.安装.使用.实例 Python操作Redis String.Hash.L ...

  6. Python-操作Memcache、Redis、RabbitMQ、

    Memcache 简述: Memcache是一套分布式的高速缓存系统,由LiveJournal的Brad Fitzpatrick开发,但目前被许多网站使用以提升网站的访问速度,尤其对于一些大型的.需要 ...

  7. Python自动化运维之17、Python操作 Memcache、Redis、RabbitMQ

    一.Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的 ...

  8. Python操作 Memcache、Redis、RabbitMQ、SQLAlchemy

    Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...

  9. centos7.6编译安装php7.2.11及redis/memcached/rabbitmq/openssl/curl等常见扩展

    centos7.6编译安装php7..11及redis/memcached/rabbitmq/openssl/curl等常见扩展 获取Php的编译参数方法: [root@eus-api-cms-bac ...

随机推荐

  1. qiankun+vue,为什么我的子应用的子路由老是跳404?这么解决

    主要解决子应用内部跳转路由时,跳到404页的问题 你能搜这个,我姑且认为你基本配置已经好了,而且主跳子的一级路由是正常的,请往下看 忘说了,我的主应用和子应用都是Vue 主应用跳子应用都正常,为什么子 ...

  2. 【算法训练营day7】LeetCode454. 四数相加II LeetCode383. 赎金信 LeetCode15. 三数之和 LeetCode18. 四数之和

    [算法训练营day7]LeetCode454. 四数相加II LeetCode383. 赎金信 LeetCode15. 三数之和 LeetCode18. 四数之和 LeetCode454. 四数相加I ...

  3. 认识 Redis client-output-buffer-limit 参数与源码分析

    概述 Redis 的 client-output-buffer-limit 可以用来强制断开无法足够快从 redis 服务器端读取数据的客户端.保护机制规则如下: [hard limit] 大小限制, ...

  4. 删除数组里含有a的元素,并且将null值放在后面

    想去掉里面含有a的元素,并将null放在后面.放在后面就是往后移,其他值往左移 1 public static void main(String[] args) { 2 //自定义的一个数组 3 St ...

  5. Selenium+Python系列(三) - 常见浏览器操作

    写在前面 上篇文章为大家分享了自动化测试中,常见元素定位的操作. 今天再次读文章,居然忘记了大家特别喜欢的CSS和Xpath定位操作分享,这怎么能行呢? 马上安利,感兴趣的同学去参考下面链接: CSS ...

  6. 基于 Redis 实现分布式锁

    1.主流分布式锁实现方案 基于数据库实现分布式锁 基于缓存(redis 等) 基于 Zookeeper 2.根据实现方式分类 类 CAS 自旋式分布式锁:询问的方式,类似 java 并发编程中的线程获 ...

  7. html页面跳转方式

    js里的方法 第一种: window.location.href = XXXX; 第二种: window.setTimeout("javascript:location.href='xxxx ...

  8. JS逆向实战4--cookie——__jsl_clearance_s 生成

    分析 网站返回状态码521,从浏览器抓包来看,浏览器一共对此地址请求了三次(中间是设置cookie的过程): 第一次请求:网站返回的响应状态码为 521,响应返回的为经过 混淆的 JS 代码:但是这些 ...

  9. November 练习(Tou Xue)打卡

    Flag:NOIP前偷100道 \(\text{CF }1600\sim 2000+\) \(\text{or}\) \(\text{At } 1200\sim 1800+\) \(\text{or} ...

  10. 【ASP.NET Core】MVC控制器的各种自定义:应用程序约定的接口与模型

    从本篇起,老周会连发N篇水文,总结一下在 MVC 项目中控制器的各种自定义配置. 本文内容相对轻松,重点讨论一下 MVC 项目中的各种约定接口.毕竟你要对控制器做各种自定义时,多数情况会涉及到约定接口 ...