Redis和数据库双写不一致的问题 |
您所在的位置:网站首页 › redis与数据库数据不一致怎么办 › Redis和数据库双写不一致的问题 |
Redis和数据库双写不一致的问题说的是,在进行数据更新时,Redis和数据库都要进行更新,怎么样才能保证在更新的同时用户读取的数据的一致性呢?我们根据具体的情况分析一下。 1、先更新数据库,再更新缓存(不可取)若有两个请求P和Q先后过来更新数据: (1)缓存刚好失效; (2)请求P更新数据库; (3)请求Q更新数据库; (4)请求Q更新缓存; (5)请求P更新缓存; 上述情况,P先与Q过来,因此更新完成后,数据库和缓存最终的值均因该为请求Q更新的值,而上述流程中,由于请求P在更新缓存是遇到了网络拥塞导致Q先更新了缓存,所以数据库中最终值的是Q更新的值,而缓存中最终值是P更新的结果,数据不一致。 2、先更新数据库,再删除缓存小问题:为什么是删除缓存而不是更新缓存? 答:第一、删除缓存采取的是懒加载模式,删除后等待下一次查询请求过来才会更新缓存。若是每次更新数据库后,都更新缓存的话,会带来不必要的服务器压力,因为更新缓存可能涉及到一些计算,数据库连表查询等等。第二、第一个方案的并发问题。 该方式是facebook在论文《Scaling Memcache at Facebook》中提出,若有两个请求P和Q先后过来,P查询数据,Q更新数据: (1)缓存刚好失效; (2)请求P查询数据库,得一个旧值; (3)请求Q将新值写入数据库; (4)请求Q删除缓存; (5)请求P将查到的旧值写入缓存; 上去确实发生了读写不一致的问题,但是仔细推敲一下:请求P先到达,发现缓存失效,然后去读取数据库。然后请求Q到达,下数据库,在删除缓存。在数据库中读操作会快于写操作,况且在进行读写分离的分布式环境下,读的速度会远快于写,而上述请求Q写数据库和删除缓存的操作,竟然发生在P写入缓存之前。从概率上讲,考虑到网络延时的问题,上述情况可能发生,但是概率极低。 在该方案下考虑上述并发问题,还不如考虑该方案下缓存删除失败的情况,来的更实在。若有两个请求Q和P先后过来,Q更新数据,P查询数据: (1)缓存还未失效; (2)请求Q将新值写入数据库; (3)请求Q删除缓存失败; (4)请求P查询缓存得到旧数据; 上述情况下,造成数据不一致状态,只能等到缓存过期或者新的写请求能删除成功,才能结束。 3、先删除缓存,再更新数据库该方案很好的弥补了第二个方案中缓存删除失败带来的问题。在该方案中,若缓存删除失败,可以直接抛出异常,此后数据库也不会再更新,因此缓存和数据库一致。若数据库更新失败,数据库中还是旧数据,缓存还是会在下次读请求中被更新为旧数据,因此缓存和数据库一致。 但是,在高并发场景下,该方案仍然有一种情况需要考虑,若有两个请求Q和P先后过来,Q更新数据,P查询数据: (1)Q删除缓存; (2)P发现没有缓存,于是访问数据库; (3)P从数据库返回旧数据,并更新缓存; (4)Q更新数据库; 上述情况下,数据不一致。我们可以对上述方案进行改进。 改进方案三:先删除缓存,再更新数据库+jvm内存队列改进中添加了一个内存队列(用被更新的数据进行唯一标记),当Q删除缓存后,在缓存被更新前,所有读和写请求都放入队列进行同步阻塞,等待缓存更新。指的注意的是,相同的写请求是没有意义的,可以忽略。还有一点值得注意,队列积压问题,要进行适当的控制。 4、先更新缓存,在将数据库更新请求放入kafka,进行一部处理上述方案是一个补充方案,比较特殊,是我在项目项目中遇到的。该方案的主要思想是,将redis当做“数据库”来进行查询,其中的时间设置为永不过期,将真正的数据库当做备份。该方案要注意redis集群的高可用性。
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |