日常开发中我们怎么用缓存,哪种模式缓存
- cache-aside:读请求,判断是否命中缓存,如果命中直接返回,如果没有命中,从数据库读取,更新缓存,返回数据。
写:写请求,先更新数据库,然后删除旧的缓存。
2.read/write-through
读:read-through:从缓存中读取数据,读到直接返回。
如果读取不到,从数据库加载,写入缓存,然后返回响应,其实和cache-aside很像,只是加了一下封装使代码更简洁。
write-through
发生写请求的时候,也是缓存抽象层完成数据源和缓存数据的更新。他是同步更新缓存和数据库的,
write-behind则是:只更新缓存,不直接更新数据库,通过批量异步的方式更新数据库。这种方式一致的要求不那么强烈,但是适合MySQL频繁写入的场景,mysql的InnoDB Buffer Pool 机制就是使用的这种模式。
操作缓存到底是要删除缓存还是更新缓存呢?
例如:两个线程A,发起写入操作,先更新数据库,线程B发起写的操作,后更新的数据库,由于网络原因,线程B先更新了缓存,线程A后更新的缓存,这就出现一个问题,就是数据库是新的数据,而缓存是老的数据。如果是删除缓存就不会有这个问题。
更新缓存相对于删除缓存还有两个劣势:
1.如果写入缓存的东西经过复杂的运算,则更新就很费性能。
2.在写的多,读的少的场景下,数据很多时候还没被读取到,就被更新了,这也是性能问题。
cache-aside为啥要先操作数据,不操作缓存呢?
1.线程A发起了一个写的操作,删除缓存
2.线程B发起了一个读的操作,缓存没有
3.线程B读DB,读出来一个老数据
4.线程B吧老的数据,放入缓存
5.线程A写入数据库新的数据。
这样就导致,缓存数据库和缓存不一致。
因此:cache-aside 先操作数据库,后操作缓存。
怎么做到数据库和缓存强一致?
其实没有办法强一致,追求绝对的一致性,不适合使用缓存。
什么是延迟双删:
他是可以保持一致性的方案之一,
1.先删除缓存
2.更新数据库
3.休眠一段时间
4.再次删除缓存
删除缓存重试机制
不管是双删还是cache-aside,都会存在
优化方案:删除失败,就多删除几次,设置一个延迟时间,引入重试机制
1.写请求更新数据库
2.缓存因为某些原因,删除失败
3.把删除失败的key放在队列里面,
4.消费消息队列的消息,获取要删除的key
5.重试删除缓存机制