更新策略 缓存更新是Redis为了节约内存而设计出来的机制,当我们向Redis插入太多数据时就会导致缓存中的数据过多,所以Redis会对部分数据进行更新即淘汰
低一致性需求(数据长久不发生变化): 使用内存淘汰机制,例如店铺类型信息的查询缓存,因为这部分数据很长一段时间都不需要更新高一致性需求: 使用主动更新机制,写入缓存的时候需要设置超时时间,例如店铺详情查询的缓存
主动更新实现主动更新策略一般有如下几种方案

人工编码的三大问题更新数据库后,删除缓存还是更新缓存?
如何保证缓存与数据库的操作的同时成功或失败?
先操作缓存还是先操作数据库?
删除缓存的操作很快,更新数据库的操作相对较慢, 所以先操作数据库再删除缓存出现线程安全问题的概率相对较低
实现商铺缓存与数据库一致根据店铺Id查询店铺时如果缓存未命中则查询数据库,将查询到的店铺信息写入Redis的同时设置缓存的超时时间
public static final Long CACHE_SHOP_TTL = 30L;
@Override
public Result queryById(Long id) {
// 先从Redis中查询对应的店铺缓存,这里的常量值是固定的前缀+店铺id
String shopJson = stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY + id);
// 如果在Redis中查询到了店铺信息(String类型的JSON字符串)则转为Shop类型直接返回
if (StrUtil.isNotBlank(shopJson)) {
Shop shop = JSONUtil.toBean(shopJson, Shop.class);
return Result.ok(shop);
}
// 在Redis中没查询到对应的店铺缓存信息则根据店铺Id去数据库中查询店铺信息
Shop shop = getById(id);
// 在数据库中也查不到就返回一个错误信息或者返回空(根据业务需求)
if (shop == null){
return Result.fail("店铺不存在!!");
}
// 在数据库中查到了店铺信息,则将shop对象转为json字符串存入redis同时设置缓存的超时时间(如30分钟)
String jsonStr = JSONUtil.toJsonStr(shop);
stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, jsonStr,CACHE_SHOP_TTL, TimeUnit.MINUTES);
// 最终把查询到的店铺信息返回给前端
return Result.ok(shop);
}
根据店铺Id修改店铺时先修改数据库再删除缓存来解决双写问题,更新和删除通过事务去控制, 业务逻辑我们依旧是写在Service层的实现类中
// 更新商铺信息
@PutMapping
public Result updateShop(@RequestBody Shop shop) {
// 直接将请求体中JSON格式的店铺信息写入数据库,这样在缓存有效期内,即使数据库中的店铺信息修改了,下次获取的还是之前缓存中的店铺信息
shopService.updateById(shop);
return Result.ok();
}
// 更新商铺信息
@PutMapping
public Result updateShop(@RequestBody Shop shop) {
// 先将请求体中JSON格式的店铺信息写入数据库,再删除缓存,保证缓存中的店铺信息和数据库中的店铺信息一致性
return shopService.update(shop);
}
public interface IShopService extends IService<Shop> {
Result update(Shop shop);
}
@Override
@Transactional
public Result update(Shop shop) {
// 首先先判一下店铺Id是否为空
if (shop.getId() == null){
return Result.fail("店铺id不能为空!!");
}
// 先修改数据库中对应的店铺信息
updateById(shop);
// 再将Redis中对应店铺的缓存删除
stringRedisTemplate.delete(CACHE_SHOP_KEY + shop.getId());
return Result.ok();
}
重启服务器进行测试,如访问餐厅时会将该餐厅的数据缓存到Redis中,然后使用POSTMAN携带JSON数据发送PUT请求http://localhost:8080/api/shop/更新餐厅信息
{
"area": "大关",
"openHours": "10:00-22:00",
"sold": 4215,
"address": "金华路锦昌文华苑29号",
"comments": 3035,
"avgPrice": 80,
"score": 37,
"name": "yunqing茶餐厅",
"typeId": 1,
"id": 1
}