Search in sources :

Example 1 with SeckillItemCache

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;
}
Also used : SeckillItem(com.whoiszxl.entity.SeckillItem) SeckillOrder(com.whoiszxl.entity.SeckillOrder) SeckillItemCache(com.whoiszxl.cqrs.cache.SeckillItemCache)

Example 2 with SeckillItemCache

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();
    }
}
Also used : SeckillItem(com.whoiszxl.entity.SeckillItem) DistributedLock(com.whoiszxl.DistributedLock) SeckillItemCache(com.whoiszxl.cqrs.cache.SeckillItemCache)

Example 3 with SeckillItemCache

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;
}
Also used : SeckillItem(com.whoiszxl.entity.SeckillItem) LocalDateTime(java.time.LocalDateTime) SeckillItemCache(com.whoiszxl.cqrs.cache.SeckillItemCache)

Example 4 with SeckillItemCache

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;
}
Also used : SeckillItemCache(com.whoiszxl.cqrs.cache.SeckillItemCache)

Example 5 with 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;
}
Also used : SeckillItem(com.whoiszxl.entity.SeckillItem) LocalDateTime(java.time.LocalDateTime) SeckillItemCache(com.whoiszxl.cqrs.cache.SeckillItemCache)

Aggregations

SeckillItemCache (com.whoiszxl.cqrs.cache.SeckillItemCache)5 SeckillItem (com.whoiszxl.entity.SeckillItem)4 LocalDateTime (java.time.LocalDateTime)2 DistributedLock (com.whoiszxl.DistributedLock)1 SeckillOrder (com.whoiszxl.entity.SeckillOrder)1