美文网首页MySQL
数据库-缓存数据一致性问题

数据库-缓存数据一致性问题

作者: zhglance | 来源:发表于2019-06-24 20:38 被阅读45次

一、问题描述:

当使用DB + cache的架构时,会出现是先更新cache,还是先更新DB的问题。

1.先更新cache,再更新DB:

如果更新cache成功,但是更新DB失败,会导致cache和DB数据的不一致。业务在查询时,查询到的cache数据是更新后的,当cache过期后,经过一次miss,将查询到DB的脏数据。

2.先更新DB,再更新cache:

如果更新DB成功,但是更新cache失败,同样会导致cache和DB数据的不一致。业务在查询时,查询到的cache数据是更新前的脏数据,当cache过期后,经过一次miss,查询到的数据才是正确的数据。
在多线程环境下,假如执行顺序如下:
1.线程A更新DB;
2.然后线程B更新DB;
3.然后线程B更新cache;
4.线程A更新cache。
这样也导致了cache和DB数据的不一致。

二、先淘汰缓存,再更新DB

针对上述问题,有人提出淘汰缓存的策略,具体方法如下:
1.先淘汰cache,如果成功,则更新DB;如果失败则不更新DB,后续可以通过重试来解决失败的问题,但是增加了一次cache的miss。

淘汰策略解决了更新cache的数据一致性问题,但是增加了一次miss cache,淘汰缓存策略特别时候cache和DB数据格式不一样的场景,如cache中的数据是通过DB中的数据计算获得的(如组织架构的树形结构cache,避免对DB的递归查询,需要根据DB计算cache的数据结构),这样也节省了更新缓存的代价。

2.1 并发导致先淘汰缓存的数据不一致性

1.线程A执行数据更新操作,先淘汰cache;
2.线程B执行查询操作,出现了miss cache;
3.线程B查询DB,并将查询到的数据缓存到cache中;
4.线程A此时更新DB。
这样cache的数据和DB的数据出现了不一致,即此时cache保存的是脏数据。

2.2 解决方案一:数据更新queue

针对高并发时cache和DB不一致的问题,可以通过数据更新queue来实现,当要更新数据时,先将要更新的数据key保存到queue中,表示此时数据正在更新,当淘汰cache,执行DB都成功后,将数据从queue队列中删除key。

在数据更新的过程中,先查看cache中是否有对应的key,如果有则返回数据;如果没有数据,则先去queue中查询是否存在对应的key,如果存在则使用while(true)来循环查询cache,并设置超时时间;如果queue中没有对应的key,则判断为miss cache,则读取DB,并将数据缓存到cache中,避免了高并发场景下的数据不一致性。

以上方案也可以解决DB主从延迟的数据一致性问题,即当key在queue中时,程序读取主库,否则读取从库。

2.3 解决方案二:延时双删除策略

采用延时双删除策略,数据更新时具体过程如下:
1.淘汰缓存;
2.更新DB;
3.sleep(100);
4.再次淘汰缓存,避免因为另外线程读取时miss cache导致的脏数据保存到了cache。
但是这种方案有sleep时间难以确定,而且加入步骤4再次淘汰执行失败,也同样导致cache和DB数据的不一致,不过可以通过缓存失效时间来实现最终一致性。

三、先更新DB,再删除cache,即缓存旁路模式(Cache Aside Pattern )

具体操作如下:

1.数据查询

先从cache中获取数据,没有得到,则从DB中获取,成功后将数据放到cache中。

2.数据更新

先更新DB,如果成功,则再执行淘汰缓存,如果执行淘汰缓存失败,则DB回滚。

a.如果数据更新时,淘汰cache失败而不执行DB回滚,可以通过如下方案解决:

方案一:使用MQ保存失败的key

可以通过消息MQ来实现重试,即将淘汰cache失败的key发送到MQ中,然后消费MQ,执行淘汰cache操作,直到淘汰成功。

方案二:使用数据库的binlog

订阅DB的binlog,获取binlog中的数据的key,然后执行淘汰cache中的key,如果失败,则发送key到MQ,后续同方案一。

b.多线程导致的不一致性

线程A执行查询,线程B执行更新,具体过程如下:
1.缓存过期失效;
2.线程A查询,则会miss cache,线程A查询DB得到旧数据,然后准备执行更新cache;
3.线程B更新数据,执行更新DB;
4.线程B淘汰cache;
5.线程A此时执行将旧数据更新cache;

这样会出现数据不一致的情况,但该不一致性出现的条件是,步骤3写入DB操作比步骤2耗时更短,才会出现步骤4先于步骤5。而由于DB的读操作远快于写操作,所以上述场景出现的概率还是很小的。如果这样的概率仍然不可接受,则可以使用“延时双删除策略”双保险策略。

相关文章

  • 解决缓存与数据库的数据一致性问题

    解决缓存与数据库的数据一致性问题 问题分析 多个写请求执行顺序不同导致脏数据 存在更新缓存请求和读缓存请求,读缓存...

  • 先更新缓存还是先更新数据库

    项目中缓存基本上成为了标配,本地缓存也好、内存数据库缓存也好,只要用了缓存就会涉及数据一致性的问题,这个一致性指的...

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

    如何保证缓存和数据库数据一致性呢? 1 先删除缓存 再更新数据库 线程1删除缓存 线程2查询数据 缓存没有命中,...

  • 缓存一致性问题

    1. 先删缓存,再更新数据库 对于保持缓存与数据库的数据一致性,有一种常见的解决方法就是先删除缓存,再更新数据库。...

  • 数据库与缓存数据一致性解决方案

    一、序言 在分布式并发系统中,数据库与缓存数据一致性是一项富有挑战性的技术难点。本文将讨论数据库与缓存数据一致性问...

  • Redis基础--缓存问题3+1

    缓存穿透、缓存雪崩、缓存击穿缓存与数据库数据一致性 缓存穿透 大多数互联网应用,使用缓存的方式如下: 当业务系统发...

  • 缓存异常:如何解决缓存与数据库的一致性

    缓存和数据库的数据不一致的产生原因 数据一致性 缓存中有数据,那么,缓存中的数据值需要和数据库中的值相同 缓存中没...

  • 缓存一致性解决方案

    1.实时同步更新 特点:更新数据库的同时,更新缓存,使用缓存工具类或者AOP实现 优点:数据一致性强,不会出现缓存...

  • 缓存的刷新机制-第一篇

    关键字:redis刷新机制、先更新缓存还是先更新数据库、缓存和数据库如何保持数据一致性。 1. 前言 几天前被面试...

  • redis缓存的一些常见问题

    1.数据一致性问题 缓存和数据库的数据不一致是如何发生的 这里的“一致性”包含了两种情况: 缓存中有数据,那么,缓...

网友评论

    本文标题:数据库-缓存数据一致性问题

    本文链接:https://www.haomeiwen.com/subject/hsdaqctx.html