缓存服务的更新策略有哪些?
https://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&mid=2247486190&idx=2&sn=9010f6afd882fb89910c9705ff0565ab&chksm=ebd635c2dca1bcd45ec1ebc53735efb60fa1c4f114d9ebb413553b529ddf5ba4c919fa1073b3&mpshare=1&scene=1&srcid=08262u47QokhNd5pMBWFG9S0&key=ef42a6c1e4fdfbc65ba82555f9896d9c5a7354602ec07e17be554bf04166467d68d3fc60fc56f82670f6bca34e1f1536c50a13b587070456bdca74a72d8260c046cb6eaeba23618af9970699daf822cd&ascene=0&uin=MTA2NzUxMDAyNQ%3D%3D&devicetype=iMac+MacBookAir6%2C2+OSX+OSX+10.10.5+build(14F2511)&version=11020012&lang=zh_CN&pass_ticket=CVcnCq3fRvmC4IGWpkSR%2FZDBORx2is4pwUIXsVX1AlDvKaC7BkGZTmaYyGPPxCY1
典型的缓存模式,一般有如下几种:
-
Cache Aside
-
Read/Write Through
-
Write Behind
每种模式都有不同的特点,适应与不同的项目场景,下面来依次看看:
-
Cache Aside 模式
这是大家经常用到的一种策略模式。这种模式主要流程如下:
-
应用在查询数据的时候,先从缓存Cache中读取数据,如果缓存中没有,则再从数据库中读取数据,得到数据库的数据之后,将这个数据也放到缓存Cache中。
-
如果应用要更新某个数据,也是先去更新数据库中的数据,更新完成之后,则通过指令让缓存Cache中的数据失效。
这里为什么不让更新操作在写完数据库之后,紧接着去把缓存Cache中的数据也修改了呢?
主要是因为这样做的话,就有2个写操作的事件了,担心在并发的情况下会导致脏数据,举个例子:
假如同时有2个请求,请求A和请求B,并发的执行。请求A是要去读数据,请求B是要去更新数据。初始状态缓存中是没有数据的,当请求A读到数据之后,准备往回写的时候,此刻,请求B正好要更新数据,更新完了数据库之后,又去把缓存更新了,那请求A再往缓存中写的就是旧数据了,属于脏数据。
那么 Cache Aside 模式就没有脏数据问题了吗?不是的,在极端情况下也可能会产生脏数据,比如:
假如同时有2个请求,请求A和请求B,并发的执行。请求A是要去读数据,请求B是要去写数据。假如初始状态缓存中没有这个数据,那请求A发现缓存中没有数据,就会去数据库中读数据,读到了数据准备写回缓存中,就在这个时候,请求B是要去写数据的,请求B在写完数据库的数据之后,又去设置了缓存失效。这个时候,请求A由于在数据库中读到了之前的旧数据,开始往缓存中写数据了,此时写进入的就也是旧数据。那么最终就会导致,缓存中的数据与数据库的数据不一致,造成了脏数据。
不过这种概率比上面一种概率要小很多。所以整体而言 Cache Aside 模式 还是一种比较简单实用的方式。
-
Read/Write Through 模式
这个模式其实就是将 缓存服务 作为主要的存储,应用的所有读写请求都是直接与缓存服务打交道,而不管最后端的数据库了,数据库的数据由缓存服务来维护和更新。不过缓存中数据变更的时候是同步去更新数据库的,在应用的眼中只有缓存服务。
流程就相当简单了:
-
应用要读数据和更新数据都直接访问缓存服务
-
缓存服务同步的将数据更新到数据库
这个模式出现脏数据的概率就比较低,但是就强依赖缓存了,对缓存服务的稳定性有较大要求,另外,增加新缓存节点时还会有初始状态空数据问题。
-
Write Behind 模式
这个模式就是 Read/Write Through 模式 的一个变种。区别就是 Read/Write Through 模式的缓存写数据库的时候是同步的,而 Write Behind 模式 的缓存操作数据库是异步的。
流程如下:
-
应用要读数据和更新数据都直接访问缓存服务
-
缓存服务异步的将数据更新到数据库(通过异步任务)
这个模式的特点就是速度很快,效率会非常高,但是数据的一致性比较差,还可能会有数据的丢失情况,实现逻辑也较为复杂。
以上就是目前三种主流的缓存更新策略,另外还有Refrsh-Ahead模式等由于使用的不是很常见就不详细介绍了。
缓存是互联网项目中非常普遍的一个提高效率的方案,用法比较多,也比较关键,大家可以一起交流。