缓存更新 套路
不是软件架构里的 mysql 数据库和 memcache/redis 的更新策略。是计算机体系结构里的设计: 如 CPU缓存,硬盘文件系统的缓存,硬盘的缓存,数据库中的缓存 等等
涉及 查询, 更新 两条路
1、错误查询: 先查,如果缓存中没有,读数据库, 然后数据放入缓存更新: 先删 缓存, 然后更新数据库。问题:查询,更新,并发操作, 如果 更新操作先删缓存, 然后查询没有命中缓存,读取了数据旧数据,然后放入缓存。 导致了缓存中的脏数据
更新缓存的 设计模式
四种: Cache aside, Read through, Write through, Write behind caching
Cache Aside Pattern
最常用, 具体逻辑:查询:失效: 从cache 读取数据,没命中, 从数据库中读取数据,成功后,放到缓存中。命中: 从cache 读取数据, 读到就返回更新:先把数据放入 数据库中, 成功后,再让缓存失效注意点: 更新操作, 不能放入数据库, 然后更新缓存。 两个并发的写操作 导致脏数据这种模式也有可能出现问题:先读取 cache中没有的数据,即先查询,并且没命中数据,然后从数据库中读取了旧数据,然后更新操作,更新了数据库,让缓存失效。最后查询操作把旧数据 放入了缓存中。 同样产生了 脏数据这个case 理论上会出现。 实际上,出现的概率非常非常低。 因为这个条件需要发生在读缓存时缓存失效,而且并发着有一个写操作。而实际上数据库的写操作会比读操作慢得多,而且还要锁表,而读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存,所有的这些条件都具备的概率基本并不大。
Read/Write Through Pattern
上面的设计模式, 应用代码需要维护两个数据存储。 缓存cache,数据库repository。该设计模式的套路:把更新数据库的操作 由缓存自己代理。 所以对于应用层来说, 后端就是一个单一的存储,存储自己维护自己的cache
read through
在查询中更新缓存。即当缓存失效的时候(过期或LRU换出),cache Aside 模式是调用方负责把数据加载入缓存而read through是 缓存服务自己进行加载,对应用方透明
write through
更新数据时发生当有数据更新时, 如果没有命中缓存,直接更新数据库,然后返回如果命中了,则更新缓存, 然后由cache 自己去更新数据库 (同步操作)
Write Behind Caching Pattern
又叫 write back。 linux文件系统的page cache的算法就是 write back。套路: 更新数据的时候只更新缓存,之后再让缓存异步的批量更新进数据库优点: 数据的I/O 操作快。 因为异步,还可以合并对同一个数据的多次操作,性能提升高。缺点: 数据不是强一致性。 可能会丢失,系统非正常退出缓存丢失。
