Redis缓存策略之缓存和数据库的一致性

一、缓存更新策略

       当数据在后端存储中发生变化时,需要更新Redis缓存以确保缓存中的数据与后端存储保持一致。以下是常见的缓存更新策略:

(1)主动更新: 在数据发生变化时,应用程序主动通知Redis更新缓存。这可以通过发布订阅机制、消息队列等方式实现。主动更新确保缓存数据及时更新,但增加了系统的复杂性。

(2)定时刷新: 周期性地刷新缓存,无论数据是否发生变化。虽然能够保持一定的实时性,但可能会导致不必要的缓存刷新,增加了系统负担。

(3)Lazy Load(懒加载): 在缓存失效时,不立即更新,而是等到下一次访问时再重新加载最新数据。这样可以避免在高并发情况下频繁地刷新缓存,但可能导致部分用户看到的是旧数据。

二、缓存失效策略 

       缓存中的数据可能因为多种原因失效,例如数据过期、被手动删除等。以下是缓存失效策略的常见选择:

(1)TTL(Time-To-Live): 为缓存设置过期时间,超过该时间则自动失效。Redis中使用EXPIRE命令或在存储数据时设置过期时间实现。

(2)LRU(Least Recently Used): 根据最近使用的数据来淘汰。当缓存空间不足时,会优先淘汰最近最少使用的数据。

(3)LFU(Least Frequently Used): 根据数据的访问频率来淘汰。使用一个计数器来记录数据被访问的次数,淘汰访问频率最低的数据。

(4)手动失效: 当数据发生变化时,通过程序手动删除缓存,强制缓存失效。

对于静态数据,可以采用TTL策略;对于动态数据,可以考虑LRU或LFU策略。

三、案例分析 

        当数据更新时,保证数据库和缓存的一致性,会遇到是先删除缓存,再操作数据库还是先操作数据库,再删除缓存的问题。这两种方案各有优缺点。

(1)先删除缓存,再操作数据库:

①优势:

通过先删除缓存再操作数据库,确保了在并发情况下,不会查询到过期或失效的缓存数据,从而保持了强一致性。

②劣势:

并发操作: 在极端情况下,如果线程一想更新数据库,线程一先删除缓存,而另一个线程而在此之后查询缓存,没有命中,于是查询数据库,并将以前删除的数据再次存入缓存。然而这时线程一还未更新完数据,这就造成了数据的不一致性。

(2)先操作数据库,再删除缓存:

①优势:

先执行数据库操作,可以减少缓存删除的频率,提高性能,特别是在高并发情况下,减少了对缓存的频繁写入。还能保证事务一致性,如果数据库操作失败,可以避免删除缓存,确保事务一致性。

②劣势:

小概率的情况下,比如在线程一,查缓存时刚好没有数据,于是到数据库查到了数据,在此之后,又有一个线程二在更新数据,它先更新数据库就删除缓存,此时缓存数据依然没有,线程二删完缓存后,线程一写入缓存,线程一写入的是以前的数据,而线程二更新了数据,导致了不一致性,但是这种情况概率很低,线程一在查询数据库到写入缓存所用时间是非常小的,很难在穿插于另一个进程的更新操作。
综上,先操作数据库,再删除缓存效果会更好一些。

先操作数据库,再删除缓存源代码如下:(以黑马点评项目为例)

@Override
@Transactional
public Result update(Shop shop) {
    Long id = shop.getId();
    if(id==null){
        return Result.fail("店铺id不能为空");
    }

    //1.更新数据库
    updateById(shop);
    //2.删除缓存
    stringRedisTemplate.delete(CACHE_SHOP_KEY+id);
    return Result.ok();
}

       在进入更新操作之前,首先检查店铺对象中的ID是否为空。如果ID为空,表示店铺ID无效,此时返回一个包含错误信息的失败结果。

       然后更新数据库,调用 updateById(shop) 方法来更新数据库中的店铺信息。这里使用的是MyBatis框架提供的 updateById 方法,该方法用于根据主键ID更新数据库中的记录。

       最后删除缓存,使用名为stringRedisTemplate操作String类型数据的Redis模板删除缓存中的相关店铺数据。这里使用了CACHE_SHOP_KEY +id作为缓存的键,CACHE_SHOP_KEY 是一个常量,为cache:shop,用于标识店铺缓存的前缀。通过删除缓存,确保下一次查询店铺信息时,可以从数据库中重新加载最新的数据到缓存中。

        如图,使用PostMan测试工具,通过PUT来更新数据,将name由原先的103茶餐厅修改为106茶餐厅。如图19,响应为200OK,说明PUT成功更新数据。 

 

如图,查看控制台,可以看到调用了代码中的update方法,name改为了106茶餐厅。

 如下图,实现了先更新数据库,再删除缓存。

 

  • 19
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无所谓_我会出丑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值