//1:看从缓存中获取数据
//2:查看缓存中的数据条数是否和需求一样
//3:结果 分三种情况
//3.1 结果与需求一样 直接转换缓存中得到数据为指定的数据类型
//3.2 结果与需求不一样 取结果和缓存数据的差集 在数据库中查找并且存储入缓存当中
//3.3 结果与需求不一样 直接从数据库中查找,然后存储入缓存中
public List<SimpleGoodsInfo> getSimpleGoodsInfoByTableId(TableId tableId) {
//获取商品简单信息,可以从redis中获取,拿不到的需要从db中获取,并且保留到db中
List<Object> goodsIds=tableId.getIds()
.stream()
.map(i->i.getId().toString())
.collect(Collectors.toList());
// FIXME 如果redis中获取不到数据,返回的是[null,null]
List<Object> cacheSimpleGoodsInfo=redisTemplate.opsForHash()
.multiGet(GoodsConstant.ECOMMERCE_GOODS_DICT_KEY,goodsIds)
.stream()
.filter(Objects::isNull)
.collect(Collectors.toList());
//如果从redis获取到信息,分两种情况去操作
if(CollectionUtils.isNotEmpty(cacheSimpleGoodsInfo)) {
//1:如果从缓存中已经获取到所需的SimpleGoodsInfo
if(cacheSimpleGoodsInfo.size()==goodsIds.size()) {
log.info("get simple goods info by ids(from redis):
[{}]",JSON.toJSONString(cacheSimpleGoodsInfo));
return parseCacheGoodsInfo(cacheSimpleGoodsInfo);
}else {
//2:需要从DB(right)和redis(left)中获取
List<SimpleGoodsInfo> left=parseCacheGoodsInfo(cacheSimpleGoodsInfo);
//取差集,传递的参数-查询到的参数
Collection<Long> subtractIds=CollectionUtils.subtract(
goodsIds.stream()
.map(g->Long.valueOf(g.toString()))
.collect(Collectors.toList()),
left.stream().map(SimpleGoodsInfo::getId)
.collect(Collectors.toList())
);
//缓存中不存在的去查询数据表,并且缓存
List<SimpleGoodsInfo> right=queryGoodsFromDBAndCacheToRedis(
new TableId(subtractIds.stream()
.map(TableId.Id::new).collect(Collectors.toList()))
);
//合并left 和right 并且返回
log.info("get simple goods info by ids(from db and cache):
[{}]",JSON.toJSONString(subtractIds));
return new ArrayList<>(CollectionUtils.union(left,right));
}
} else {
//从redis什么都查询不到
return queryGoodsFromDBAndCacheToRedis(tableId);
}
}
/**
* 从数据表中获取数据,并且缓存到java对象中
* @param tableId
* @return
*/
private List<SimpleGoodsInfo> queryGoodsFromDBAndCacheToRedis(TableId tableId)
{
List<Long> ids=tableId.getIds()
.stream()
.map(TableId.Id::getId)
.collect(Collectors.toList());
log.info("get simple goods info by ids(from db):[{}]",JSON.toJSONString(ids));
List<EcommerceGoods> ecommerceGoods=IterableUtils.toList(ecommerceGoodsDao.findAllById(ids));
List<SimpleGoodsInfo> simpleGoodsInfos = ecommerceGoods.stream().map(EcommerceGoods::toSimple)
.collect(Collectors.toList());
//将结果缓存,下次直接从redis中获取
log.info("cache goods info:[{}]",JSON.toJSONString(ids));
Map<String,String> id2JsonObject
=new HashMap<>(simpleGoodsInfos.size());
simpleGoodsInfos.forEach(simpleGoodsInfo ->
id2JsonObject.put(simpleGoodsInfo.getId().toString(),simpleGoodsInfo.toString()));
redisTemplate
.opsForHash().putAll(GoodsConstant.ECOMMERCE_GOODS_DICT_KEY,id2JsonObject);
return simpleGoodsInfos;
}
/**
* 将缓存中的数据反序列化为java数据类型数据
* @param cacheSimpleGoodsInfo
* @return
*/
private List<SimpleGoodsInfo> parseCacheGoodsInfo(List<Object> cacheSimpleGoodsInfo)
{
return cacheSimpleGoodsInfo.stream()
.map(s->JSON.parseObject(s.toString(),SimpleGoodsInfo.class))
.collect(Collectors.toList());
}
redis处理缓存和数据库层之间的处理
于 2022-10-13 13:31:33 首次发布