如何保证Redis缓存和数据库数据一致性

在缓存的日常运用中,经常会遇到从缓存中获取某个值,经过业务处理后需要更新数据库对于的数据和该缓存值的内容,而这两个操作和该请求中其他的操作都可能出现异常,甚至时候需要进行IO操作的时间过长,都可能会造成更新缓存和更新数据库只成功一种的情况,这会造成数据不一致,在生产环境中排查这类问题非常困难,如何在设计阶段保证缓存一致性是开发人员在使用缓存时必须考虑的问题

读操作的数据一致性

如果缓存命中并直接返回,就不会进行DB操作,也就不存在一致性问题了

我们主要说一下未命中的情况,读操作涉及到数据库缓存的存放,整个请求的流程应该是

  1. 从缓存中获取值
  2. 缓存命中则使用缓存的值,未命中则需要进行下一步操作
  3. 从数据库中获取值,一般是从读数据库中获取
  4. 将数据进行缓存
  5. 完成请求其他的操作

写操作的数据一致性

在写操作中,我们对于缓存的操作并不是修改而是直接淘汰,下一次请求Cache Miss之后去进行缓存的写操作,

  1. 从缓存中获取值
  2. 删除缓存,下一次查询缓存的时候会未命中,而去查询数据库
  3. 更新数据库
  4. 删除缓存
  5. 完成请求其他的操作

    如果使用这个策略,我们要注意的地方有,删除缓存后会不会造成缓存击穿的问题,也需要考虑,数据库更新需要耗费时间,在完成更新之前可能有另外的线程以及完成了旧数据的缓存,所以进行了两次缓存淘汰

读写分离的数据一致性

数据不一致的来源首先来自于主从库不一致,然后由Catch miss时查询从库,导致的缓存和数据库不一致

  1. 读主库,针对热点数据,在短时间内可能会发生大量变化,此时主从同步的时间差很容易影响到缓存读取到的数据准确性,针对特殊的数据可以直接从主库读取,避免主从数据库不同步造成的后续影响
  2. 数据库监听,监听从库更新的数据,并针对缓存范围内的内容尝试进行缓存淘汰

    其他策略的简述

  • 不去关心缓存的一致性 如果是像微博或者头条一样的产品,他们的推送内容是否要求必须一致呢,答案并不是,短时间的缓存不一致并不会造成问题,那么缓存和数据库只要做到最终一致性即可