执行秒杀逻辑(1.2)

执行秒杀逻辑(1.2),第1张

执行秒杀:

用户通过秒杀页面,点击商品,前端传递秒杀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;
	}

不许勿喷!!谢谢!!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/langs/741867.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-28
下一篇 2022-04-28

发表评论

登录后才能评论

评论列表(0条)

保存