首先,我们知道redis是缓存中间件,它所有数据都是存储在内存中,而数据库数据一般存储在硬盘中,这就导致我们读取数据的速度完全不同。
三种策略
-
先删缓存,再更新数据库
这种情况容易出现
- 1、线程A删除了缓存,还没更新数据库
- 2、线程B没有读到缓存,去查询数据库,将数据库中旧数据读到并写入缓存
- 3、线程A然后更新了数据库,导致缓存和数据库数据最终一致性没有成功
-
先更新数据库,再删除缓存
这种情况容易出现
- 缓存刚好失效
- 线程B读取数据库旧数据,
- 线程A更新数据库之后,删除了缓存
- 线程B将旧数据写入缓存,缓存的值和数据库的值没有保持最终一致性
-
先更新数据库再更新缓存
这种情况容易出现
- 线程A更新了数据库
- 线程B更新数据库
- 线程B更新缓存
- 线程A更新缓存,最终缓存中是A的值,数据库是B的值
解决办法就是采用延迟双删策略,结合第二种先更新数据库,再删缓存的策略 伪代码如下
db.update();
redis.delKey("key1");
sleep(5000s);//具体时间按业务评估,也就是数据这个接口跑业务所需要的时间
redis.delKey("key1");
或者使用canal同步数据库binlog日志到redis,实现数据最终一致性