引言
本文代码已提交至Github(版本号:
a08c2b261d8cd31850ccebc38a4a6620090e619f
),有兴趣的同学可以下载来看看:https://github.com/ylw-github/taodong-shop
在上一篇博客《淘东电商项目(74) -秒杀系统(库存超卖解决方案)主要讲解了库存超卖的解决,继续完善上一篇博客的代码,以下的第二个步骤:
@Transactional public BaseResponse<JSONObject> spike(String phone, Long seckillId) { // 1.参数验证 if (StringUtils.isEmpty(phone)) { return setResultError("手机号码不能为空!"); } if (seckillId == null) { return setResultError("商品库存id不能为空!"); } SeckillEntity seckillEntity = seckillMapper.findBySeckillId(seckillId); if (seckillEntity == null) { return setResultError("商品信息不存在!"); } // 2.用户频率限制 setnx 如果key存在话 // 3.(悲观锁 )修改数据库对应的库存 1万中只有100个抢购成功 提前生成好100个token 谁能够抢购成功token放入到mq中实现异步修改库存 int inventoryDeduction = seckillMapper.pessimisticDeduction(seckillId); if (!toDaoResult(inventoryDeduction)) { log.info(">>>修改库存失败>>>>inventoryDeduction返回为{} 秒杀失败!", inventoryDeduction); return setResultError("亲,请稍后重试!"); } // 4.添加秒杀成功订单 基于MQ实现异步形式 OrderEntity orderEntity = new OrderEntity(); orderEntity.setUserPhone(phone); orderEntity.setSeckillId(seckillId); int insertOrder = orderMapper.insertOrder(orderEntity); if (!toDaoResult(insertOrder)) { return setResultError("亲,请稍后重试!"); } log.info(">>>修改库存成功>>>>inventoryDeduction返回为{} 秒杀成功", inventoryDeduction); return setResultSuccess("恭喜您,秒杀成功!"); }
本文目录结构:
1.用户操作频率限制代码实现
用户的操作频率限制很简单,可以使用Redis的操作机制限制,Redis超时设置通用方法如下:
/** * description: 如果key存在的话返回fasle 不存在的话返回true * create by: YangLinWei * create time: 2020/5/25 5:45 下午 */ public Boolean setNx(String key, String value, Long timeout) { Boolean setIfAbsent = stringRedisTemplate.opsForValue().setIfAbsent(key, value); if (timeout != null) { stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS); } return setIfAbsent; }
完善第二步骤:
@Transactional public BaseResponse<JSONObject> spike(String phone, Long seckillId) { // 1.参数验证 if (StringUtils.isEmpty(phone)) { return setResultError("手机号码不能为空!"); } if (seckillId == null) { return setResultError("商品库存id不能为空!"); } SeckillEntity seckillEntity = seckillMapper.findBySeckillId(seckillId); if (seckillEntity == null) { return setResultError("商品信息不存在!"); } // 2.用户频率限制 setnx 如果key存在话 Boolean reusltNx = redisUtil.setNx(phone, seckillId + "", 10l); if (!reusltNx) { return setResultError("访问次数过多,10秒后在实现重试!"); } // 3.(悲观锁 )修改数据库对应的库存 1万中只有100个抢购成功 提前生成好100个token 谁能够抢购成功token放入到mq中实现异步修改库存 int inventoryDeduction = seckillMapper.pessimisticDeduction(seckillId); if (!toDaoResult(inventoryDeduction)) { log.info(">>>修改库存失败>>>>inventoryDeduction返回为{} 秒杀失败!", inventoryDeduction); return setResultError("亲,请稍后重试!"); } // 4.添加秒杀成功订单 基于MQ实现异步形式 OrderEntity orderEntity = new OrderEntity(); orderEntity.setUserPhone(phone); orderEntity.setSeckillId(seckillId); int insertOrder = orderMapper.insertOrder(orderEntity); if (!toDaoResult(insertOrder)) { return setResultError("亲,请稍后重试!"); } log.info(">>>修改库存成功>>>>inventoryDeduction返回为{} 秒杀成功", inventoryDeduction); return setResultSuccess("恭喜您,秒杀成功!"); }
2. 测试
浏览器访问:http://localhost:9800/spike?phone=13800000001&seckillId=100001
浏览器立刻再次访问:
可以看到通过redis可以控制用户访问的频率,本文完!