Cache Aside
最常用的缓存模式,大体意思是
先从cache中取数据,没有获取到则从数据库中读取,成功后放到缓存中;如果在cache中获取到数据直接返回;更新时先把数据存到数据库,成功后再让缓存失效
- 先更新数据库,在更新缓存:遇到的问题是两个并发的更新操作,数据库先更新的后更新缓存,数据库后更新的先更新缓存,这样就会造成数据库与缓存的数据不一致,应用程序中读取的数据都是脏数据
- 先删除缓存,在更新数据库: 遇到的问题是有两个并发操作,一个更新操作先删除了缓存,此时另一个并发的读取操作没有命中缓存,直接读取数据库并更新回了缓存,这个时候正好更新操作完成数据更新。此时数据库和缓存的数据不一致,应用程序读取的数据都脏数据了
- 先更新数据库,在删除缓存 :这个方式也算是我们实际系统使用中比较推荐的一种方式,但是这种方式在理论上还是可能会出现问题,两个并发操作,其中一个查询操作没有命中缓存,此时查询出来了数据库中的老数据,此时另一个并发的更新操作,在刚才的并发读操作之后更新了数据库中的数据并删除了缓存,然后并发读操作线程又把老数据写入了缓存,此时又造成了数据的不一致,应用程序读取的都是脏数据。因为这种概率差生的情况实在是太小,所以才是我们系统中经常使用的一种方式了。
Read/Write Through
Cache Aside 模式中,应用程序需要维护两个数据存储,一个是缓存,一个是数据库,在Read/Write Through 更新模式中,应用程序只需要维护缓存,数据库的维护工作就有缓存代理了
Read Through
Read Through 模式就是在查询时更新缓存,也就是说,在缓存失效时,Cache Aside 模式是由调用方负责把数据载入缓存,而Read Through 模式是缓存服务自己更新缓存,自己来加载数据
Write Through
Write Through 和Read Through 类似,当数据更新时,如果命中缓存则更新缓存,然后缓存更新数据库,这是一个同步的操作;如果没有命中缓存,直接更新数据库返回
Write Behind Caching
Write Behind Caching 更新模式是在更新数据时只更新缓存,不更新数据库,而我们的缓存会异步的更新数据库。这个模式的话就是速度快,毕竟我们直接操作内存,因为是异步的,Write Behind Caching 更新模式还可以合并对同一个数据的多次操作到数据库,所以性能的提升也是很明显的
问题就是数据不是强一致性的,而且还可能会丢失,Write Behind Caching 更新模式实现逻辑复杂,因为它需要确认有哪些数据是被更新的,哪些数据是需要刷到持久层的数据库的。只有当缓存失效的时候才会把它真正的持久化起来
总结
- Cache Aside 更新模式实现起来比较简单,但是需要维护两个存储,一个缓存,一个数据库
- Read/Write Through 更新模式只需要维护一个数据存储(缓存),但是实现起来复杂
- Write Behind Caching 更新模式和Read/Write Through 更新模式类似,区别是Write Behind Caching 更新模式的数据持久化操作好是异步的,Read/Write Through 更新模式的数据持久化操作是同步的。优点是直接操作内存速度快,多次操作可以合并持久化到数据库。缺点是可能数据丢失,例如系统断电等
缓存是通过牺牲强一直性来提高性能的,所以使用缓存来提高性能就会有数据更新的延迟。这就需要我们在设计时结合业务场景仔细思考是否需要缓存,使用缓存选择合同的缓存方式,缓存设置合适的过期时间 这个时间一定要设置,并且太短太长都不好,太短的话请求就会太多的落到数据库,造成缓存穿透,也就失去了缓存的优势。太长的话缓存中脏数据又会使系统长时间的处于一个延迟的状态,而且系统中长时间没有人访问的缓存数据数据会一直存在内存中,造成内存浪费。