打破困局:数据库与缓存不一致问题全解析

农民  论坛元老 | 2025-5-10 13:32:39 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1710|帖子 1710|积分 5130

数据库和缓存不一致性的问题,怎样办理?

答复



  • 为了包管 Redis 和 数据库 的一致性,肯定要缓存和数据库双写
  • 业内常见的 3 种方案:

    • 先更新数据库,再删除缓存
    • 延迟双删
                 先删除缓存,
            再更新数据库,
            再删除一次缓存
    • cache-aside
                 更新数据库,基于 bin log 监听进行缓存删除

扩展

1、为什么要删缓存,而不是更新?



  • 优先选择删除缓存,而不是更新缓存。
  • 更新缓存的动作,相比于直接删除缓存。操作过程比力的复杂,而且,也轻易堕落
           更新缓存的例子:当我们需要通过缓存进行扣减库存的时候。

    • 你可能需要从缓存中查出整个订单模型数据,
    • 把他进行反序列化之后,再解析出其中的库存字段,
    • 把他修改掉,然后再序列化,
    • 末了,再更新到缓存中可以看到
       
  • 缓存删除 带来的一个小问题
           缓存删除会带来一次 cache miss
        这种 cache miss 在某种程度上,可能会导致缓存击穿
        通过加锁的方式,比力方便的办理缓存击穿的问题的。
2、先写数据库,照旧先删缓存?


  • 先删缓存,再写数据库

    • 长处:先删除缓存乐成了,但是,第二步更新数据库失败了,这种情况是可以接受的。
    • 缺点:这种方式,会无形中放大 “读写并发”,导致的数据不一致的问题。
                 对于一个读线程来说,虽然,不会写数据库,但是,会更新缓存的。
            数据不一致的问题,示例:
            假如一个读线程,在读缓存的时候没查到值,他就会去数据库中查询。
            假如,在查询到结果之后,更新缓存之前,数据库被更新了。
            但是,这个读线程是完全不知道的。
            那么,就导致终极缓存会被重新用一个“旧值”覆盖掉。
            这样,就导致了缓存和数据库的不一致的现象

  • 先写数据库,再删缓存

    • 利益1:缓存删除失败的概率照旧比力低的。
    • 利益2:数据库是作为持久层存储的。先更新数据库,就可以包管数据的可靠性和一致性。
    • 问题:先写数据库,后删除缓存,假如,第二步失败了。会导致数据库中的数据已经更新,缓存照旧旧数据。终极,导致数据不一致。

  • 延迟双删

    • 参考: 延迟双删?

3、怎样选择?


  • 业务量不大,并发不高的情况,可以选择**“先更新数据库,后删除缓存”**的方式,因为,这种方案更加简单。
           先操作数据库,后操作缓存。是一种比力范例的计划模式一 Cache Aside Pattern
        这种模式的主要方案就是,先写数据库,后删缓存。而且,缓存的删除是可以在旁路异步实行的。
        这种模式的长处,他可以办理 “写写并发“导致的数据不一致问题,并且,可以大大降低“读写并发”的问题。
        所以,这也是Facebook比力推崇的一种模式。
  • 业务量比力大,并发度很高的话,那么发起选择 “先删除缓存,再更数据库”。因为,这种方式在引入延退双删、分布式锁等机制,会使得整个方案会更加趋近于完美,带来的并发问题更少。当然,也会更复杂
4、方案再优化



  • Cache Aside Pattern 这种模式中,我们可以异步的在旁路处置惩罚缓存。
  • 实现方式:借助数据库的 bin log 大概 基于异步消息订阅的方式。

    • 先操作数据库,数据库操作完,发一个异步消息出来。
    • 然后,再由一个监听者在接到消息之后,异步的把缓存中的数据删撤除。
    • 大概,借助数据库的 binlog,订阅到数据库变更之后,异步的扫除缓存。




  • 再完美一点(按现实情况评估,是否需要此方案)

    • 先删缓存
    • 再更新数据
    • 再监听binlog删除缓存

5、缓存更新的计划模式


  • Read/Write Through Pattern

    • Read Through 模式
                 是由缓存配置一个读模块,它知道怎样将数据库中的数据写入缓存。
            在数据被哀求的时候,假如未命中,则将数据从数据库载入缓存。
    • Write Through 模式
                 缓存配置一个写模块,它知道怎样将数据写入数据库。
            当应用要写入数据时,缓存会先存储数据,并调用写模块将数据写入数据库
    • 这两种模式下,不需要应用本身去操作数据库,缓存本身就把活干完了。

  • Write Behind Caching Pattern

    • 在更新数据的时候,只更新缓存,而不更新数据库。然后,再异步的定时的,把缓存中的数据持久化到数据库中。
    • 长处/缺点:读写速率都很快,但是,会造成一定的数据丢失。
    • 得当场景:可以用在比如:统计文章的访问量、点赞等场景中。答应数据少量丢失,但是,速率要快。

6、没有银弹


  • 任何的技能方案,都是一个权衡的过程。
  • 没有一个“完美”的方案,只有“符合”的方案。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农民

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表