• 数据一致性


    四种常用的解决方案

    方案一:Cache Aside Pattern

      读请求

    1. 先读缓存再读库
    2. 如果缓存命中,返回数据
    3. 如果缓存未命中,读库并把数据写入缓存,然后再返回

      写请求

    1. 数据写库
    2. 删除缓存

      这里很重要的一点在写请求中,要删除缓存而不是更新缓存。缓存的更新会发生在下一次读请求时。这里为什么会选择删除缓存,而没有更新缓存呢。因为如果更新缓存的话,存在并发写操作时,无法保证多个进程的执行顺序,有可能旧数据会覆盖新数据。 Cache Aside Pattern方案虽然使用范围比较广,但它本身也存在一些问题。

      问题一

      如上图,进程A在T1时刻数据写入库中,T2时刻删除了缓存。在高并发场景下,T1和T2时刻之间的读请求从缓存中读到的数据和库中的数据会出现不一致。

      问题二

      如上图,进程A在T1时刻把数据写入库中,T2时刻删除缓存失败。失败的原因暂不详谈。这种情况下会导致库和缓存数据长时间不一致。

      问题三

      如上图,进程A是读请求,进程B是写请求。

    1. 进程A读缓存未命中,然后从库中读到值A;
    2. 此时进程A可能因为某种原因发生了进程切换。
    3. 进程B执行写库,把值B写入库中;
    4. 进程B删除缓存。
    5. 进程A排队完成继续执行,把值A写入缓存。

      此时库中数据是B,缓存中是A,出现了数据不一致。

    方案二:Double delete方法

      方案二是在方案一的基础上发展而来的。  

      读请求

      同方案一

      写请求

    1. 删除缓存
    2. 数据写库,返回写入成功
    3. 睡眠一段时间(通常是几百ms、也可以是一定时间范围内的随机值,根据具体业务场景决定)
    4. 删除缓存 

      此方案的写请求,与Cache Aside Pattern方法相比,最前面多了一次删除缓存,这样就可以避免T1~T2时间差的数据不一致。在最后删除缓存前有一个短暂的等待,这样就避免了方案一中的问题三:防止因为上下文切换等原因导致的数据不一致问题。

    方案三:基于分布式锁的方案

      读请求

    1. 先读缓存再读库
    2. 如果缓存命中,返回数据
    3. 如果缓存未命中,取锁(可重试多次)
    4. 取锁成功,读库并把数据写入缓存
    5. 释放锁

      写请求

    1. 取锁
    2. 取锁成功后,数据写库
    3. 删除缓存
    4. 释放锁

      加锁之后,数据一致性能得到很好的保证,但是数据的访问效率会受到较大的影响。所以,很多时候加锁未必是理想方案。不过在写少、读多的业务场景中也可以考虑。

    方案四:基于Binlog订阅方式,删除缓存

      读请求

    1. 先读缓存再读库
    2. 如果缓存命中,返回数据
    3. 如果缓存未命中,读库并把数据写入缓存,然后再返回

      写请求

      只写数据库

      对于缓存的更新,我们采用订阅数据库日志的方式实现。比如采用阿里开源的Canal,订阅MySQL的Binlog,然后放入MQ,消费端消费数据,然后把数据和缓存中的数据进行比较,把不一致的数据从缓存中删除。删除失败可以尝试多次删除。这种方案,可以把缓存删除逻辑从业务代码中剥离,业务开发专注于业务;但是需要引入额外的组件,花费更高的维护成本。

    总结

      以上是处理库和缓存数据一致性问题的常用方案。他们都有一个共同点删除缓存,而不是更新缓存。不管是哪一种方案,都很难做到库和缓存数据完全一致。所以在各方案中,都可以加异步的对账逻辑,定期检查库和缓存中的数据是否一致,出现不一致时,删除缓存数据即可。

    链接:https://juejin.cn/post/6992576951470800932

  • 相关阅读:
    structs2---OGNL表达式
    六种获取配置properties文件的方法
    java poi导出Excel 总结
    Linux中发布项目的一些命令笔记
    JavaScript 闭包
    常见数据库连接方式
    Docker(五):镜像
    Docker(四):docker的安装
    Ubuntu命令
    Docker(三):Docker的基本概念
  • 原文地址:https://www.cnblogs.com/linguoguo/p/15941929.html
Copyright © 2020-2023  润新知