库存售罄方案
- 库存售罄标识
- 售罄后不操作后续流程
- 售罄后通知各系统售罄
- 回补上新
库存售罄方案实现
库存售罄标识
@Override
@Transactional
public boolean decreaseStock(Integer itemId, Integer amount) {
long result = redisTemplate.opsForValue().increment("promo_item_stock_" + itemId, amount * -1);
if (result > 0) {
return true;
} else if (result == 0) {
redisTemplate.opsForValue().set("promo_item_stock_invalid_" + itemId, "true");
return true;
} else {
redisTemplate.opsForValue().increment("promo_item_stock_" + itemId, amount);
return false;
}
}
售罄后不操作后续流程
- 生成库存流水之前,前看看是否存在售罄标识,如果存在,就不走后面的流程,直接返回前端;
@RequestMapping(value = "/createorder", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
@ResponseBody
public CommonReturnType createOrder(@RequestParam(name = "itemId") Integer itemId,
@RequestParam(name = "amount") Integer amount,
@RequestParam(name = "promoId", required = false) Integer promoId) throws BusinessException {
String token = httpServletRequest.getParameterMap().get("token")[0];
if (StringUtils.isEmpty(token)) {
throw new BusinessException(EmBusinessError.USER_NOT_LOGIN, "用户还未登录,不能下单");
}
UserModel userModel = (UserModel) redisTemplate.opsForValue().get(token);
if (userModel == null) {
throw new BusinessException(EmBusinessError.USER_NOT_LOGIN, "用户还未登录,不能下单");
}
// 判断库存是否已经售罄,若对应的售罄 key 存在,则直接返回下单失败
if (redisTemplate.hasKey("promo_item_stock_invalid_" + itemId)) {
throw new BusinessException(EmBusinessError.STOCK_NOT_ENOUGH);
}
String stockLogId = itemService.initStockLog(itemId, amount);
if(!mqProducer.transactionAsyncReduceStock(userModel.getId(), promoId, itemId, amount, stockLogId)) {
throw new BusinessException(EmBusinessError.UNKNOWN_ERROR, "下单失败");
}
return CommonReturnType.create(null);
}