精华内容
下载资源
问答
  • 缓存和数据库一致性问题

    千次阅读 2020-10-21 16:06:29
    缓存和数据库一致性问题 前言 在我们生产的过程中,我们会发现我们80%的业务是由20%的数据来驱动的,这20%的数据往往被我们称为热数据,这种现象也被称为二八定律。这种数据访问不均匀的现象,使得我们可以采用最...

    缓存和数据库一致性问题

    前言

    在我们生产的过程中,我们会发现我们80%的业务是由20%的数据来驱动的,这20%的数据往往被我们称为热数据,这种现象也被称为二八定律。这种数据访问不均匀的现象,使得我们可以采用最有效的技术——缓存来提升我们整个系统的性能,但是用到缓存我们不可避免地要考虑一个问题缓存和数据库数据一致性的问题。

    分布式下的数据一致性问题 可参考我的博客:分布式下的数据一致性问题

    正文

    缓存和数据库一致性问题

    缓存和数据库双写一致性问题

    • 强一致性:缓存和数据库数据始终保持一致
    • 最终一致性:缓存和数据库数据有一段时间不一致,单不影响查询结果。

    解决缓存一致性的解决方案

    • 延时双删策略
    • 通过消息队列来更新缓存
    • 通过binlog来同步mysql数据库到redis

    延时双删策略

    延时双删策略一个写操作会进行以下流程:

    1. 先淘汰缓存
    2. 再写数据库
    3. 休眠1秒,再次淘汰缓存

    接着我们要明确为什么要采用先淘汰缓存,再写数据库的策略。

    先写数据库再更新缓存的弊端

    1.线程安全方向(为什么要先操作缓存,再操作数据库)
    同时有请求A和请求B进行更新操作,那么会出现:

    • 线程A更新了数据库;
    • 线程B更新了数据库;
    • 线程B更新了缓存;
    • 线程A更新了缓存;(A出现网络波动)

    这就出现请求A更新缓存应该比请求B更新缓存早才对,但是因为网络等原因,B却比A更早更新了缓存。这就导致了脏数据。
    并且这种情况只能等缓存失效,才能够得到解决,这样的话很大程度会对业务产生比较大的影响。

    2.业务方向(为什么选择淘汰缓存,而不是更新缓存)

    • 缓存的意义就是为了提升读操作的性能,如果你写操作比较频繁,频繁更新缓存且没有读操作,会造成性能浪费,所以应该由读操作来触发生成缓存,故而在写操作的时候应采用淘汰缓存的策略。
    • 有的时候我们在存入缓存可能也会做一些其他转化操作,但是如果又立马被修改,也会造成性能的浪费。

    采用先淘汰缓存,再写数据库事实上不是完美的方案,但是是相对而言最合理的方法,它有下面的特殊情况:

    1. 写请求A进行写操作,删除缓存;
    2. 读请求B查询发现缓存不存在;
    3. 读请求B去数据库查询得到旧值;
    4. 读请求B将旧值写入缓存;
    5. 写请求A将新值写入数据库;(这里不采取行动,会造成数据库与缓存数据不一致)

    上述情况就会导致不一致的情形出现。

    延时双删策略是为了解决采用先淘汰缓存,再写数据库可能造成数据不一致的问题,这个时候写请求A应采用休眠1秒,再次淘汰缓存的策略:

    • 采用上述的做法,第一次写操作,会出现将近1秒(小于 1秒减去读请求操作时间)的数据不一致的问题,1秒后再次执行缓存淘汰,下次读操作后就会保证数据库与缓存数据的一致性了。

    • 这里提到的1秒,是用来确保读请求结束(一般是几百ms),写请求可以删除读请求造成的缓存脏数据。

    另外还存在一种极端情况是:如果第二次淘汰缓存失败,会导致数据和缓存一直不一致的问题,所以

    • 缓存要设置失效时间
    • 设置重试机制或者采用消息队列的方式保证缓存被淘汰。

    通过消息队列来更新缓存

    采用消息队列中间件的方式能够保证数据库数据与缓存数据的最终一致性。

    • 实现了异步更新缓存,降低了系统的耦合性
    • 但是破坏了数据变化的时序性
    • 成本相对比较高
      在这里插入图片描述

    通过binlog来同步mysql数据库到redis中

    Mysql数据库任何时间对数据库的修改都会记录在binglog中;当数据发生增删改,创建数据库对象都会记录到binlog中,数据库的复制也是基于binlog进行同步数据

    • mysql压力不大情况下,延迟较低;
    • 和业务完全解耦;
    • 解决了时序性问题;
    • 成本相对而言比较大。
      在这里插入图片描述
      在这里插入图片描述
    展开全文
  • 缓存和数据库一致性解决方案: 1. 问题背景 2. 缓存更新策略 3. 改进方案 4. Cache Aside Pattern
  • 缓存和数据库数据一致性

    千次阅读 2018-08-27 22:06:29
    1、产生缓存和数据库数据一致性问题的问题 当我们数据库压力大的时候可以对数据库做读写分离,主库负责写操作,从库负责读操作,主从数据库之间采用二进制日志文件来同步数据。 还有另一种解决方案是使用缓存,...

    1、产生缓存和数据库数据一致性问题的问题

    当我们数据库压力大的时候可以对数据库做读写分离,主库负责写操作,从库负责读操作,主从数据库之间采用二进制日志文件来同步数据。

    还有另一种解决方案是使用缓存,通常我们使用缓存的姿势是查询直接从缓存中取,缓存中没有则去数据库取,数据库取到结果之后再塞到缓存中去。如果有修改操作,则删除缓存,并且查询一次结果塞到缓存中。

    上面两个方案都是为了解决数据库压力太大问题,两个方案看起来都没有任何问题,但是当两个方案一起实施的时候就会发生问题。

    假设我们需要缓存商品信息,并且使用了主从数据库。

    用户发送一个修改商品信息的请求,那么会去主库中修改商品信息,并且删除缓存,然后从从库中查询商品信息放到缓存中去,由于主从数据库之间同步数据有一定的延迟,所以从从库中查询出来的商品信息可能是未修改前的商品信息,就会将未修改前的商品信息塞到缓存中。

    下一次查询商品信息的时候,会先去缓存中查询,而缓存存在有商品信息(过期的),所以直接返回缓存中的商品信息,这样就导致了缓存和数据库数据不一致的问题。

    2、缓存加有效期

    给缓存加上有效期是最简单的确保数据最终一致性的解决方案,可以对缓存中的数据加一个有效期,那么即使缓存中的数据是过期的,但是也只会影响一段时间的结果,可以保证数据的最终一致性。

    这种缓存加有效期的解决方案虽然可以保证数据最终一致性,但是不可避免的会产生一段时间的脏数据(过期数据),只适用于修改频率较低并且准确性要求不高的使用场景。

    3、双淘汰

    缓存和数据库数据不一致的问题产生的根源就是主从数据库之间同步数据有延迟。

    如果我们在修改商品信息之后不是立马更新缓存,而是等待从数据库从主数据库同步完数据之后再去更新缓存,那么这个问题就解决了。

    所以我们可以在修改商品信息的时候,将修改信息写到主库中,并且删除缓存,然后后将这一条记录添加到一个队列中并且设置一个传入时间。

    另一个线程去遍历队列中的消息记录,当消息记录的延迟时间超过主从数据库之间同步数据的延迟,则消费这一条消息记录,删除缓存,在从库中查询出商品详细信息,再将商品详细信息存到缓存中。

    这个方案的思想是等到主从同步结束之后再去修改缓存中的数据,在数据的最终一致性上比缓存添加有效期上要好很多,但是在两次淘汰之间还是可能会存在脏数据。

    4、双淘汰的优化

    上面双淘汰的机制存在的问题就是在两次淘汰之间如果有查询请求过来还是会去请求从库,从而导致这段时间会存在脏数据。

    那么我们可以基于上面的问题去优化双淘汰方案。

    在修改商品信息之后,先将修改信息写道主库,并且删除缓存,然后添加一个关于这个商品信息的标记到缓存中。

    在收到查询商品信息的请求之后,先去查询缓存,如果缓存中存在数据则直接返回缓存中的数据;

    如果缓存中不存在,则先去查询缓存中是否有关于这个商品信息的标记,如果存在这个标记,表示查询时间是在两次淘汰之间,从库可能还没同步好主库中的数据。那么就从主库中查询商品信息,将查询结果塞到缓存中,并且删除缓存中关于商品详细信息的标记。

    同样有一个线程去遍历队列中的消息记录,当消息记录的延迟时间超过主从数据库之间同步数据的延迟,则消费这一条消息记录。

    消费过程先去查询缓存中有没有这个商品的记录,如果存在表示在两次淘汰之间有过查询请求,从主库中查询到商品详细放到缓存中了,所以可以不做任何操作;如果缓存中不存在,则在从库中查询出商品详细信息,再将商品详细信息存到缓存中,并且删除缓存中关于商品信息的标记。

    这个优化后的双太太方案牺牲了主库的一部分性能,保证了查询数据的一致性。

    5、总结

    上面也只是给出了三种常见的解决方案,还有很多其他的解决方案,目前为止也没有哪种解决方案是万能的,要么牺牲性能,要么牺牲一致性。

    当然了在数据一致性要求很高的常见最好不要去使用缓存,使用缓存主要就是为了性能而不是绝对的一致性。


    喜欢这篇文章的朋友,欢迎扫描下图关注公众号lebronchen,第一时间收到更新内容。
    这里写图片描述

    展开全文
  • 深入理解缓存缓存和数据库一致性

    万次阅读 多人点赞 2019-07-08 23:02:09
    产生原因 主要有两种情况,会导致缓存和 DB 的一致性问题: 并发的场景下,导致读取老的 DB 数据,更新...当然,有一点我们要注意,缓存和 DB 的一致性,我们指的更多的是最终一致性。我们使用缓存只要是提高读...

    GitHub:https://github.com/JDawnF

    产生原因

    主要有两种情况,会导致缓存和 DB 的一致性问题:

    1. 并发的场景下,导致读取老的 DB 数据,更新到缓存中。

    2. 缓存和 DB 的操作,不在一个事务中,可能只有一个操作成功,而另一个操作失败,导致不一致。

    当然,有一点我们要注意,缓存和 DB 的一致性,我们指的更多的是最终一致性。我们使用缓存只要是提高读操作的性能,真正在写操作的业务逻辑,还是以数据库为准。例如说,我们可能缓存用户钱包的余额在缓存中,在前端查询钱包余额时,读取缓存,在使用钱包余额时,读取数据库。

    更新缓存的设计模式

    1.Cache Aside Pattern(旁路缓存)

    这是最常用最常用的pattern了。其具体逻辑如下:

    • 失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。

    • 命中:应用程序从cache中取数据,取到后返回。

    • 更新:先把数据存到数据库中,成功后,再让缓存失效。

    一个是查询操作,一个是更新操作的并发,首先,没有了删除cache数据的操作了,而是先更新了数据库中的数据,此时,缓存依然有效,所以,并发的查询操作拿的是没有更新的数据,但是,更新操作马上让缓存的失效了,后续的查询操作再把数据从数据库中拉出来。而不会像文章开头的那个逻辑产生的问题,后续的查询操作一直都在取老的数据。

    要么通过2PC或是Paxos协议保证一致性,要么就是拼命的降低并发时脏数据的概率,而Facebook使用了这个降低概率的玩法,因为2PC太慢,而Paxos太复杂。当然,最好还是为缓存设置上过期时间。

    2.Read/Write Through Pattern

    在上面的Cache Aside套路中,我们的应用代码需要维护两个数据存储,一个是缓存(Cache),一个是数据库(Repository)。所以,应用程序比较啰嗦。而Read/Write Through套路是把更新数据库(Repository)的操作由缓存自己代理了,所以,对于应用层来说,就简单很多了。可以理解为,应用认为后端就是一个单一的存储,而存储自己维护自己的Cache。

    Read Through

    Read Through 套路就是在查询操作中更新缓存,也就是说,当缓存失效的时候(过期或LRU换出),Cache Aside是由调用方负责把数据加载入缓存,而Read Through则用缓存服务自己来加载,从而对应用方是透明的。

    Write Through

    Write Through 套路和Read Through相仿,不过是在更新数据时发生。当有数据更新的时候,如果没有命中缓存,直接更新数据库,然后返回。如果命中了缓存,则更新缓存,然后再由Cache自己更新数据库(这是一个同步操作)

    下图自来Wikipedia的Cache词条。其中的Memory你可以理解为就是我们例子里的数据库。

    3.Write Behind Caching Pattern

    Write Behind 又叫 Write Back。write back就是Linux文件系统的Page Cache的算法

    Write Back套路,一句说就是,在更新数据的时候,只更新缓存,不更新数据库,而我们的缓存会异步地批量更新数据库。

    这个设计的好处就是让数据的I/O操作飞快无比(因为直接操作内存嘛 ),因为异步,write backg还可以合并对同一个数据的多次操作,所以性能的提高是相当可观的。

    但是,其带来的问题是,数据不是强一致性的,而且可能会丢失(我们知道Unix/Linux非正常关机会导致数据丢失,就是因为这个事)。在软件设计上,我们基本上不可能做出一个没有缺陷的设计,就像算法设计中的时间换空间,空间换时间一个道理,有时候,强一致性和高性能,高可用和高性性是有冲突的。软件设计从来都是取舍Trade-Off。

    另外,Write Back实现逻辑比较复杂,因为他需要track有哪数据是被更新了的,需要刷到持久层上。操作系统的write back会在仅当这个cache需要失效的时候,才会被真正持久起来,比如,内存不够了,或是进程退出了等情况,这又叫lazy write。

    在wikipedia上有一张write back的流程图,基本逻辑如下:

    参照:左耳朵耗子《缓存更新的套路》

    缓存架构设计:

    1.更新缓存 VS 淘汰缓存

    更新缓存:数据不但写入数据库,还会写入缓存;优点:缓存不会增加一次miss,命中率高

    淘汰缓存:数据只会写入数据库,不会写入缓存,只会把数据淘汰掉;优点:简单

    这两者的选择主要取决于“更新缓存的复杂度”。

    例如,上述场景,只是简单的把余额money设置成一个值,那么:

    (1)淘汰缓存的操作为deleteCache(uid)

    (2)更新缓存的操作为setCache(uid, money)

    更新缓存的代价很小,此时我们应该更倾向于更新缓存,以保证更高的缓存命中率

    如果余额是通过很复杂的数据计算得出来的,例如业务上除了账户表account,还有商品表product,折扣表discount

    account(uid, money)

    product(pid, type, price, pinfo)

    discount(type, zhekou)

    业务场景是用户买了一个商品product,这个商品的价格是price,这个商品从属于type类商品,type类商品在做促销活动要打折扣zhekou,购买了商品过后,这个余额的计算就复杂了,需要:

    (1)先把商品的品类,价格取出来:SELECT type, price FROM product WHERE pid=XXX

    (2)再把这个品类的折扣取出来:SELECT zhekou FROM discount WHERE type=XXX

    (3)再把原有余额从缓存中查询出来money = getCache(uid)

    (4)再把新的余额写入到缓存中去setCache(uid, money-price*zhekou)

    更新缓存的代价很大,此时我们应该更倾向于淘汰缓存。

    总之,淘汰缓存操作简单,并且带来的副作用只是增加了一次cache miss,建议作为通用的处理方式。

    2.先操作数据库 vs 先操作缓存

    当写操作发生时,假设淘汰缓存作为对缓存通用的处理方式,又面临两种抉择:

    (1)先写数据库,再淘汰缓存

    (2)先淘汰缓存,再写数据库

    对于一个不能保证事务性的操作,一定涉及“哪个任务先做,哪个任务后做”的问题,解决这个问题的方向是:如果出现不一致,谁先做对业务的影响较小,就谁先执行。

    由于写数据库与淘汰缓存不能保证原子性,谁先谁后同样要遵循上述原则。

    假设先写数据库,再淘汰缓存:第一步写数据库操作成功,第二步淘汰缓存失败,则会出现DB中是新数据,Cache中是旧数据,数据不一致。

    假设先淘汰缓存,再写数据库:第一步淘汰缓存成功,第二步写数据库失败,则只会引发一次Cache miss。

    结论:数据和缓存的操作时序:先淘汰缓存,再写数据库。

    3.缓存架构优化

    上述缓存架构有一个缺点:业务方需要同时关注缓存与DB,主要有两种优化方案:

    一种方案是服务化:加入一个服务层,向上游提供帅气的数据访问接口,向上游屏蔽底层数据存储的细节,这样业务线不需要关注数据是来自于cache还是DB。

    另一种方案是异步缓存更新:业务线所有的写操作都走数据库,所有的读操作都总缓存,由一个异步的工具来做数据库与缓存之间数据的同步,具体细节是:

    (1)要有一个init cache的过程,将需要缓存的数据全量写入cache

    (2)如果DB有写操作,异步更新程序读取binlog,更新cache

    在(1)和(2)的合作下,cache中有全部的数据,这样:

    (a)业务线读cache,一定能够hit(很短的时间内,可能有脏数据),无需关注数据库

    (b)业务线写DB,cache中能得到异步更新,无需关注缓存

    这样将大大简化业务线的调用逻辑,存在的缺点是,如果缓存的数据业务逻辑比较复杂,async-update异步更新的逻辑可能也会比较复杂。

    4.结论:

    (1)淘汰缓存是一种通用的缓存处理方式

    (2)先淘汰缓存,再写数据库

    (3)服务化是向业务方屏蔽底层数据库与缓存复杂性的一种通用方式

    参照:沈剑《缓存架构设计细节二三事》

    缓存和DB一致性的解决方案

    1)先淘汰缓存,再写数据库

    因为先淘汰缓存,所以数据的最终一致性是可以得到有效的保证的。因为先淘汰缓存,即使写数据库发生异常,也就是下次缓存读取时,多读取一次数据库。

    但是,这种方案会存在缓存和 DB 的数据会不一致的情况,参照《缓存与数据库一致性优化》 所说。

    我们需要解决缓存并行写,实现串行写。比较简单的方式,引入分布式锁。

    • 在写请求时,先淘汰缓存之前,获取该分布式锁。

    • 在读请求时,发现缓存不存在时,先获取分布式锁。

    这样,缓存的并行写就成功的变成串行写落。写请求时,是否主动更新缓存,根据自己业务的需要,是否有,都没问题。

    2)先写数据库,再更新缓存

    按照“先写数据库,再更新缓存”,我们要保证 DB 和缓存的操作,能够在“同一个事务”中,从而实现最终一致性。

    基于定时任务来实现

    • 首先,写入数据库。

    • 然后,在写入数据库所在的事务中,插入一条记录到任务表。该记录会存储需要更新的缓存 KEY 和 VALUE 。

    • 【异步】最后,定时任务每秒扫描任务表,更新到缓存中,之后删除该记录。

    基于消息队列来实现

    • 首先,写入数据库。

    • 然后,发送带有缓存 KEY 和 VALUE 的事务消息。此时,需要有支持事务消息特性的消息队列,或者我们自己封装消息队列,支持事务消息。

    • 【异步】最后,消费者消费该消息,更新到缓存中。

    这两种方式,可以进一步优化,可以先尝试更新缓存,如果失败,则插入任务表,或者事务消息。

    另外,极端情况下,如果并发写执行时,先更新成功 DB 的,结果后更新缓存:

     

    • 理论来说,希望的更新缓存顺序是,线程 1 快于线程 2 ,但是实际线程1 晚于线程 2 ,导致数据不一致。

    • 图中一直是基于定时任务或消息队列来实现异步更新缓存,如果网络抖动,导致【插入任务表,或者事务消息】的顺序不一致。

    • 那么怎么解决呢?需要做如下三件事情:

      • 1、在缓存值中,拼接上数据版本号或者时间戳。例如说:value = {value: 原值, version: xxx}

      • 2、在任务表的记录,或者事务消息中,增加上数据版本号或者时间戳的字段。

      • 3、在定时任务或消息队列执行更新缓存时,先读取缓存,对比版本号或时间戳,大于才进行更新。 当然,此处也会有并发问题,所以还是得引入分布式锁或 CAS 操作。

    3) 基于数据库的 binlog 日志

    1、重客户端

    写入缓存:

    • 应用同时更新数据库和缓存

    • 如果数据库更新成功,则开始更新缓存,否则如果数据库更新失败,则整个更新过程失败。

    • 判断更新缓存是否成功,如果成功则返回

    • 如果缓存没有更新成功,则将数据发到MQ中

    • 应用监控MQ通道,收到消息后继续更新Redis。

    问题点:如果更新Redis失败,同时在将数据发到MQ之前的时间,应用重启了,这时候MQ就没有需要更新的数据,如果Redis对所有数据没有设置过期时间,同时在读多写少的场景下,只能通过人工介入来更新缓存。

    读缓存:

    如何来解决这个问题?那么在写入Redis数据的时候,在数据中增加一个时间戳插入到Redis中。在从Redis中读取数据的时候,首先要判断一下当前时间有没有过期,如果没有则从缓存中读取,如果过期了则从数据库中读取最新数据覆盖当前Redis数据并更新时间戳。具体过程如下图所示:

    2、客户端数据库与缓存解耦

    上述方案对于应用的研发人员来讲比较重,需要研发人员同时考虑数据库和Redis是否成功来做不同方案,如何让研发人员只关注数据库层面,而不用关心缓存层呢?请看下图:

    • 应用直接写数据到数据库中。

    • 数据库更新binlog日志。

    • 利用Canal中间件读取binlog日志。

    • Canal借助于限流组件按频率将数据发到MQ中。

    • 应用监控MQ通道,将MQ的数据更新到Redis缓存中。

    可以看到这种方案对研发人员来说比较轻量,不用关心缓存层面,而且这个方案虽然比较重,但是却容易形成统一的解决方案。

    参照: 《技术专题讨论第五期:论系统架构设计中缓存的重要性》

    PS:下面这两种比较实用

    • 先淘汰缓存,再写数据库”的方案,并且无需引入分布式锁。

    • 先写数据库,再更新缓存”的方案,并且无需引入定时任务或者消息队列。

    使用缓存过程中,经常会遇到缓存数据的不一致性和脏读现象。一般情况下,采取缓存双淘汰机制,在更新数据库的淘汰缓存。此外,设定超时时间,例如三十分钟。

    极端场景下,即使有脏数据进入缓存,这个脏数据也最存在一段时间后自动销毁。

    另外,在 DB 主从架构下,方案会更加复杂。详细可以看看 《主从 DB 与 cache 一致性优化》

     

     

     

     

     

     

     

     

     

     

    展开全文
  • 个人想法是考虑到数据的安全,如果说使用缓存来控制比较难,而且缓存性能也会受到很大的限制。 基本操作: 删缓存失败,不去执行update数据库操作 删除缓存成功,更新数据库失败,读的操作会重新更新的缓存中。...

    刚刚刷面试题时遇到,答案是缓存只做失效,不做更新

    为啥呢?个人想法是考虑到数据的安全性,如果说使用缓存来控制比较难,而且缓存性能也会受到很大的限制。

    基本操作:

    删缓存失败,不去执行update数据库操作

    删除缓存成功,更新数据库失败,读的操作会重新更新的缓存中。

    删除缓存成功,更新数据库也成功,读的动作也会将新的数据更新到缓存

    展开全文
  • 缓存和数据库保持一致性主要是指当数据发生更新时如何保证同时更新缓存和数据库的问题。 一致性保证方式 1、设置失效时间,到期自动失效 优点:实现简单。 缺点:有延迟,一旦设置就不可控,存在固定不变的延迟时间...
  • Redis怎么保持缓存数据库一致性

    万次阅读 多人点赞 2018-08-26 09:42:31
    将不一致分为三种情况: 1. 数据库有数据,缓存没有数据; 2. 数据库有数据,缓存也有数据,数据不相等; 3. 数据库没有数据,缓存有数据。   在讨论这三种情况之前,先说明一下我使用缓存的策略,也是...
  • 如何保证缓存数据库一致性

    千次阅读 2020-12-26 16:54:04
    先删除缓存数据库还没有更新成功,此时如果读取缓存缓存不存在,去数据库中读取到的是旧值,缓存一致发生。 解决方案 延时双删 延时双删的方案的思路是,为了避免更新数据库的时候,其他线程从缓存中...
  • 缓存数据库一致性

    千次阅读 2019-04-03 20:05:53
    什么是缓存缓存就是数据交换的缓冲区,针对服务对象的不同(本质就是不同的硬件)都可以构建缓存。 目的是,把读写速度慢的介质的数据保存在读写速度快的介质中,从而提高读写速度,减少时间消耗。 例如: CPU ...
  • 如何保证缓存数据库数据一致性

    千次阅读 2019-07-02 15:34:17
    一般来说,就是如果你的系统不是严格要求缓存+数据库必须一致性的话,缓存可以稍微的跟数据库偶尔有不一致的情况,最好不要做这个方案,读请求写请求串行化,串到一个内存队列里去,这样就可以保证一定不会出现不...
  • 先mark: https://www.cnblogs.com/yanglang/p/9098661.html ...mid=404308725&idx=1&sn=1a25ce76dd1956014ceb8a011855268e&scene=21#wechat_redirec...
  • 缓存数据库一致性问题

    千次阅读 2019-05-11 23:10:41
    最经典的缓存+数据库读写的模式,cache aside pattern 1、Cache Aside Pattern (1)读的时候,先读缓存缓存没有的话,那么就读数据库,然后取出数据后放入缓存,同时返回响应 (2)更新的时候,先删除缓存,...
  • (1)啥时候数据库和缓存中的数据会不一致 (2)不一致优化思路 (3)如何保证数据库缓存一致性
  • 缓存和数据库一致性解决方案

    千次阅读 2019-07-05 14:16:40
    1、采用延时双删策略 在写库前后都进行redis.del(key)...具体的步骤就是:先删除缓存、再写数据库、休眠500毫秒、再次删除缓存 那么,这个500毫秒怎么确定的,具体该休眠多久呢? 需要评估自己的项目的读数据...
  • 如何保证缓存和数据库数据的一致性Java系列2021.pdf
  • Redis缓存数据库双写一致性

    千次阅读 2019-03-02 21:18:13
    保证缓存和数据库一致性主要有两个方面的考虑: 1、读数据时,先读取缓存,如果换成不存在,则读取数据库,再将结果保存在缓存中 2、更新数据时,主要有以下几种策略: (1)先更新数据库,再更新缓存 (2)先删除...
  • 2. 数据库有数据,缓存也有数据,数据不相等; 3. 数据库没有数据,缓存有数据。 在讨论这三种情况之前,先说明一下我使用缓存的策略,也是大多数人使用的策略,叫做 Cache Aside Pattern。简而言之,就是1. 首先...
  • 缓存数据库一致性思考

    千次阅读 2017-02-21 21:13:00
    时隔两年,重新启动这个博客。熟悉又有点陌生,这两年我的技术方向有了很大改变,但...问题:怎么保持缓存数据库一致? 要解答这个问题,我们首先来看不一致的几种情况。我将不一致分为三种情况: 1. 数据库有...
  • Redis缓存数据库一致性解决方案

    千次阅读 2020-11-06 15:13:04
    涉及到数据更新:数据库和缓存更新,就容易出现缓存和数据库间的数据一致性问题: 如果先删了缓存,还没有来得及写MySQL,另一个线程就来读,发现缓存空,则去数据库读取数据写入缓存,此时缓存中为脏数据 如果先写...
  • 怎么保持缓存数据库一致性

    千次阅读 2019-02-26 07:59:28
    1. 数据库有数据,缓存没有数据; 2. 数据库有数据,缓存也有数据,数据不相等; 3. 数据库没有数据,缓存有数据。 在讨论这三种情况之前,先说明一下我使用缓存的策略,也是大多数人使用的策略,叫做 Cache Aside ...
  • 缓存数据库 一致性分析

    千次阅读 2020-09-06 18:16:57
    缓存数据库 一致性分析(双写) 1、1 Read Pattern 读模式 总结: 读的时候,先读缓存缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。 1、2 Write Pattern 写模式 更新与write是一样的,先...
  • 面试题:高并发场景下,如何保证缓存数据库一致性? 问题分析 我们日常开发中,对于缓存用的最多的场景就像下图一样,可能仅仅是对数据进行缓存,减轻数据库压力,缩短接口响应时间。 这种方案在不需要考虑高...
  • 缓存和数据库一致性问题本文讨论的背景是,cache如memcache,redia等缓存来缓存数据库读取出来的数据,以提高读性能,如何处理缓存里的数据数据库数据的一致性是本文讨论的内容:正常的缓存步骤是:1查询缓存数据...
  • 解决缓存数据库一致性问题

    千次阅读 2017-02-21 11:18:01
    2)使用不当,容易引起缓存和数据库数据不一致的问题 3、数据不一致的原因  缓存操作与数据库操作不是原子操作,当一方操作成功、另一方操作失败时就会造成数据不一致问题 4、不同情况下常用处理方法
  • 缓存数据库一致

    2018-07-14 10:15:41
    》中的方案,都会遇到缓存数据库一致的问题。今天聊聊这个问题。 一、数据库主从不一致先回顾下,无缓存时,数据库主从不一致问题。如上图,发生的场景是,写后立刻读:(1)主库一个写请求(主从没同步完成)...
  • 本文主要探讨几种常见的缓存的读写模式,以及如何来保证缓存和数据库的数据一致性。 Cache-Aside Cache-Aside可能是项目中最常见的一种模式。它是一种控制逻辑实现在应用程序中的模式。缓存和数据库直接进行交互...
  • redis缓存数据库一致性问题解决

    万次阅读 多人点赞 2018-03-09 16:30:42
    redis缓存数据库一致性问题解决更多干货分布式实战(干货)spring cloud 实战(干货)mybatis 实战(干货)spring boot 实战(干货)React 入门实战(干货)构建中小型互联网企业架构(干货)一、需求起因假设先写...
  • Redis缓存数据库一致性方案

    千次阅读 2018-03-17 20:23:45
    数据库处理要求强一致实时的数据,例如金融数据、交易数据; redis处理不要求强一致实时的数据,例如网站最热贴排行榜; 二、Cache-Aside模式 Cache-Aside模式的意思是业务代码直接维护缓存,这是最常用...
  •  你只要用缓存,就可能会涉及到缓存数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?  3 详解  一般来说,就是如果你的系统不是严格要求缓存+数据库必须一致性的话,...
  • 首先,缓存由于其高并发高性能的特性,已经在项目中被广泛使用。在读取缓存方面,大家没啥疑问,都是按照下图的流程来进行业务操作。 但是在更新缓存方面,对于更新完数据库,是更新缓存呢,还是删除缓存。又或者...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 233,791
精华内容 93,516
关键字:

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