黑马点评商铺类型缓存练习

需求描述

给商铺类型业务添加缓存,注意此时商户类型的数据是list集合类型。

代码实现

ShopTypeController

1
2
3
4
5
6
7
8
9
10
11
@RestController
@RequestMapping("/shop-type")
public class ShopTypeController {
@Resource
private IShopTypeService typeService;

@GetMapping("list")
public Result queryTypeList() {
return typeService.queryType();
}
}

调用typeService的queryType()接口进行商户类型的查询。

IShopTypeService

1
2
3
public interface IShopTypeService extends IService<ShopType> {
Result queryType();
}

在此接口层定义查询接口。

ShopTypeServiceImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Service
public class ShopTypeServiceImpl extends ServiceImpl<ShopTypeMapper, ShopType> implements IShopTypeService {
@Resource
private StringRedisTemplate stringRedisTemplate;

public Result queryType() {
String key = CACHE_TYPE_LIST;
//从redis中查询类型缓存
String typeJson = stringRedisTemplate.opsForValue().get(key);
//如果缓存不为空,直接返回
if (StrUtil.isNotBlank(typeJson)) {
List<ShopType> shopTypeList = JSONUtil.toList(typeJson, ShopType.class);
return Result.ok(shopTypeList);
}
//为空,查询
List<ShopType> shopTypeList = query().orderByAsc("sort").list();
//将数据库信息保存到缓存
stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shopTypeList));
return Result.ok(shopTypeList);
}
}

在实现层利用redis进行缓存,逻辑为:先查询如果不为空则直接返回,若为空则进行查询并将结果保存到List的数据类型中,最后将其存到redis中。

实现效果

image-20240908185510717

如图所示,成功在redis中进行了商铺列表信息的缓存。

后续优化

缓存一致性问题:由于该数据在业务中不轻易改动,因此设置一个TTL即可。

缓存一致更新策略的最佳实践方案:

  • 低一致性需求:使用Redis自带的内存淘汰机制
  • 高一致性需求:主动更新,并以超时剔除作为兜底方案
    • 读操作:缓存命中直接返回;未命中则查询数据库并写入缓存设定超时时间
    • 写操作:先写数据库再删除缓存;确保数据库和缓存操作的原子性

缓存击穿问题:目前的想法是利用数据库往redis里面添加null值实现。