目录
二、读/写透明(Read/Write Through Pattern)
先上一个错误操作示范
操作方法:先删除缓存,然后再更新数据库,而后续的操作会把数据再写入到的缓存中。
存在的问题:查询请求没hit到缓存会把旧数据更新到缓存中。
解释:两个并发操作,一个是更新操作,另一个是查询操作,更新操作删除缓存后,查询操作没有命中缓存,先把老数据读出来后放到缓存中,然后更新操作更新了数据库。于是,在缓存中的数据还是老的数据,导致缓存中的数据是脏的,而且还一直这样脏下去了。
正确姿势
一、缓存失效(Cache Aside Pattern)
策略(Facebook论文范例):
- 失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。
- 命中:应用程序从cache中取数据,取到后返回。
- 更新:先把数据存到数据库中,成功后,再让缓存失效。
问题:
1、为什么不写完数据库后再更新缓存
并发两个写操作可能会导致脏数据。
2、该策略存在什么问题?
问题1 脏读:一个查询缓存请求,一个更新缓存请求。查询缓存没有hit,从数据库查出了旧数据,此时有个更新请求过来,更新数据库后把缓存设为了失效。刚才查询请求此时把旧数据更新到缓存中,于是缓存中的数据会一直是脏数据。
问题2 更新缓存失效失败:概览太低不考虑
解释:实际发生的概览非常低,需满足两个条件:1、读缓存时缓存失效,而且并发着有一个写操作 2、读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存。由于一般写操作时间远大于读操作时间,所以发生概率很低。要么通过2PC(太慢)或是Paxos(太复杂)协议保证一致性,要么就是拼命的降低并发时脏数据的概率。
二、读/写透明(Read/Write Through Pattern)
策略:
Read Through
Read Through 套路就是在查询操作中更新缓存,也就是说,当缓存失效的时候(过期或LRU换出),Cache Aside是由调用方负责把数据加载入缓存,而Read Through则用缓存服务自己来加载,从而对应用方是透明的。
Write Through
Write Through 套路和Read Through相仿,不过是在更新数据时发生。当有数据更新的时候,如果没有命中缓存,直接更新数据库,然后返回。如果命中了缓存,则更新缓存,然后再由Cache自己更新数据库(这是一个同步操作)
三、写回调( Write Back)
策略:
在更新数据的时候,只更新缓存,不更新数据库,而我们的缓存会异步地批量更新数据库。
优点:让数据的I/O操作飞快无比。
缺点:数据不是强一致性的,而且可能会丢失。
参考
1、缓存更新的套路:
https://coolshell.cn/articles/17416.html#Write_Behind_Caching_Pattern