use of com.whoiszxl.cqrs.cache.SeckillItemCache in project shopzz by whoiszxl.
the class DefaultPlaceOrderServiceImpl method doPlaceOrder.
@Override
public Long doPlaceOrder(Long memberId, SeckillOrderSubmitCommand seckillOrderSubmitCommand) {
boolean allowFlag = checkSeckill(seckillOrderSubmitCommand.getSeckillId());
AssertUtils.isTrue(allowFlag, "秒杀活动校验失败");
allowFlag = checkSeckillItem(seckillOrderSubmitCommand.getSeckillItemId());
AssertUtils.isTrue(allowFlag, "秒杀商品校验失败");
// 缓存中获取秒杀item,并将缓存中的库存设置上
SeckillItemCache seckillItemCache = seckillItemCachedService.getCachedSeckillItem(seckillOrderSubmitCommand.getSeckillItemId(), null);
putStockToItem(seckillItemCache.getSeckillItem());
SeckillItem seckillItem = seckillItemCache.getSeckillItem();
boolean preSubCacheFlag = false;
try {
// 进行库存预扣减
preSubCacheFlag = stockCacheService.subCacheStock(seckillOrderSubmitCommand.getSeckillItemId(), seckillOrderSubmitCommand.getQuantity());
AssertUtils.isTrue(preSubCacheFlag, "库存预扣减失败");
// 进行库存实际扣减
boolean subDbFlag = seckillItemService.subDbStock(seckillOrderSubmitCommand.getSeckillItemId(), seckillOrderSubmitCommand.getQuantity());
AssertUtils.isTrue(subDbFlag, "库存扣减失败");
// 持久化订单
SeckillOrder seckillOrder = buildSeckillOrder(seckillItem, seckillOrderSubmitCommand);
boolean saveFlag = seckillOrderService.save(seckillOrder);
if (!saveFlag) {
ExceptionCatcher.catchValidateEx(ResponseResult.buildError("下单失败"));
}
return seckillOrder.getId();
} catch (Exception e) {
// 如果预下单成功了,回滚缓存里的库存数量
if (preSubCacheFlag) {
boolean recoverFlag = stockCacheService.addCacheStock(seckillOrderSubmitCommand.getSeckillItemId(), seckillOrderSubmitCommand.getQuantity());
if (!recoverFlag) {
log.error("预扣减库存恢复失败,用户ID:{}, 秒杀商品ID:{}, 秒杀数量:{}", memberId, seckillOrderSubmitCommand.getSeckillItemId(), seckillOrderSubmitCommand.getQuantity());
}
ExceptionCatcher.catchValidateEx(ResponseResult.buildError("下单失败"));
}
}
return null;
}
use of com.whoiszxl.cqrs.cache.SeckillItemCache in project shopzz by whoiszxl.
the class SeckillItemCachedServiceImpl method loadDb.
private SeckillItemCache loadDb(Long seckillItemId) {
DistributedLock lock = distributedLockFactory.getDistributedLock(RedisKeyPrefixConstants.LOCK_GET_ITEM_FROM_DB + seckillItemId);
try {
boolean isLockSuccess = lock.tryLock(1, 5, TimeUnit.SECONDS);
if (!isLockSuccess) {
return new SeckillItemCache().tryLater();
}
SeckillItem seckillItem = seckillItemService.getById(seckillItemId);
SeckillItemCache seckillItemCache;
if (seckillItem == null) {
seckillItemCache = new SeckillItemCache().notExist();
} else {
seckillItemCache = new SeckillItemCache().with(seckillItem);
}
redisUtils.setEx(RedisKeyPrefixConstants.CACHE_SECKILL_ITEM + seckillItemId, JsonUtil.toJson(seckillItemCache), 3, TimeUnit.SECONDS);
log.info("从数据库加载数据,并保存到redis中:{}", seckillItemCache);
return seckillItemCache;
} catch (Exception e) {
log.error("从数据库加载数据失败", e);
return new SeckillItemCache().tryLater();
} finally {
lock.unlock();
}
}
use of com.whoiszxl.cqrs.cache.SeckillItemCache in project shopzz by whoiszxl.
the class DefaultPlaceOrderServiceImpl method checkSeckillItem.
private boolean checkSeckillItem(Long seckillItemId) {
SeckillItemCache seckillItemCache = seckillItemCachedService.getCachedSeckillItem(seckillItemId, null);
// 2. 校验缓存是否需要延迟加载
if (!seckillItemCache.isLater()) {
log.info("从缓存中获取秒杀商品信息需要延迟加载, 秒杀商品ID: {}", seckillItemId);
return false;
}
// 3. 校验活动是否存在
if (!seckillItemCache.isExist() || seckillItemCache.getSeckillItem() == null) {
log.info("秒杀商品不存在, 秒杀商品ID: {}", seckillItemId);
return false;
}
// 4. 校验活动是否上线
SeckillItem seckillItem = seckillItemCache.getSeckillItem();
if (!seckillItem.getStatus().equals(StatusEnum.OPEN.getCode())) {
log.info("秒杀商品未开启, 秒杀商品ID: {}", seckillItemId);
return false;
}
// 5. 校验活动是否在进行中
LocalDateTime now = LocalDateTime.now();
if (!seckillItem.getStartTime().isBefore(now) || !seckillItem.getEndTime().isAfter(now)) {
log.info("秒杀商品未在开启时间内, 秒杀商品ID: {}", seckillItemId);
return false;
}
return false;
}
use of com.whoiszxl.cqrs.cache.SeckillItemCache in project shopzz by whoiszxl.
the class SeckillItemCachedServiceImpl method getDistributedCache.
/**
* 从分布式缓存中获取item
* @param seckillItemId
* @return
*/
private SeckillItemCache getDistributedCache(Long seckillItemId) {
String itemKey = RedisKeyPrefixConstants.CACHE_SECKILL_ITEM + seckillItemId;
String itemJson = redisUtils.get(itemKey);
SeckillItemCache seckillItemCache = JsonUtil.fromJson(itemJson, SeckillItemCache.class);
if (seckillItemCache == null) {
// 缓存不存在,需要从数据库中读取,并更新缓存
seckillItemCache = loadDb(seckillItemId);
}
if (seckillItemCache != null && !seckillItemCache.isLater()) {
boolean isLockSuccess = localCacleUpdatelock.tryLock();
if (isLockSuccess) {
try {
seckillItemGuavaCache.put(seckillItemId, seckillItemCache);
log.info("更新了本地item缓存:{}", seckillItemCache);
} finally {
localCacleUpdatelock.unlock();
}
}
}
return seckillItemCache;
}
use of com.whoiszxl.cqrs.cache.SeckillItemCache in project shopzz by whoiszxl.
the class QueuedPlaceOrderServiceImpl method checkSeckillItem.
private boolean checkSeckillItem(Long seckillItemId) {
SeckillItemCache seckillItemCache = seckillItemCachedService.getCachedSeckillItem(seckillItemId, null);
// 2. 校验缓存是否需要延迟加载
if (seckillItemCache.isLater()) {
log.info("从缓存中获取秒杀商品信息需要延迟加载, 秒杀商品ID: {}", seckillItemId);
return false;
}
// 3. 校验活动是否存在
if (!seckillItemCache.isExist() || seckillItemCache.getSeckillItem() == null) {
log.info("秒杀商品不存在, 秒杀商品ID: {}", seckillItemId);
return false;
}
// 4. 校验活动是否上线
SeckillItem seckillItem = seckillItemCache.getSeckillItem();
if (!seckillItem.getStatus().equals(StatusEnum.OPEN.getCode())) {
log.info("秒杀商品未开启, 秒杀商品ID: {}", seckillItemId);
return false;
}
// 5. 校验活动是否在进行中
LocalDateTime now = LocalDateTime.now();
if (!seckillItem.getStartTime().isBefore(now) || !seckillItem.getEndTime().isAfter(now)) {
log.info("秒杀商品未在开启时间内, 秒杀商品ID: {}", seckillItemId);
return false;
}
return true;
}
Aggregations