Redis 缓存数据一致性
本文将介绍 Redis 作为缓存时的数据一致性问题及其解决方案。
一、缓存数据一致性问题
一旦在应用中引入了缓存,同一份数据便会在数据库和缓存同时存储,如果因为 “增删改” 导致两个地方的数据不一致,便会影响整个应用的数据正确性。
二、数据不一致的产生
1. 读写缓存 - 同步直写
对于同步直写策略,数据更新时需要同时更新缓存和数据库,一般会引入事务机制以确保操作原子性。因此,可以认为缓存和数据库的数据是一致的。
2. 读写缓存 - 异步写回
对于异步写回策略,假如在数据库还未写回时,缓存发生故障,数据库将丢失这一部分改动。因此,无法保证数据一致性。
3. 只读缓存
(1) 原子性操作带来的数据不一致
对于只读缓存而言,数据更新时需要同时进行 “删除缓存值” 和 “更新数据库值” 两个子操作,无论子操作的顺序如何,只要无法保证原子性,便会导致数据不一致。
当然,上图中的情况没有讨论的必要,操作失败了本就应该重试。
一种容易想到的解决方案是:多次重试,直至成功。
(2) 并发请求带来的数据不一致
假设子操作的顺序是:先删除缓存值,后更新数据库。
更新数据库需要一定的时间,在 “缓存值删除且数据库未被更新” 期间,如果有另一请求访问该数据,则它会从数据库中获取旧数据并更新缓存,导致数据不一致。
一种解决方案是:在更新完数据库后,等待一小段时间,再进行一次缓存删除操作。这种做法先删除一次缓存,延迟一段时间后又删除一次缓存,因此被称为 延迟双删。
等待的时间是为了确保 “缓存值删除且数据库未被更新” 期间的其它请求已执行完成,避免删除后又被错误更新
假设子操作的顺序是:先更新数据库,后删除缓存值。
在这种情况下,数据更新期间会有一部分请求从缓存中读取到旧数据,不过对业务的影响较小。
四、建议做法
建议将 Redis 作为只读缓存,并且先更新数据库后删除缓存。
参考
- Redis
- Redis 教程 | 菜鸟教程
- Redis数据库学习教程(快速入门版)
- Redis 核心技术与实战