前言
在学习了为一个接口添加Redis缓存后,我们要思考一个问题:缓存是把双刃剑,在为我们带来便捷的同时也产生了一些问题。例如缓存的一致性问题,因为我们把数据同时保存在缓存与数据库当中,当数据库内数据发生改变时,用户取到的数据还是缓存中的旧数据,与数据库不一致。所以这一篇我们要学习的是缓存的更新策略,来解决数据不一致的问题。
企业中常见的缓存更新策略
在这三种更新策略中,每种策略都有各自的优缺点,所以我们要根据我们所处的业务场景来选择合适的更新策略。
主动更新的业务逻辑是最复杂的,那么它到底复杂在哪里呢?
主动更新策略分为三个方案,第一个方案需要我们手动编码,可控性更高。在大多数企业的开发中都会选用第一种方案,那么使用第一种更新方案我们也需要考虑三个问题:
一、删除缓存还是更新缓存?
- 更新缓存:每次更新数据库都要更新缓存,无效的写操作比较多
- 删除缓存:更新数据库时让缓存失效,查询时再更新缓存
我们选择删除缓存。
二、如何保证缓存与数据库的操作的同时成功或失败?
- 单体系统,将缓存与数据库操作放在一个事务
- 分布式系统,利用TCC等分布事务方案
三、先操作缓存还是先操作数据库?
- 先删除缓存,再操作数据库
- 先操作数据库,再删除缓存
那么具体选择哪个呢?在两个线程的情况下,我们需要进行一个对比:
当我们选择先删除缓存,再操作数据库时,就会发生上面的情况:我们删除了缓存,正准备更新数据库的时候,线程2传来了获取数据的请求,由于缓存被删除,线程二直接查询数据库并把未及时更新的数据又重新添加到缓存之内 ,导致用户获取的数据依然是旧数据。
那么如果我们选择先操作数据再删除缓存呢?
在正常情况下,不会发生数据一致性的问题。但是会有上图这种特殊情况:缓存到期刚好失效,这个时候线程一的用户传来数据请求,由于为命中缓存,所以查到了数据库中的旧数据。这个时候线程二再更新数据库并进行删除缓存操作,删除的缓存是空缓存,所以导致删除缓存操作无效。那么线程一写入和缓存的数据还是旧数据。在这个极为特殊的情况下才会发生数据一致性问题。所以我们一般选择先操作数据库再删除缓存。
总结: