根据试题ID从缓存查询的时候,为了防止缓存穿透,会将不存在的试题查询ID,放到Redis缓存起来。项目实例:
List<String>cacheKeys=new ArrayList<>();
List<String>notExistValidateKey=new ArrayList<>();
for(String queId:queIds){
// 正常的缓存
cacheKeys.add(RedisConstants.QUESTION_RELATION_CACHE_KEY+queId);
// 不存在的试题id,防止缓存穿透
notExistValidateKey.add(RedisConstants.NOT_EXIST_QUESTION_CACHE_KEY+queId);
}
// 从缓存中查询出不存在的试题
List<String>notExistQueIds=redisService.batchGetObject(notExistValidateKey,String.class);
if(CollectionUtils.isNotEmpty(notExistQueIds)){
// 正常试题ID集合中把这些不存在的过滤掉
queIds.removeAll(notExistQueIds);
cacheKeys.removeAll(getNotExistKeysByNotExistQueIds(notExistQueIds));
if(CollectionUtils.isEmpty(queIds)){
return null;
}
}
// ....
// 保存不存在的试题
saveNotExistRelation(queIds,relations);
/**
* @description: 保存不存在的试题
*/
private void saveNotExistRelation(List<String>queIds,List<QuestionSplitRelation>existRelation){
if(new HashSet<>(queIds).size() <= existRelation.size()){
return;
}
List<String>notExistQueIds=new ArrayList<>();
if(CollectionUtils.isEmpty(existRelation)){
notExistQueIds.addAll(queIds);
}else{
notExistQueIds=(List)CollectionUtils.subtract(queIds,ListUtils.fetchFieldValue(existRelation,"queId"));
}
Map<String,Object>caches=new HashMap<>();
for(String rel:notExistQueIds){
caches.put(RedisConstants.NOT_EXIST_QUESTION_CACHE_KEY+rel,rel);
}
// 目前缓存仅保存10秒,后期加入 binlog 同步则可适当增加时间
redisService.batchSetObject(caches,10);
}