缓存更新 套路

  1. 不是软件架构里的 mysql 数据库和 memcache/redis 的更新策略。
  2. 是计算机体系结构里的设计: CPU缓存,硬盘文件系统的缓存,硬盘的缓存,数据库中的缓存 等等

涉及 查询, 更新 两条路

  1. 1、错误
  2. 查询: 先查,如果缓存中没有,读数据库, 然后数据放入缓存
  3. 更新: 先删 缓存, 然后更新数据库。
  4. 问题:
  5. 查询,更新,并发操作, 如果 更新操作先删缓存, 然后查询没有命中缓存,读取了数据旧数据,然后放入缓存。 导致了缓存中的脏数据

更新缓存的 设计模式

四种: Cache aside, Read through, Write through, Write behind caching

Cache Aside Pattern

  1. 最常用, 具体逻辑:
  2. 查询:
  3. 失效: cache 读取数据,没命中, 从数据库中读取数据,成功后,放到缓存中。
  4. 命中: cache 读取数据, 读到就返回
  5. 更新:
  6. 先把数据放入 数据库中, 成功后,再让缓存失效
  7. 注意点: 更新操作, 不能放入数据库, 然后更新缓存。 两个并发的写操作 导致脏数据
  8. 这种模式也有可能出现问题:
  9. 先读取 cache中没有的数据,即先查询,并且没命中数据,然后从数据库中读取了旧数据,
  10. 然后更新操作,更新了数据库,让缓存失效。
  11. 最后查询操作把旧数据 放入了缓存中。 同样产生了 脏数据
  12. 这个case 理论上会出现。 实际上,出现的概率非常非常低。 因为这个条件需要发生在读缓存时缓存失效,而且并发着有一个写操作。而实际上数据库的写操作会比读操作慢得多,而且还要锁表,而读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存,所有的这些条件都具备的概率基本并不大。

Read/Write Through Pattern

  1. 上面的设计模式, 应用代码需要维护两个数据存储。 缓存cache,数据库repository
  2. 该设计模式的套路:
  3. 把更新数据库的操作 由缓存自己代理。 所以对于应用层来说, 后端就是一个单一的存储,存储自己维护自己的cache

read through

  1. 在查询中更新缓存。
  2. 即当缓存失效的时候(过期或LRU换出),cache Aside 模式是调用方负责把数据加载入缓存
  3. read through 缓存服务自己进行加载,对应用方透明

write through

  1. 更新数据时发生
  2. 当有数据更新时, 如果没有命中缓存,直接更新数据库,然后返回
  3. 如果命中了,则更新缓存, 然后由cache 自己去更新数据库 (同步操作)

Write Behind Caching Pattern

  1. 又叫 write back linux文件系统的page cache的算法就是 write back
  2. 套路: 更新数据的时候只更新缓存,之后再让缓存异步的批量更新进数据库
  3. 优点: 数据的I/O 操作快。 因为异步,还可以合并对同一个数据的多次操作,性能提升高。
  4. 缺点: 数据不是强一致性。 可能会丢失,系统非正常退出缓存丢失。