redis缓存+数据库双写不一致问题分析与解决方案
Posted 星仔学习
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis缓存+数据库双写不一致问题分析与解决方案相关的知识,希望对你有一定的参考价值。
在高并发场景下,肯定会发生这个问题,这里简单谈谈解决思路
1.常规简单的解决方案
先删除缓存,在更新数据库,如果删除缓存成功,修改数据库失败了,那么数据库中依然是旧数据,如果去读取数据的时候,发现缓存没有,则去读数据库,数据库会把旧数据加载到缓存里,这样缓存和数据库则保持了一致。
2.如果在高并发的情况下会发生了如下更复杂的操作
比如有数据发生了变更,先删除了缓存,然后准备要去修改数据库,此时还没修改,这时候一个请求过来,去读缓存,发现缓存空了,去查询数据库,查到了修改前的旧数据,放到了缓存中 ,之后数据变更的程序完成了数据库的修改。完了,数据库和缓存中的数据不一样了。。。
3.内存队列
更新数据的时候,根据数据的唯一标识,将操作路由之后,发送到一个jvm内部的队列中,读取数据的时候,如果发现数据不在缓存中,那么将重新读取数据+更新缓存的操作,根据唯一标识路由之后,也发送同一个jvm内部的队列中
一个队列对应一个工作线程,每个工作线程串行拿到对应的操作,然后一条一条的执行。这样的话,一个数据变更的操作,先执行删除缓存,然后再去更新数据库,但是还没完成更新。此时如果一个读请求过来,读到了空的缓存,那么可以先将缓存更新的请求发送到队列中,此时会在队列中积压,然后同步等待缓存更新完成
这里有一个优化点,一个队列中,其实多个更新缓存请求串在一起是没意义的,因此可以做过滤,如果发现队列中已经有一个更新缓存的请求了,那么就不用再放个更新请求操作进去了,直接等待前面的更新操作请求完成即可,待那个队列对应的工作线程完成了上一个操作的数据库的修改之后,才会去执行下一个操作,也就是缓存更新的操作,此时会从数据库中读取最新的值,然后写入缓存中。如果请求还在等待时间范围内,不断轮询发现可以取到值了,那么就直接返回; 如果请求等待的时间
超过一定时长,那么这一次直接从数据库中读取当前的旧值。
以上是关于redis缓存+数据库双写不一致问题分析与解决方案的主要内容,如果未能解决你的问题,请参考以下文章