缓存常用的3种读写策略(保证缓存与数据库的一致性)

3 种缓存读写策略各有优劣,不存在最佳,需要我们根据具体的业务场景选择更适合的。

旁路(Cache Aside Pattern)

平时使用比较多的一个缓存读写模式,比较适合读请求比较多的场景。

  1. 先更新 DB;
  2. 然后直接删除 cache 。

:

  1. 从 cache 中读取数据,读取到就直接返回;
  2. cache中读取不到的话,就从 DB 中读取数据返回;
  3. 再把数据放到 cache 中。

问题

在写数据的过程中,可以先删除 cache ,后更新 DB 么?

不行,可能会造成多线程读取的数据不一致,即数据库(DB)和缓存(Cache)数据不一致,

比如:

请求1先把cache中的A数据删除 -> 请求2从DB中读取数据->请求1再把DB中的A数据更新。

就和volatile一样,必须保证读之前的写入要对所有的线程可见。

在写数据的过程中,先更新DB,后删除cache就没有问题了么?

理论上可能会出现数据不一致,不过概率非常小,因为缓存的写入速度远快于数据库的写入速度。

出现不一致的情况,比如:

请求1从DB读数据A->请求2写更新数据 A 到数据库并把删除cache中的A数据->请求1将数据A写入cache。

缺陷

缺陷1:首次请求数据一定不在 cache 的问题

解决办法:可以将热点数据可以提前放入cache 中。

缺陷2:写操作比较频繁的话导致cache中的数据会被频繁被删除,这样会影响缓存命中率 。

解决办法:

数据库和缓存数据强一致场景 :更新DB的时候同样更新cache,不过我们需要加一个锁/分布式锁来保证更新cache的时候不存在线程安全问题。

可以短暂地允许数据库和缓存数据不一致的场景 :更新DB的时候同样更新cache,但是给缓存加一个比较短的过期时间,这样的话就可以保证即使数据不一致的话影响也比较小。

读写穿透(Read/Write Through Pattern)

"旁路" 之上进行了封装,

写(Write Through)

  1. 先查 cache,cache 中不存在,直接更新 DB。
  2. cache 中存在,则先更新 cache,然后 cache 服务自己更新 DB(同步更新 cache 和 DB)。

读(Read Through)

  1. 从 cache 中读取数据,读取到就直接返回 。
  2. 读取不到的话,先从 DB 加载,写入到 cache 后返回响应。

异步缓存写入(Write Behind Pattern)

"异步""读写穿透" 很相似,两者都是由 cache 服务来负责 cache 和 DB 的读写。

"读写穿透" 是同步更新 cache 和 DB,

"异步" 则是只更新缓存,不直接更新 DB,而是改为异步批量的方式来更新 DB。

Copyright © qgao 2021-* all right reserved,powered by Gitbook该文件修订时间: 2022-06-06 16:56:43

results matching ""

    No results matching ""