如下就是实现一个抢课系统的来类比一个秒杀系统。
我们这里引入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;
String redisKey = studentId+"_"+courseId;
Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(redisKey, "1".toString(), ttl, TimeUnit.SECONDS);
if(aBoolean) {
RSemaphore semaphore = redissonClient.getSemaphore(COURSE_SEMAPHORE + courseId);
boolean b = semaphore.tryAcquire(1);
if(b){
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);
courseService.changeNowNum(to.getCourseId());
} catch (Exception e) {
e.printStackTrace();
}
}
以上就上学生抢课系统的主要思路,比较简介。其中步骤主要分为如下:
1、课程上架
2、学生抢课模块,抢课校验,课程信息放MQ中
3、监听MQ中的选课信息,进行入库操作。
个人公众号 :hellotqq,坚持原创输出,坚持分享学习感悟,与您共同成长!
|