个人觉得引入缓存之后,如果为了短时间的不一致性问题,选择让系统设计变得更加复杂的话,完全没必要。
    下面单独对 Cache Aside Pattern(旁路缓存模式) 来聊聊。

    • 先更新 DB
    • 然后直接删除 cache 。

    简单画了一张图帮助大家理解写的步骤。
    image.png
    :

    • 从 cache 中读取数据,读取到就直接返回
    • cache中读取不到的话,就从 DB 中读取数据返回
    • 再把数据放到 cache 中。

    简单画了一张图帮助大家理解读的步骤。
    image.png

    如果更新数据库成功,而删除缓存这一步失败的情况的话,简单说两个解决方案:

    1. 缓存失效时间变短(不推荐,治标不治本) :我们让缓存数据的过期时间变短,这样的话缓存就会从数据库中加载数据。另外,这种解决办法对于先操作缓存后操作数据库的场景不适用。
    2. 增加 cache 更新重试机制(常用): 如果 cache 服务当前不可用导致缓存删除失败的话,我们就隔一段时间进行重试,重试次数可以自己定。如果多次重试还是失败的话,我们可以把当前更新失败的 key 存入队列中,等缓存服务可用之后,再将缓存中对应的 key 删除即可。具体来说,可以把要删除的缓存值或者是要更新的数据库值暂存到消息队列中(例如使用 Kafka 消息队列)。当应用没有能够成功地删除缓存值或者是更新数据库值时,可以从消息队列中重新读取这些值,然后再次进行删除或更新。如果能够成功地删除或更新,我们就要把这些值从消息队列中去除,以免重复操作,此时,我们也可以保证数据库和缓存的数据一致了。

    比如说面试官很可能会追问:“在写数据的过程中,可以先删除 cache ,后更新 DB 么?
    答案: 那肯定是不行的!因为这样可能会造成数据库(DB)和缓存(Cache)数据不一致的问题。为什么呢?比如说请求1 先写数据A,请求2随后读数据A的话就很有可能产生数据不一致性的问题。这个过程可以简单描述为:
    请求1先把cache中的A数据删除 -> 请求2从DB中读取数据->请求1再把DB中的A数据更新。
    当你这样回答之后,面试官可能会紧接着就追问:“在写数据的过程中,先更新DB,后删除cache就没有问题了么?
    答案: 理论上来说还是可能会出现数据不一致性的问题,不过概率非常小,因为缓存的写入速度是比数据库的写入速度快很多!如果追求强一致性,建议使用分布式锁。
    比如请求1先读数据 A,请求2随后写数据A,并且数据A不在缓存中的话也有可能产生数据不一致性的问题。这个过程可以简单描述为:
    请求1从DB读数据A->请求2写更新数据 A 到数据库并把删除cache中的A数据->请求1将数据A写入cache。
    现在我们再来分析一下 Cache Aside Pattern 的缺陷
    缺陷1:首次请求数据一定不在 cache 的问题
    解决办法:可以将热点数据可以提前放入cache 中。
    缺陷2:写操作比较频繁的话导致cache中的数据会被频繁被删除,这样会影响缓存命中率 。
    解决办法:

    • 数据库和缓存数据强一致场景 :更新DB的时候同样更新cache,不过我们需要加一个锁/分布式锁来保证更新cache的时候不存在线程安全问题。
    • 可以短暂地允许数据库和缓存数据不一致的场景 :更新DB的时候同样更新cache,但是给缓存加一个比较短的过期时间,这样的话就可以保证即使数据不一致的话影响也比较小。