执行秒杀:
用户通过秒杀页面,点击商品,前端传递秒杀id,进入到商品详情页面,通过秒杀id查询Redis中的这个商品的信息,返回给前端展示。用户点击秒杀携带商品id跟商品的防刷码,做了用户登录的校验,然后一堆校验,校验防刷码、商品、秒杀时间、秒杀状态。预减库存,信号量减1,最后构建了一个预创订单,预创订单数据,订单号、购买人、课程的id、价格、课程的名字。然后把预创订单存储到Redis 中。最终将这个预创订单号返回给前端。
这里执行秒杀还做了防止用户重复秒杀该商品,也就是没有支付就在详情页面一直点击秒杀,以用户id跟课程id作为key存储到Redis。
代码演示
service
/**
* 点击秒杀
* 1.参数校验
* 1.课程的防刷码
* 2.课程是否存在
* 3.
* 2.条件校验
* 1.要登录
* 2.秒杀码校验
* 3.秒杀时间是否合法
* 4.重复秒杀
* 5.黑名单(没做)
*
* 3.预见库存
* 1.卖完 信号量剪到0,就秒杀不了了。
* 4.构建订单
* @TODO 直接构建一个订单,然后直接先存在Redis 秒杀--快!!
* 4.构建订单详情
* 5.构建秒杀支付订单
* 6.mq事务消息
* 7.订单超时 延迟消息
* @param dto 秒杀防刷码 秒杀课程
* @return 秒杀订单号
*/
@Override
public String kill(KillDTO dto) {
long oldTime = System.currentTimeMillis();
String killCode = dto.getKillCode();
Long killCourseId = dto.getKillCourseId();
//==1.登录
Login login = LoginContextHolder.getLogin();
if(login == null){
throw new MyError("请先登录");
}
//==1.查看Redis
Object killCourse_key = redisTemplate.opsForHash().get("killCourse_KEY", killCourseId.toString());
if(killCourse_key==null){
throw new MyError("非法请求!!");
}
KillCourse killCourse = JSON.parseObject(killCourse_key.toString(), KillCourse.class);
//秒杀码匹对
if(!killCourse.getKillCode().equals(killCode)){
//校验秒杀码
throw new MyError("非法请求!!");
}
//==3.校验秒杀时间
long nowTime = System.currentTimeMillis();
if(nowTime < killCourse.getStartTime().longValue() || nowTime > killCourse.getEndTime().longValue()){
//秒杀时间之前,说明秒杀还没开始 现在时间大于了结束时间,秒杀结束了
throw new MyError("非法请求");
}
//==4.重复秒杀
Long killId = killCourse.getId();
String loginIdStr = login.getId().toString();
String killUserRepeat = loginIdStr + ":" + killId;
Object killRepeat = redisTemplate.opsForValue().get(killUserRepeat);
if(killRepeat != null){
throw new MyError("请勿重复秒杀");
}
//5.预减库存
//===1.获得到一个信号量
RSemaphore semaphore = redissonClient.getSemaphore("killCounts:" + killId.toString());
//信号量减 1
boolean tryAcquire = semaphore.tryAcquire(killConstant);
if(!tryAcquire){
throw new MyError("库存不足!!");
}
//6.构建订单,存储在Redis
KillOrderVO killOrderVO = new KillOrderVO();
killOrderVO.setAmount(killCourse.getKillPrice());
killOrderVO.setCourseId(killCourse.getCourseId());
String killOrderCode = OrderUtils.getOrderCode(Integer.valueOf(loginIdStr));
killOrderVO.setOrderNo(killOrderCode);
killOrderVO.setUserId(login.getId());
killOrderVO.setCourseName(killCourse.getCourseName());
//保存到Redis
redisTemplate.opsForValue().set(
killOrderCode,
killOrderVO
);
// 用户秒杀就存储一个记录在Redis,防止重复点击秒杀
redisTemplate.opsForValue().set(
killUserRepeat,
killConstant
);
long nowTime1 = System.currentTimeMillis();
log.info("总计耗时间:{} 毫秒",nowTime1-oldTime);
return killOrderCode;
}
不许勿喷!!谢谢!!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)