MySQL
和redis
数据一致性问题
缓存是一种提高系统读性能的常见技术,对于读多写少的应用场景,我们经常使用缓存来进行优化。
是更新缓存还是删除缓存
更新缓存
- 数据不但写入数据库中,还会写入缓存中
- 优点:缓存不会增加一次 cache miss,命中率高
淘汰缓存
- 数据只会写入数据库,不会写入缓存,把数据淘汰掉
- 优点:简单
- 增加一次 cache miss
取决于更新缓存的复杂度:简单就更新,计算比较复杂的时候,就淘汰
先操作数据库 vs 先操作缓存
对于一个不能保证事务性的操作,一定涉及哪个任务先做,哪个任务后做的问题,解决这个问题的方向是,如果出现不一致的情况,谁先做对业务的影响小,谁就先做。
假设先写数据库,再淘汰缓存:
- 更新数据库操作成功,将编号 001 的账号的余额从 50 元更新为 100 元
- 可是淘汰缓存操作失败,缓存中是旧数据 50 元,从而造成了 数据不一致,用户查询时,在缓存中命中,返回 50 块的错误余额
结论是:应该先淘汰缓存,再写数据库。
这样即使第二步写数据库失败,则只会引发一次 cache miss。
假设先更新缓存,在更新数据库
如果缓存更新成功了,但数据库更新失败,那么此时缓存中是最新值,但数据库中是「旧值」。
虽然此时读请求可以命中缓存,拿到正确的值,但是,一旦缓存「失效」,就会从数据库中读取到「旧值」,重建缓存也是这个旧值。
这时用户会发现自己之前修改的数据又「变回去」了,对业务造成影响。
缓存架构优化
传统架构 缺点:业务方需要同时关注缓存与数据库
**主流优化:**服务化 加入一个服务层,向上游提供数据访问接口,向上游屏蔽底层数据存储的细节,这样业务线不需要关注数据是来自于缓存还是数据库