Redis中的几种更新策略

Redis中的几种更新策略

最近项目中用到redis做缓存,翻阅了各种资料,顺便也记录一下。

  • 在redis缓存和mysql数据库跟新的策略中,它们都存在一定的缺点,由于操作缓存和操作数据库不是一个原子操作,在一个线程进行操作缓存或操作数据库的过程中,它们之间的时间节点可能会穿插其他线程发起的数据库和缓存操作,这会导致数据一致性的问题,即缓存和数据库中的内容不一致,主要有以下几种策略:

1.删除缓存再更新数据库
这是很容易发生数据不一致问题的,当有一个读线程A一个更新线程B同时进行访问时,如果是以下顺序,B删除缓存,A读取缓存中不在key,A去数据库中查询旧的数据并插入缓存,B将新的数据写入数据库,这样就导致了缓存中仍然是老数据,而数据库中依然是新数据。

时间点 读线程A 写线程B
1 删除缓存
2 从数据库查询到旧的值
3 写入缓存旧的值
4 写入数据库新的值
最终 缓存中为旧的值 数据库中为新的值

2.更新数据库在删除缓存
这种策略比第一种稍微好一点,也比较常用,它发生数据不一致的情况是,读线程A一个更新线程B同时进行访问时,如果A线程在最开始查询的时候缓存中本来就不存在该键(比如第一次查询该key,或者这个key的缓存之前就被更新操作删除了),A去读取数据中的旧的数据,B去把数据库中的旧的数据改为新的数据,B去把缓存删除,A再把旧的数据插入缓存,这样也会导致,缓存中是旧的数据,而数据库中是新的数据。

时间点 读线程A 写线程B
1 从数据库查询到旧的值
2 写入数据库新的值
3 删除缓存
4 写入缓存旧的值
最终 缓存中为旧的值 数据库中为新的值

3.更新缓存再更新数据库
这样的话,发生数据不一致的情况发生在两个更新线程AB并发的时候,比如当A将缓存更新A的新值,B也将缓存更新B的新值,且B又将数据写入到了数据库中,然后A再将数据写入到数据库中,这样就造成了缓存里的数据时B 的新值,而数据库里的数据又是A的新值,当然因为一般更新操作比查询操作要少很多,所以更新缓存比删除缓存发生数据不一致的概率会更小。

时间点 写线程A 写线程B
1 写入缓存A的值
2 写入缓存B的值
3 写入数据库B的值
4 写入数据库A的值
最终 数据库中为A的值 缓存中为B的值

4.更新数据库再更新缓存
这和第三点是同理的,两个写线程也会发生数据不一致情况。

  • 此外,这四种方式都有一个地方会导致数据不一致,网上其他的资料里面也没有谈到,就是在redis中没有该缓存的时候或者缓存失效的时候,你一个读线程A去查缓存没查到,然后就去数据库里查完,然后管你是那种策略,一个更新线程B就来把它数据库更新了,缓存删除或者更新了,最终A又会去把原来的旧的值写到缓存里面,导致数据库是新值,缓存还是被后执行的读线程给写入了旧数据。
时间点 读线程A 写线程B
1 从数据库中读取旧的值
2 写入数据库新的值
3 删除或更新缓存
4 写入缓存旧的值
最终 缓存中为旧的值 数据库中为新的值
  • 所以如果需要保证数据库与缓存的一致性,可以参考我下面的博客
  • 主要是使用队列让每个线程的操作穿行化,防止出现以上的那些情况
  • 博客链接: 使用队列实现redis数据一致性的解决方案.
  • 谢谢大家观看

你可能感兴趣的:(redis)