目录
一、添加redis缓存的主要逻辑
二、代码
三、结果
四、缓存更新策略
五、代码
一、添加redis缓存的主要逻辑
在未添加缓存时,前端向后端发起查询请求时,后端收到请求就直接查数据库,它的速度如下:
其实速度也不慢,那是因为我的数据库里面没有太多数据,所以查起来速度还是特别快的,但随着我们的数据库数据量逐渐增大,如果没有缓存的话,那查询速度会越来越慢。
添加redis缓存的逻辑也不难,总结下来也就是以下这几点:
1.后端查询时,先查redis缓存,redis缓存中有数据直接返回,没有数据再去查数据库
2.查数据库时,没有对应数据则向前端发出错误信息,有数据则向前端发送数据并将数据写入redis缓存中
流程图如下所示:
二、代码
@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {@Autowiredprivate StringRedisTemplate stringRedisTemplate;/*** 根据id查询店铺信息* @param id* @return*/@Overridepublic Result queryById(Long id) {String key = RedisConstants.CACHE_SHOP_KEY + id;//1.从redis中查询商铺缓存信息String shopJson = stringRedisTemplate.opsForValue().get(key);//2、判断是否存在if (StrUtil.isNotBlank(shopJson)) {//3、存在,直接返回Shop shop = JSONUtil.toBean(shopJson, Shop.class);return Result.ok(shop);}//4、不存在,根据id查询数据库Shop shop = getById(id);//5、判断数据库中是否有数据if (shop == null) {//6、没有,返回错误return Result.fail("店铺不存在");}//7、有数据,返回,并将数据写入redisString jsonStr = JSONUtil.toJsonStr(shop);stringRedisTemplate.opsForValue().set(key,jsonStr);//8、返回结果return Result.ok(shop);}
}
三、结果
当第一次执行时,redis中是没有数据的,执行过后就会将对应数据写入redis中
下一次的查询时速度就会快上不少
如果数据库中的数据更多的话,效果会更加明显
四、缓存更新策略
既然我们已经对查询业务增加了缓存,那当数据库的数据和缓存数据不一样的时候,我们如何去解决它们之间的一致性问题呢?
其实解决方案十分简单:
当数据库的数据发生变更时,例如增加、删除、修改等操作,我们先去操作数据库再去删除缓存。
为什么选择删除缓存而不选择更新缓存呢?
如果选择更新缓存很可能会出现多次无效的写操作,比如:我更新了十次数据库之后才有一次查询操作,这时候缓存也是随之更新了十次。那如果我在他第一次更新数据库的时候就选择删除缓存,那么我就省去了这些更新缓存的无效写操作,性能上肯定是提高了不少。因此我们会选择删除缓存而不是更新缓存。
为什么要选择先操作数据库而不是先操作缓存呢?
因为数据库是基于磁盘的,缓存是基于内存的,操作数据库的耗时往往会比操作缓存的耗时大上不少。因此如果先删缓存再更新数据库,那就会出现在更新数据库的过程中(时间比较长)被其他查询缓存的操作乘虚而入,这时候缓存为空会从数据库中拿数据填入缓存,这时候就会出现数据不一致的问题。因此我们会选择先操作数据库再操作缓存。
因此我们还要给上面写的代码进行补全,在对数据进行修改的时候要进行以下的逻辑:
1.更新数据库
2.删除缓存
五、代码
@Override@Transactionalpublic Result update(Shop shop) {Long id = shop.getId();if (id == null) {return Result.fail("店铺id不能为空");}//1.更新数据库updateById(shop);//2.删除缓存stringRedisTemplate.delete(RedisConstants.CACHE_SHOP_KEY + id);//3.返回结果return Result.ok();}