前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot整合Redis:Redis优化解决数据一致性问题

SpringBoot整合Redis:Redis优化解决数据一致性问题

作者头像
苏泽
发布2024-03-28 09:40:31
3050
发布2024-03-28 09:40:31
举报

本期我们重点讲一个后端的必考面试题 也是开发中常遇到的问题--数据一致性问题

上一期我们讲到了 SpringBoot如何结合Redis做一个缓存 实现我们减少对数据库压力的一个目的。还不知道怎么做的小伙伴可以先回顾一下前文http://t.csdnimg.cn/tshRD

下面正文

只要使用Redis缓存

就必然存在缓存和DB数据一致性问题。若数据不一致,则业务应用从缓存读取的数据就不是最新数据,可能导致严重错误。如将商品库存缓存在Redis,若价格不对,则下单时就可能出错,这是难以接受的。

什么是缓存和DB的数据一致性?

一致性包含如下情况:

  • 缓存有数据 缓存的数据值需和DB相同
  • 缓存无数据 DB是最新值

不符合这两种情况的,都属于缓存和DB数据不一致

所以 这里我们先讨论更新的策略 一共是这么几种情况

先删缓存 再更数据库 查缓存未命中则查询数据库 写入缓存 如下

该策略可能导致数据不一致的问题。例如,线程1更新数据前先删除缓存,这时候线程2查询该缓存,发现不存在,则去DB中获取,得到旧值放入缓存,然后线程1更新数据库。这时候就出现了缓存与数据库不一致的问题。
如图就导致了数据不一致 缓存是10 数据库却是20

所以就有另一种解决方案 先更新数据库 再删缓存

线程1更新了数据库,线程2也更新数据库,这时候由于某种原因,线程2首先更新了缓存,线程1后续更新。 这样就会导致了缓存脏数据的问题,因为目前数据库中存储的是线程2更新后的数据,而缓存存储的是线程1更新的旧数据。

如何解决?

延时双删

1、何为延时双删

延迟双删(Delay Double Delete)是一种在数据更新或删除时为了保证数据一致性而采取的策略。这种策略通常用于解决数据在缓存和数据库中不一致的问题。 具体来说,在某些场景下,我们需要先更新或删除数据库中的数据,然后再更新或删除缓存中的数据,以保证数据的一致性。

它的实现思路是

在删除缓存之后,让当前线程休眠一段时间,然后再次删除缓存。这个时间段是为了给数据库操作足够的时间来完成,确保数据已经持久化到数据库中。通过延迟双删,可以防止在休眠期间有其他线程读取到旧的缓存数据,从而保证数据的一致性。 值得注意的是,不管哪种方案,都避免不了Redis存在脏数据的问题,只能减轻这个问题,要想彻底解决,得要用到同步锁和对应的业务逻辑层面解决。

代码语言:javascript
复制
RedisUtils.del(key);// 先删除缓存
    updateDB(user);// 更新db中的数据
    Thread.sleep(N);// 延迟一段时间,在删除该缓存key
    RedisUtils.del(key);// 先删除缓存
需要注意的点

上述中(延迟N秒)的时间要大于一次写操作的时间。原因:如果延迟时间小于写入redis的时间,会导致请求1清除了缓存,但是请求2缓存还未写入的尴尬。。。

延迟的时间如何确定?

在业务程序运行时,统计业务逻辑执行读数据和写缓存的操作时间,以此为基础来进行估算。因为这个方案会在第一次删除缓存值后,延迟一段时间再次进行删除,所以称为“延迟双删”。

总结

把几种方案进行总结会得到这样的结论

  1. Cache-Aside(旁路缓存)
    • 应用程序直接与缓存和数据库对话。
    • 优点:适用于读多的应用场景,具有缓存失效弹性,可以直接访问数据库。
    • 缺点:可能导致缓存与数据库不一致。
  2. Read-Through Cache(读取穿透缓存)
    • 缓存与数据库保持一致,当缓存丢失时,从数据库加载数据并填充缓存。
    • 优点:适用于读量较大的工作负载,可以预热缓存。
    • 缺点:第一次请求数据时会导致缓存丢失,额外的数据加载成本。
  3. Write-Through Cache(写入穿透缓存)
    • 先将数据写入缓存,再写入数据库,保持缓存与数据库一致。
    • 优点:结合了读取穿透缓存的好处,提供数据一致性保证。
    • 缺点:引入额外的写延迟。
  4. Write-Around(写入绕过缓存)
    • 数据直接写入数据库,只有读取的数据才能进入缓存。
    • 优点:适用于只写一次、读取次数较少或从不读的情况。
    • 缺点:可能导致缓存未命中,读取性能较低。
  5. Write-Back(写入回写缓存)
    • 应用程序将数据写入缓存,缓存立即确认,并在延迟一段时间后写入数据库。
    • 优点:提高写性能,适用于写工作量大的工作负载,对混合工作负载有效。
    • 缺点:可能导致数据丢失,对数据库故障具有一定弹性。

根据具体的应用场景和需求,可以选择合适的缓存策略或结合多种策略来提高系统性能和数据一致性。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-03-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 本期我们重点讲一个后端的必考面试题 也是开发中常遇到的问题--数据一致性问题
  • 上一期我们讲到了 SpringBoot如何结合Redis做一个缓存 实现我们减少对数据库压力的一个目的。还不知道怎么做的小伙伴可以先回顾一下前文http://t.csdnimg.cn/tshRD
    • 下面正文
    • 只要使用Redis缓存
      • 就必然存在缓存和DB数据一致性问题。若数据不一致,则业务应用从缓存读取的数据就不是最新数据,可能导致严重错误。如将商品库存缓存在Redis,若价格不对,则下单时就可能出错,这是难以接受的。
      • 什么是缓存和DB的数据一致性?
      • 所以 这里我们先讨论更新的策略 一共是这么几种情况
        • 先删缓存 再更数据库 查缓存未命中则查询数据库 写入缓存 如下
          • 该策略可能导致数据不一致的问题。例如,线程1更新数据前先删除缓存,这时候线程2查询该缓存,发现不存在,则去DB中获取,得到旧值放入缓存,然后线程1更新数据库。这时候就出现了缓存与数据库不一致的问题。
        • 所以就有另一种解决方案 先更新数据库 再删缓存
          • 线程1更新了数据库,线程2也更新数据库,这时候由于某种原因,线程2首先更新了缓存,线程1后续更新。 这样就会导致了缓存脏数据的问题,因为目前数据库中存储的是线程2更新后的数据,而缓存存储的是线程1更新的旧数据。
      • 如何解决?
        • 延时双删
          • 1、何为延时双删
        • 它的实现思路是
          • 需要注意的点
          • 延迟的时间如何确定?
      • 总结
      相关产品与服务
      云数据库 Redis
      腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档