常见的缓存读写策略是哪3种?
- Cache Aside(旁路缓存)
- Read/Write Through(读/写穿透)
- Write Behind(异步缓存写入)
其中我们最常使用就是Cache Aside这种缓存读写策略
Cache Aside(旁路缓存)
写策略:
- 先更新DB
- 直接删除缓存
图解:
读策略:
- 先读缓存,缓存中有,则返回
- 缓存中没有,则从DB中读取返回
- 将读取的数据写入缓存
思考: 在写数据过程中,可以先删除缓存,在更新DB吗?
不可以。因为这样可能会造成DB和缓存的不一致问题。
举例: 当请求A先写数据,将缓存删除后,请求B来读取数据,发现缓存中没有数据,就去DB中读取,然后将读取的数据写入到缓存中(ps:这不白删了吗?我前脚刚删,你后脚又写进来了),请求A更新DB。
文字描述太抽象了,画个图帮助大家理解
思考: 先写DB,在删除缓存就一定没有问题吗?
不一定。
举例: 缓存中没有数据,请求A读取到DB中的数据,这时请求B过来更新DB中的数据,缓存中没有数据所以不用删除,请求A将读取到的数据写入到缓存中
图解:
这种策略的缺点:
1、第一次读取数据时,在缓存中一定不存在,需要去DB中读取
解决方案: 做缓存预热,先将热点数据提前放入到缓存中
2、写操作频繁导致缓存中的数据被频繁的删除,导致缓存命中率低
解决方案:
- 更新DB的同时更新缓存,不过需要加一个锁/分布式锁来保证更新缓存的时候不会存在安全性问题(这种方案还能保证DB和缓存的数据一致性,但是效率较低)
- 更新DB的同时更新缓存,给缓存设置一个较短过期时间(这种方案可能会导致一段时间的数据不一致,适合与允许一段时间缓存不一致的场景)
Read/Write Through(读/写穿透)
写策略:
- 先查询缓存中是否存在,不存在直接更新DB
- 缓存中存在,先更新DB,然后再去更新DB
图解:
读策略:
- 从缓存中读取数据,读取到直接返回
- 缓存中读取不到数据,查询DB,写入缓存后返回
与Cache Aside的读策略比较(容易混淆)
Read/Write Through中的读策略都是从缓存中读取,如果缓存中没有则有缓存服务去DB中读取。
Cache Aside中的读策略如果读取的数据在缓存中没有,会从DB中读取,然后由客户端来写入到缓存中。
最大的不同就是缓存由谁来写入,前者由缓存服务去写,对客户端是透明的,后者则有客户端手动写入
Write Behind(异步缓存写入)
和Read/Write Through类似,都是有缓存服务去DB中读取数据,唯一的不同就是Read/Write Through是同步更新缓存和DB,而Write Behind只更新缓存,然后由异步的方式来更新DB。
这种方式的写性能非常高,但是对数据一致性具有更大的挑战(更新缓存后,缓存服务还没来得及写入到DB中,缓存服务宕机了,这部分数据就丢失了)。
使用场景: 适合一些数据经常发生变化但是对数据一致性要求不高的场景,例如: 浏览量、点赞量