缓存更新的几种套路

378 阅读2分钟

记得有一次面试的时候,被问到项目中使用Redis时,是如何更新缓存的。尴尬的是,在开始使用Redis的一段时间内,我总是下意识的使用前辈封装的类库,而对缓存更新的套路一无所知。

后来在前辈的指点下看了CoolShell,陈皓老师的这篇缓冲更新的套路才恍然大悟。

首先无论是哪一种套路我们都应该把它放在一个多线程的环境下讨论,才能得知它是否问题。

Cache Aside Pattern (旁路缓存)

这是一个最常见的缓存套路。

首先读取过程不涉及数据的修改。读过程和读过程并发,只存在更新缓存部分会有冲突,但由于数据没有变更,并发造成的相互更新,结果一致。

上图可以看到读写并发的过程如果 4、5顺序调换就会造成旧数据被重新更新,数据库和缓存不一致。但是这个case是虽然理论上会造成不一致,但实际的过程中出现的概率非常低。因为写操作需要锁表比读操作慢得多,先5再4的概率是很低的。

为什么现在的缓存都使用这种模式呢?首先要保证一致性,其实还有2PC和Paxos协议,但是这两种解决方案有一个致命的缺点就是效率太慢了。所以业界使用了一个一个并发时脏数据概率很低的方案。另外缓存设置最好加上过期时间,即使出现了缓存错误的清空,过期也会纠正。

Read/Write Through Pattern (穿透读写)

穿透读写的本质是把缓存单独作为一个存储,应用层不操作数据库。当你读取数据时,缓存有数据就返回数据,没有就返回空。缓存和数据库之间的数据同步由缓存来自动进行。

写操作一样我们只写缓存,如果缓存已有这行数据则更新或插入,同步又缓存后续完成。

这种方案其本质就是牺牲一致性来获取高并发的性能,例如点赞等场景。