缓存读写模式
一. Cache Aside (旁路缓存)
-
读操作
客户端优先读取 Cache,如果 Cache miss,则 读取 DB,并且将读取到的数据回落到 Cache 中。
-
写操作
由客户端先更新 DB ,然后直接将 key 从 Cache 中删除,由 DB 来驱动缓存数据的更新。
-
特点
这种模式的特点是,由客户端处理所有数据访问细节,同时利用 Lazy 计算的思想,更新 DB 后,直接删除 Cache 并通过 DB 更新,确保数据以 DB 结果为准,可以大幅降低 Cache 和 DB 中数据不一致的概率。
-
适用场景
- 缓存数据的计算逻辑比较复杂。
- 对数据一致性要求较高。
- 数据变更不频繁,没有超大并发的热点 key。
-
优化点
可以借助一个 Trigger 服务,实时监听 DB 中数据的变更(如监听 MySQL binlog),同时更新 Cache 中的数据。在客户端读取 Cache 时,如果Trigger 还没写入,则由调用方自行到 DB 加载计算并写入 Cache。
-
存在的问题
由于更新操作会删除缓存中的数据,所以如果存在某些热点 key 被删除,则会导致瞬时大量请求穿透到 DB,对 DB 造成很大的压力。
二. Read/Write Through(读写穿透)
上面的 Cache Aside 下,业务应用需要同时维护 Cache 和 DB 两个数据存储方,过于繁琐,于是就有了 Read/Write Through 模式。在这种模式下,业务应用只关注一个存储服务即可,业务方的读写 Cache 和 DB 的操作,都由存储服务代理。
-
读操作
同 Cache Aside 。
-
写操作
存储服务首先查 Cache,如果数据在 Cache 中不存在,则只更新 DB;如果数据在 Cache 中存在,则先更新 Cache,然后更新 DB。
-
特点
- 存储服务封装了所有的数据处理细节,业务应用端代码只用关注业务逻辑本身,系统的隔离性更佳;
- 进行写操作时,如果 Cache 中没有数据则不更新,有缓存数据才更新,内存效率更高。
三. Write Behind Caching(异步缓存写入)
Write Behind Caching 模式与 Read/Write Through 模式类似,也由数据存储服务来管理 cache 和 DB 的读写。不同点是,数据更新时,Read/write Through 是同步更新 cache 和 DB,而 Write Behind Caching 则是只更新缓存,不直接更新 DB,而是改为异步批量的方式来更新 DB。
-
特点
数据存储的写性能最高,非常适合一些变更特别频繁的业务,特别是可以合并写请求的业务。
-
优化点
可以将多个写请求 merge 成一个进行处理。比如对一些计数业务,一条短视频被点赞 1万次,如果连续更新 1万次 DB 代价很大,而合并成一次请求直接加 1万,则是一个非常轻量的操作。
-
存在的问题
这种模式下,数据的一致性变差,甚至在一些极端场景下可能会丢失数据。比如系统 Crash、机器宕机时,如果有数据还没保存到 DB,则会存在丢失的风险。
-
适用场景
- 对数据一致性要求不高。
- 更新操作比较频繁。