mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-23 05:00:25 +08:00
feat(PmsConstants.java): 商品详情缓存
1、添加商品详情本地缓存 2、商品详情分布式锁保证原子操作 Closes I3V770
This commit is contained in:
parent
17dc8fdb59
commit
05dd9a07bf
@ -9,4 +9,8 @@ public interface PmsConstants {
|
||||
String LOCKED_STOCK_PREFIX = "stock:locked:";
|
||||
|
||||
String LOCK_SKU_PREFIX="lock:sku:";
|
||||
|
||||
String PRODUCT_DETAIL_CACHE = "product:detail:cache:";
|
||||
|
||||
String LOCK_PRODUCT_DETAIL="lock:product:detail";
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
package com.youlai.mall.pms.config;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.youlai.mall.pms.pojo.dto.app.ProductFormDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author DaniR
|
||||
* @version 1.0
|
||||
* @description 本地缓存设置
|
||||
* @createDate 2021/6/16 10:08
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ProductLocalCache {
|
||||
private Cache<String, ProductFormDTO> localCache = null;
|
||||
|
||||
@PostConstruct
|
||||
private void init(){
|
||||
localCache = CacheBuilder.newBuilder()
|
||||
//设置本地缓存容器的初始容量
|
||||
.initialCapacity(10)
|
||||
//设置本地缓存的最大容量
|
||||
.maximumSize(500)
|
||||
//设置写缓存后多少秒过期
|
||||
.expireAfterWrite(60, TimeUnit.SECONDS).build();
|
||||
}
|
||||
|
||||
|
||||
public void setLocalCache(String key, ProductFormDTO object){
|
||||
localCache.put(key,object);
|
||||
}
|
||||
|
||||
public ProductFormDTO get(String key){
|
||||
return localCache.getIfPresent(key);
|
||||
}
|
||||
}
|
@ -5,58 +5,103 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.youlai.common.redis.utils.RedisUtils;
|
||||
import com.youlai.mall.pms.config.ProductLocalCache;
|
||||
import com.youlai.mall.pms.mapper.PmsSpuMapper;
|
||||
import com.youlai.mall.pms.pojo.dto.SpuDTO;
|
||||
import com.youlai.mall.pms.pojo.dto.app.ProductFormDTO;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpuAttributeValue;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSku;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpec;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpu;
|
||||
import com.youlai.mall.pms.pojo.dto.SpuDTO;
|
||||
import com.youlai.mall.pms.service.IPmsSpuAttributeValueService;
|
||||
import com.youlai.mall.pms.pojo.entity.PmsSpuAttributeValue;
|
||||
import com.youlai.mall.pms.service.IPmsSkuService;
|
||||
import com.youlai.mall.pms.service.IPmsSpecService;
|
||||
import com.youlai.mall.pms.service.IPmsSpuAttributeValueService;
|
||||
import com.youlai.mall.pms.service.IProductService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.youlai.mall.pms.common.constant.PmsConstants.LOCK_PRODUCT_DETAIL;
|
||||
import static com.youlai.mall.pms.common.constant.PmsConstants.PRODUCT_DETAIL_CACHE;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @date 2020-11-06
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class ProductServiceImpl extends ServiceImpl<PmsSpuMapper, PmsSpu> implements IProductService {
|
||||
|
||||
private IPmsSkuService iPmsSkuService;
|
||||
private IPmsSpuAttributeValueService iPmsSpuAttributeValueService;
|
||||
private IPmsSpecService iPmsSpecService;
|
||||
private final IPmsSkuService iPmsSkuService;
|
||||
private final IPmsSpuAttributeValueService iPmsSpuAttributeValueService;
|
||||
private final IPmsSpecService iPmsSpecService;
|
||||
private final RedisUtils redisUtils;
|
||||
private final RedissonClient redissonClient;
|
||||
private final ProductLocalCache productLocalCache;
|
||||
|
||||
|
||||
@Override
|
||||
public ProductFormDTO getProductById(Long spuId) {
|
||||
// spu
|
||||
PmsSpu spu = this.getById(spuId);
|
||||
SpuDTO SpuDTO = new SpuDTO();
|
||||
BeanUtil.copyProperties(spu, SpuDTO);
|
||||
if (StrUtil.isNotBlank(spu.getPics())) {
|
||||
// spu专辑图片转换处理 json字符串 -> List
|
||||
List<String> pics = JSONUtil.toList(JSONUtil.parseArray(spu.getPics()), String.class);
|
||||
SpuDTO.setPics(pics);
|
||||
//1、一级本地缓存设置
|
||||
ProductFormDTO product = productLocalCache.get(PRODUCT_DETAIL_CACHE + spuId);
|
||||
if (null != product) {
|
||||
log.info("get LocalCache product:" + product);
|
||||
return product;
|
||||
}
|
||||
// 属性
|
||||
List<PmsSpuAttributeValue> attrs = iPmsSpuAttributeValueService.list(
|
||||
new LambdaQueryWrapper<PmsSpuAttributeValue>(
|
||||
).eq(PmsSpuAttributeValue::getSpuId, spuId)
|
||||
);
|
||||
//2、二级缓存设置,Redis中获取商品详情信息
|
||||
product = (ProductFormDTO) redisUtils.get(PRODUCT_DETAIL_CACHE + spuId);
|
||||
if (null != product) {
|
||||
log.info("get redis product:" + product);
|
||||
return product;
|
||||
}
|
||||
//3、分布式锁,保证原子操作
|
||||
RLock lock = redissonClient.getLock(LOCK_PRODUCT_DETAIL + spuId);
|
||||
try {
|
||||
if (lock.tryLock()) {
|
||||
// spu
|
||||
PmsSpu spu = this.getById(spuId);
|
||||
SpuDTO SpuDTO = new SpuDTO();
|
||||
BeanUtil.copyProperties(spu, SpuDTO);
|
||||
if (StrUtil.isNotBlank(spu.getPics())) {
|
||||
// spu专辑图片转换处理 json字符串 -> List
|
||||
List<String> pics = JSONUtil.toList(JSONUtil.parseArray(spu.getPics()), String.class);
|
||||
SpuDTO.setPics(pics);
|
||||
}
|
||||
// 属性
|
||||
List<PmsSpuAttributeValue> attrs = iPmsSpuAttributeValueService.list(
|
||||
new LambdaQueryWrapper<PmsSpuAttributeValue>(
|
||||
).eq(PmsSpuAttributeValue::getSpuId, spuId)
|
||||
);
|
||||
// 规格
|
||||
List<PmsSpec> specs = iPmsSpecService.listBySpuId(spuId);
|
||||
// sku
|
||||
List<PmsSku> skuList = iPmsSkuService.list(new LambdaQueryWrapper<PmsSku>().eq(PmsSku::getSpuId, spuId));
|
||||
|
||||
// 规格
|
||||
List<PmsSpec> specs = iPmsSpecService.listBySpuId(spuId);
|
||||
|
||||
// sku
|
||||
List<PmsSku> skuList = iPmsSkuService.list(new LambdaQueryWrapper<PmsSku>().eq(PmsSku::getSpuId, spuId));
|
||||
|
||||
ProductFormDTO product = new ProductFormDTO(SpuDTO, attrs, specs, skuList);
|
||||
product = new ProductFormDTO(SpuDTO, attrs, specs, skuList);
|
||||
//TODO 4、需要判断商品是否是秒杀商品,根据秒杀信息更新商品秒杀相关信息
|
||||
log.info("get db product:" + product);
|
||||
redisUtils.set(PRODUCT_DETAIL_CACHE + spuId, product, 3600);
|
||||
productLocalCache.setLocalCache(PRODUCT_DETAIL_CACHE + spuId,product);
|
||||
} else {
|
||||
log.info("get redis2 product:" + product);
|
||||
product = (ProductFormDTO) redisUtils.get(PRODUCT_DETAIL_CACHE + spuId);
|
||||
if (null!=product) {
|
||||
productLocalCache.setLocalCache(PRODUCT_DETAIL_CACHE + spuId, product);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (lock.isLocked()) {
|
||||
if (lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
return product;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user