数据库和缓存一致性的几种设计模式
1. Cache-aside 模式
cache aside比较官方给出的解释:
https://docs.microsoft.com/en-us/azure/architecture/patterns/cache-aside
-
读操作的流程:
- 先读取cache,如果命中的话,直接返回数据;如果没有命中,从db读取。
- 更新缓存
-
写操作的流程:
- 先写入或更新db
- 标记缓存失效
读没有什么问题,写的时候,这里的设计就比较巧妙了。cache-aside选择先更新db,在标记缓存失效。如果不这样做,会怎么样呢?为什么要先写db,再标记缓存呢?
如果先写缓存,在更新db的话。会出现一个边界情况,如果请求1在更新完缓存之后,请求2(线程2)将数据从db中读了出来,覆盖了缓存。导致缓存数据错误。所以,一个cache-aside的设计,就是只写db,不写缓存,缓存标记失效。这样重复标记失效也不会出现大问题。大大减少的可能出现问题的边界,降低系统的复杂性。
采用标记缓存失效,而不是更新缓存的另外一个好处是:
在写多读少的业务中,主动更新的成本会更高一些。比如,写100次读1一次,主动更新缓存的话,更新更新100次缓存,而使用被动更新的方案的话,只更新一次缓存。
2. write/read through模式
read through
write through
write + read through结合
这种模式缓存就相当于一个proxy,上层业务就负责读写,更新db对上层业务透明。
3. write back 模式
这种模式有个问题,如果写入到缓存的数据,没有来的及写入到db,就是出现数据丢失。
4. 缓存穿透的问题
涉及到缓存和db的系统,缓存穿透就不得不需要考虑。如果请求没有命中缓存,大量的读请求就会穿过缓存,落到db上,db造成压力,甚至拖垮整个系统。可以设计系统的时候提前评估一下系统是否可能出现这种case,以及如果缓存被击穿有没有什么兜底的方案,不至于整个系统被拖垮。在应对缓存穿透的问题中,布隆过滤器是一个好东西。
以上是几种db和缓存一致性的设计模式,在实际的业务中,不太会像理论中采用某一个方案,往往都是混合使用。或者在不同特定的业务系统上面使用不同的方案。了解一下前人从各种踩坑之后,抽象出来的理论,还是可以提供一些有借鉴意义的经验,避免重复掉坑。
参考:
https://coolshell.cn/articles/17416.html
java3y的公众号上的一篇文章
网友评论