为什么要写这篇文章
最近呢,需要写一个供M端(APP端)访问视频合辑信息的接口,以后可以在商家店铺上看见视频及对应的相关商品啦。由于M端访问数量挺大的吧,需要用到缓存(用的redis),将合辑信息存入redis中,减轻MySQL读压力。和组里的人讨论后,发现缓存套路深,需要记下来。
缓存解决什么问题
数据缓存主要用于分担数据库的压力,对于redis基于内存的非关系型数据库,它提高了查询性能。
缓存使用场景
1.数据实时性要求不高。经常访问,但是很少改变数据。
2.性能要求较高。
缓存更新的4种模式
Cache Aside Pattern
缓存失效:若在cache中没找到,从数据库中读取,并将读取出的数据更新到cache中。
缓存命中:从cache中读取出来,返回数据。
缓存更新:先更新数据库,再将缓存失效。
问题1:这种模式什么情况会出问题?
一个读请求,没有命中缓存,从数据库中读取数据。此时,一个写请求过来,更新了数据库数据,并将缓存设为无效。然后,读请求将读到的数据存入缓存中,导致缓存数据与数据库数据不一致(脏数据)。
出现这种情况的概率非常低,必须发生在,读缓存时缓存失效,同时有一个写操作到来。写操作需要上锁,会比读慢很多,读操作需要在写操作前进入,又要晚于写操作更新缓存,概率很小。
问题2:为什么模式不是先删除缓存再更新数据库?
想一下这样一种场景,一个读操作,一个写操作,写操作将缓存删除,读操作没读到缓存,从数据库中取,然后将数据更新到缓存,写操作更新数据库,此时数据不一致。
问题3:为什么模式不是先更新数据库再更新缓存?
对于2个并发写操作,可能导致脏数据,数据库与缓存不一致。
Read Through Pattern
当缓存失效时,由缓存服务自己来加载数据。
Write Through Pattern
当更新数据时,如果没有命中缓存,那么直接更新数据库,然后返回。如果命中了缓存,那么只更新缓存,由cache服务自己更新数据库。
Write Back Pattern
这个是Linux文件系统的Page Cache算法(表示没听过)
在更新数据的时候,只更新缓存,不更新数据库,而缓存会异步地批量更新数据库。(可以合并对同一数据的多次操作)
只有当缓存将要失效的时候才真正被持久起来。这样当缓存挂了,会很尴尬的。
牺牲了一致性和可用性,提高了性能。