redis保证缓存和数据库一致性

107 阅读2分钟

redis保证缓存和数据库一致性

1.先更新缓存,后更新数据库

  • 如果更新成功了,但数据库更新失败,那么此时缓存中是最新值,但是数据库中是【旧值】
  • 虽然此时请求可以命中缓存,拿到正确的值,但是一旦缓失,就会从数据库中读取到【旧值】,重建缓存也是这个旧值。

2.先更新数据库,后更新缓存

  • 如果更新数据库成功了,但是缓存更新失败了,那么此时数据库中是最新的值,缓存中是【旧值】。
  • 之后的读请求都读到的是旧数据,只有当缓存【失效】后,才能从数据库中得到正确的值。

3.先删除缓存,再更新数据库

如果有 2 个线程要并发【读写】数据,可能会发生以下场景:

  • 线程A 要更新 X=2 (原值X=1)
  • 线程A 先删除缓存
  • 线程B 读缓存,发现不在,从数据中读取到旧值(X=1)
  • 线程A 将新值写入数据库(X=2)
  • 线程B 将旧值写入缓存(X=1)

最终 X 的值在缓存中是1(旧值),在数据库中是2(新值),发生不一致。

4.先更新数据库,再删除缓存

依旧是两个线程【并发读写】数据 :

  • 缓存中 X 不存在(数据库中 X=1)
  • 线程A 读取数据库,得到旧值(X=1)
  • 线程B 更新数据库(X=2)
  • 线程B 删除缓存
  • 线程A 将旧值写入缓存(X=1)

最终X的值在缓存中是1(旧值),在数据库中是2(新值),也发生不一致

这种情况理论来说是可能发生的,但实际中真有可能发生吗?

其实概率很低,这是因为它必须满足 3 个条件:

  1. 缓存刚已失效
  2. 读写请求并发
  3. 更新数据库 + 删除缓存的时间(步骤3~4),要比读数据库 + 写缓存的时间短(步骤2和5)

仔细想一下,条件3发生的概率是非常低的

因为写数据库一般会先【加锁】,所以写数据库,通常是要比读数据库的时间更长的

这么看来,【先更新数据库 + 再删除缓存】的方案,是可以保证数据一致性的。

所以,我们应该采用这种方案(【先更新数据库 + 再删除缓存】)来操作数据库和缓存。