精华内容
下载资源
问答
  • 2022-03-10 16:21:31

    加缓存无疑是减少数据库、服务器压力的一大神器,缓存里的数据一般都是稳定的,不容易更改的,但是有的时候,某些业务场景需要更改缓存中的内容,这必然就涉及到更改本地数据库中的数据,其中关键的一个点就是保证其数据库和缓存的数据一致保证为最新数据。目前数据同步方案有两种:双写模式失效模式,下面会分别介绍其具体内容和优劣。

    一、双写模式:

    双写模式就是在更改数据库后,在对缓存中的数据进行操作。可能有朋友会想到为什么不先改缓存再改数据库呢?这里分别介绍一下:

    《【58沈剑架构系列】缓存架构设计细节二三事》58沈剑:

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

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

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

    书内说的内容并没有问题,但是没完全考虑好并发请求时的数据脏读问题,让我们再来看看孤独烟老师《分布式之数据库和缓存双写一致性方案解析》:

    先删缓存,再更新数据库

    该方案会导致请求数据不一致

    同时有一个请求A进行更新操作,另一个请求B进行查询操作。那么会出现如下情形:

    (1)请求A进行写操作,删除缓存

    (2)请求B查询发现缓存不存在

    (3)请求B去数据库查询得到旧值

    (4)请求B将旧值写入缓存

    (5)请求A将新值写入数据库

    上述情况就会导致不一致的情形出现。而且,如果不采用给缓存设置过期时间策略,该数据永远都是脏数据。

    所以先删缓存,再更新数据库并不是一劳永逸的解决方案,再看看先更新数据库,再删缓存这种方案怎么样?

    先更新数据库,再删缓存这种情况不存在并发问题么?

    不是的。假设这会有两个请求,一个请求A做查询操作,一个请求B做更新操作,那么会有如下情形产生

    (1)缓存刚好失效

    (2)请求A查询数据库,得一个旧值

    (3)请求B将新值写入数据库

    (4)请求B删除缓存

    (5)请求A将查到的旧值写入缓存

    ok,如果发生上述情况,确实是会发生脏数据。

    然而,发生这种情况的概率又有多少呢?

    发生上述情况有一个先天性条件,就是步骤(3)的写数据库操作比步骤(2)的读数据库操作耗时更短,才有可能使得步骤(4)先于步骤(5)。可是,大家想想,数据库的读操作的速度远快于写操作的(不然做读写分离干嘛,做读写分离的意义就是因为读操作比较快,耗资源少),因此步骤(3)耗时比步骤(2)更短,这一情形很难出现。

    先更新数据库,再删缓存依然会有问题,不过,问题出现的可能性会因为上面说的原因,变得比较低!所以如果不是对数据的实时性要求特别高的话,一般都是先更新数据库再操作缓存。如果非要保证一致性的话,我们一般只强调最终一致性,而不是理想中的完全一致,这个内容稍后会讲。

    言归正传,开始说双写模式。

    双写模式就是对数据库中的内容进行写入新的操作后,再set进缓存中的一份。但是这样做法有一个缺点如图所示:

    线程a,b对数据库中name的name字段修改为name=张三,a修改后去set进入缓存,因为网络波动加服务器机房较远,这次修改需要1.2s 这时再0.2s时候线程b再来进行了操作将name=张三改为name=李四,也去修改缓存,这次很快在0.8s就完成了操作,而0.2s后a对缓存的操作修改完毕,用户看到的还是name等于张三,不过这个数据已经是脏数据了,这就是双写模式的过程和其问题。

    解决办法:对每一个数据加上过期时间,现在错了没事,因为数据稳定存在数据库中,等缓存中的数据过期了,用户请求发现缓存中没有了,则会去查数据库得到最新值并set进入缓存,缺点就是如果业务对数据一致性的要求很高则这种方案不行。当然也可以加锁,保证a修改完后,b才可以进行修改数据库内容然后修改缓存,不过对性能有影响,分布式下Redission的lock是处于阻塞状态,对于cpu有很大损耗。

    二、失效模式

    失效模式就是先对数据库中的内容进行修改,然后对缓存进行操作,这里的操作是删除缓存中的内容而不是修改。

     先说缺点:如图所示,线程a修改完数据库库后,删除缓存,这时候线程b来对数据库进行修改,结果因为这次IO很慢很慢事务还没有提交,线程c进来的时候发现缓存没有数据,就去读取a对数据库更改的数据然后更新到缓存中,如果这次更新操作很快,线程b还没更新完数据库呢这时,并没有什么影响,无非就是更新了一个错误数据,后面线程b对数据库操作完就会删除掉缓存,等到下一个请求进来就可以得到正确数据了。

    对于失效模式还有一种叫延时双删,就是先删缓存、再更新数据库延时500毫秒、更新完再删一次缓存防止在这个写入期间缓存被写入了新的数据。

    缺点:比如线程A删除缓存然后线程B查询数据库获取旧值然后线程B更新了缓存,这时线程A更新数据库并线程A延时删缓存,前三步执行后,数据库和缓存是一致的,相当于没删除。后两部先更新数据库,再删缓存。所以延时双删演变成了先更新数据库,再删除缓存,问题还是没解决。为什么?假设,此时,在第4步执行之前,又来了个查询C,C查询到旧值。第6步:C将旧值插入缓存。此时出现缓存和数据库不一致

    解决方法:1.加锁(系统笨重,不推荐)2.先思考这数据是不是要经常修改,如果经常修改直接读数据库就好了这样比用缓存还要加锁都要好。

    数据库缓存一致性:

    1.如果是用户维度数据(订单数据、用户数据),这种并发几率很小,(因为我们只是注册使用人多,但是不可能某个人在一秒内修改一万次自己的个性签名对吧),所以我们不考虑,缓存数据加上过期时间,每隔一段时间出发读的主动更新即可。

    2.如果是菜单,商品介绍等基础数据,这样的对于一致性要求不高的数据(例如京东发现Iphone13修改了描述,京东也修改,用户又不知道我们什么时候修改)可以使用canal订阅binlog的方式

    3.缓存数据+过期时间一般足以解决大部分业务对于缓存的要求。

    4.通过加锁保证并发读写,写写eider时候按顺序排队。读读无所谓,所以这样的更适合使用读写锁。(业务不关心脏数据,允许临时更改脏数据可忽略)。

    Canal是什么:

    是阿里开源的一个中间件,模拟mysql的从服务器,只要mysql进行了数据变化,就会在binlog中记录,这是canal就把这个更新拿来,然后就自动去把缓存中的数据更新。这样的好处是我们不用关心缓存,只用关系数据库方面即可。

    缺点:加了中间件,又要加一些东西配置。

    一般canal是解决大数据的数据异构问题,比如小A喜欢购买衣服,小B喜欢购买电子产品,她俩都打开购物App,首页推荐的内容一定是不同的。怎么实现呢:假如有一个表记录了每个人浏览了什么类型的商品,cannal就去订阅这个表和数据库的商品表,实时知道那些商品进行了变化然后进行分析计算,生成另外一个异构系统的用户推荐表,然后web就从这个表中拿来数据进行展示推荐,减少了大量的计算。

    总结:

    我们能放入缓存的数据本就不应是实时性的、一致性要求很高的,所以缓存数据的时候要加上过期时间保证每天拿到最新的即可。

    我们不应过度设计,增加系统复杂性。

    遇到实时性、一致性要求高的数据,就应该直接查数据库,即时速度慢一些,(可以使用动静分离增大虚拟机内存等方式提高速度和吞吐量)。

    更多相关内容
  • 数据一致性解决方案

    千次阅读 2022-03-12 21:21:17
    数据一致性解决方案 CAP理论 C:一致性、A:可用性、P:分区容错性 CAP只能满足两个 CA:两阶段提交的严格选举协议 ...副本数据一致性: 一般用于容灾和高可用:副本之间通过同步复制或者异步复制的方式

    数据一致性解决方案

    CAP理论

    C:一致性、A:可用性、P:分区容错性
    CAP只能满足两个
    CA:两阶段提交的严格选举协议
    CP弱A:RAFT协议等多数派选举协议
    AP:GOSSIP等冲突解决协议

    数据一致性

    时间一致性:所有相关数据副本任意时刻数据一致
    事务一致性:事务之行前后数据一致
    应用一致性:分布式事务一致

    BASE理论

    基本可用:允许偶尔失败
    软状态:数据状态要求任意时刻一致
    最终一致性:弱一致性

    数据一致性解决方案

    多副本数据一致性:
    一般用于容灾和高可用:副本之间通过同步复制或者异步复制的方式达到数据一致。
    分布式事务数据一致性:
    本地事务是指数据库的单机事务处理,有点是严格的ACID特性,高效、可靠、状态可以只在资源管理器中维护、应用编程模型简单。缺点:不具备分布式事务处理能力,隔离的最小单位受限于资源管理器。
    分布式事务:事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点上。

    强一致性解决方案:

    一次请求对多个数据源的数据进行完整性以及一致性的操作,满足事务的特性,要么全部成功,要么全部失败,保证原子性以及可见性。
    强一致性通过锁定资源的方式,但是会牺牲性能,使用之前需要谨慎评估。

    XA分布式事务

    XA协议:
    是X/OPEN组织提出的分布式事务规范,该规范主要定义了全局事务管理器(TM)和本地资源管理器(RM)之间的接口,本地资源管理器往往由数据库实现。
    主流的数据库产品都提供了XA接口,XA接口是一个双向的系统接口,在事务管理器以及多个资源管理器之间作为通信桥梁。
    之所以需要XA,是因为在分布式系统中从理论上讲,两台机器是无法达到一致性状态的,因此引入了一个单节点进行协调。
    有全局事务管理器管理的机器可以跨多个资源和进程,负责各个本地资源的提交和回滚,全局事务管理器一般使用XA二阶段提交协议与数据库进行交互。

    二阶段提交(2PC)

    在这里插入图片描述

    准备阶段:
    事务协调者向所有事务参与者发送事务内容,询问是否可以提交事务,并等待参与者回复。
    提交阶段:
    如果协调者收到了参与者的失败信息或者超时信息,直接给所有参与者发送回滚信息进行事务回滚;否则发送提交信息。
    2PC方案实现起来比较简单,但是实际项目中使用比较少
    缺陷:

    • 性能问题:所有参与者在事务提交阶段处于同步阻塞状态,容易造成性能问题;
    • 可靠性问题:如果协调者存在单点故障问题,一旦协调者出现故障,参与者一直处于锁定状态;
    • 数据一致性问题:第二阶段如果发生局部网络问题,一部分收到提交消息,一部分没有收到,会导致数据不一致。

    三阶段提交(3PC)

    在这里插入图片描述

    三阶段提交是在二阶段提交的基础上的改进版本,主要是加入了超时机制,同时在协调者和参与者中都引用了超时机制。
    三阶段是将二阶段里面的准备阶段拆分为两个阶段,插入了一个预提交阶段,这样原先二阶段准备之后,参与者发生崩溃或者错误所引起的问题。
    第一阶段:
    事务协调者向所有事务参与者发送事务内容,询问是否可以提交事务(canCommit),并等待参与者回复。参与者收到请求之后,检查是否可以提交,如果认为可以执行事务操作,返回Yes,并进入预备状态(参与者不执行事务操作),否则返回No。
    第二阶段:
    协调者根据第一阶段中参与者的相应情况来决定是否可以进行基于事务的预提交操作:
    任何一个参与者反馈abord,即中断事务,协调者向所有参与者发送abord,abord或者超时都会中断事务。
    第三阶段:
    第二阶段中所有参与者均返回yes,会向所有参与者发送doCommit请求,参与者收到doCommit请求之后会正式执行事务提交,并释放整个事务期间的占用资源,各参与者向协调者返回完成的消息,协调者收到所有参与者的反馈的ack完成的消息后,完成事务的提交。
    注意:
    在进入第三阶段之后,无论是协调者出现问题,还是协调者与参与者的网络出现问题,都会导致参与者无法收到协调者的请求,此时参与者都会在等待超时之后继续执行事务提交(因为异常的情况毕竟是少数)

    弱一致性解决方案

    弱一致性:复制是异步的,最终一致性是弱一致性的特例,保证用户最终能够读取到某操作对系统特定的数据更新。
    弱一致性为了提高系统的吞吐量,允许一定程度上的数据脏读。

    最终一致性解决方案

    强一致性的技术实现成本很高,运行性能低,很难满足真实业务场景下的高并发需求,在实际的生产环境中,通常采用最终一致性的解决方案。
    最终一致性:不追求任意时刻系统都能满足数据完整且一致的要求,通过一段业务上可接受时间之后,系统能达到数据完整且一致的目标。

    消息队列

    在这里插入图片描述

    建立两个消息topic,一个用来处理正常的业务提交,一个用来处理异常冲正消息。请求服务向正常的topic提交业务请求,如果全部正常,则数据一致;如果出现任何异常,向异常的topic提交业务请求,负责回滚。

    事务消息方案

    在这里插入图片描述

    核心: 消息队列必须支持半事务消息(如RocketMQ),半事务消息提供类似于X/OPEN XA二阶段提交的分布式事务功能,这样能够确保请求服务执行本地事务和发送消息在一个全局事务中,只有本地事务成功执行之后,消息才会被投递。消息一旦被投递,默认设计业务执行必须成功(通过重试机制)。如果因为某些异常导致业务最终执行失败,系统无法自愈。只能通过告警的方式等待人工干预。

    数据订阅方案

    在这里插入图片描述

    核心: 监听数据库的更新日志,并转换成消息流供消费端进行订阅处理。业务订阅是异步的,会存在一定的消息延迟。

    TCC事务补偿

    在这里插入图片描述

    TCC是服务化的二阶段编程模型,尝试(try)、确认(confirm)、取消(cancel)均由业务编码实现。
    try阶段: 尝试执行业务,完成所有业务的检查,实现一致性;预留必须的业务资源,实现准隔离型。
    confirm阶段: 真正执行业务,不做任何检查,仅适用于try阶段预留的业务资源,同时要满足幂等性。
    cancel阶段: 取消执行业务,释放try阶段预留的业务资源,操作要满足幂等性。

    相比于二阶段提交:
    TCC位于业务层服务,二阶段提交位于资源层
    **性能提升: **业务来实现控制资源锁的粒度大小,不会锁定整个资源
    数据最终一致性: 基于confirm和concel的幂等性,保证最终事务完成确认或者取消。
    可靠性: 解决了XA协议的协调者单点故障的问题,由主业务方发起并控制整个业务活动,业务管理器也变成多点,引入集群。
    缺点:
    都要有具体业务实现,业务耦合度较高,提高开发成本。

    saga事务模式

    在这里插入图片描述

    核心思想: 将长事务拆成多个本地短事务,由saga事务协调器进行协调,如果正常结束,则正常完成;如果某个步骤失败,根据相反顺序依次调用补偿操作,达到事务的最终一致性。
    基本协议:

    • saga事务由许多幂等的有序的小事务组成;
    • 每个小事务都有对应的补偿,用于撤销执行后的结果;
      和TCC相比,没有预留动作,直接提交。
      有些场景不适合补偿,比如发送短信,发了之后如果撤销,就得再给用户发送说明撤销,体验较差。
    展开全文
  • Redis 保证数据一致性方案解析

    千次阅读 2022-03-22 23:03:31
    谈谈一致性 一致性就是数据保持一致,在分布式系统中,可以理解为个节点中数据的值是一致的。...最终一致性:最终一致性是弱一致性的一个特例,系统会保证在一定时间内,能够达到一个数据一致的状态。这里之所以将

    谈谈一致性

    一致性就是数据保持一致,在分布式系统中,可以理解为多个节点中数据的值是一致的。

    • 强一致性:这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么,用户体验好,但实现起来往往对系统的性能影响大
    • 弱一致性:这种一致性级别约束了系统在写入成功后,不承诺立即可以读到写入的值,也不承诺多久之后数据能够达到一致,但会尽可能地保证到某个时间级别(比如秒级别)后,数据能够达到一致状态
    • 最终一致性:最终一致性是弱一致性的一个特例,系统会保证在一定时间内,能够达到一个数据一致的状态。这里之所以将最终一致性单独提出来,是因为它是弱一致性中非常推崇的一种一致性模型,也是业界在大型分布式系统的数据一致性上比较推崇的模型

    解决一直性主要有以下几种方案:

    一、先更新数据库,再更新缓存

    这套方案,大家是普遍反对的。为什么呢?有如下两点原因。

    1.1(线程安全角度)

    同时有请求A和请求B进行更新操作,那么会出现

    1. 线程 A 更新了数据库
    2. 线程 B 更新了数据库
    3. 线程 B 更新了缓存
    4. 线程 A 更新了缓存

    这就出现请求A更新缓存应该比请求B更新缓存早才对,但是因为网络等原因,B却比A更早更新了缓存。缓存和数据库的数据不一致了。缓存保存的是老数据,数据库保存的是新数据。这就导致了脏数据,因此不考虑。

    1.2(业务场景角度)

    1. 如果你是一个写数据库场景比较多,而读数据场景比较少的业务需求,采用这种方案就会导致,数据压根还没读到,缓存就被频繁的更新,浪费性能。
    2. 如果你写入数据库的值,并不是直接写入缓存的,而是要经过一系列复杂的计算再写入缓存。那么,每次写入数据库后,都再次计算写入缓存的值,无疑是浪费性能的。显然,删除缓存更为适合。

    二、先删除缓存,再更新数据库

    该方案会导致不一致的原因是。同时有一个请求A进行更新操作,另一个请求B进行查询操作。那么会出现如下情形:

    (1)请求 A 进行写操作,删除缓存
    (2)请求 B 查询发现缓存不存在
    (3)请求 B 去数据库查询得到旧值
    (4)请求 B 将旧值写入缓存
    (5)请求 A 将新值写入数据库

    上述情况就会导致不一致的情形出现。而且,如果不采用给缓存设置过期时间策略,该数据永远都是脏数据。

    那么,如何解决呢?

    2.1 采用延时双删策略

    (1)先淘汰缓存
    (2)再写数据库(这两步和原来一样)
    (3)休眠1秒,再次淘汰缓存
    这么做,可以将1秒内所造成的缓存脏数据,再次删除。

    2.2 那么,这个1秒怎么确定的,具体该休眠多久呢?

    针对上面的情形,读者应该自行评估自己的项目的读数据业务逻辑的耗时。然后写数据的休眠时间则在读数据业务逻辑的耗时基础上,加几百 ms 即可。这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。

    2.3 如果你用了mysql的读写分离架构怎么办?

    ok,在这种情况下,造成数据不一致的原因如下,还是两个请求,一个请求 A 进行更新操作,另一个请求 B 进行查询操作。

    1. 请求 A 进行写操作,删除缓存
    2. 请求 A 将数据写入数据库了,
    3. 请求 B 查询缓存发现,缓存没有值
    4. 请求 B 去从库查询,这时,还没有完成主从同步,因此查询到的是旧值
    5. 请求 B 将旧值写入缓存
    6. 数据库完成主从同步,从库变为新值

    上述情形,就是数据不一致的原因。还是使用双删延时策略。只是,睡眠时间修改为在主从同步的延时时间基础上,加几百 ms。

    2.4 采用这种同步淘汰策略,吞吐量降低怎么办?

    那就将第二次删除作为异步的。自己起一个线程,异步删除。这样,写的请求就不用沉睡一段时间后了,再返回。这么做,加大吞吐量。

    2.5 第二次删除,如果删除失败怎么办?

    这是个非常好的问题,因为第二次删除失败,就会出现如下情形。还是有两个请求,一个请求 A 进行更新操作,另一个请求 B 进行查询操作,为了方便,假设是单库:

    1. 请求 A 进行写操作,删除缓存
    2. 请求 B 查询发现缓存不存在
    3. 请求 B 去数据库查询得到旧值
    4. 请求 B 将旧值写入缓存
    5. 请求 A 将新值写入数据库
    6. 请求 A 试图去删除请求 B 写入对缓存值,结果失败了。

    这也就是说,如果第二次删除缓存失败,会再次出现缓存和数据库不一致的问题。
    如何解决呢?
    具体解决方案,看第三种更新策略的解析。

    三、先更新数据库,再删除缓存(推荐)

    Cache-Aside pattern

    • 失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。
    • 命中:应用程序从cache中取数据,取到后返回。
    • 更新:先把数据存到数据库中,成功后,再让缓存失效。

    3.1 这种情况不存在并发问题么?

    不是的。假设这会有两个请求,一个请求A做查询操作,一个请求B做更新操作,那么会有如下情形产生

    1. 缓存刚好失效
    2. 请求A查询数据库,得一个旧值
    3. 请求B将新值写入数据库
    4. 请求B删除缓存
    5. 请求A将查到的旧值写入缓存

    ok,如果发生上述情况,确实是会发生脏数据。

    3.2 然而,发生这种情况的概率又有多少呢?

    发生上述情况有一个先天性条件,就是步骤(3)的写数据库操作比步骤(2)的读数据库操作耗时更短,才有可能使得步骤(4)先于步骤(5)。可是,大家想想,数据库的读操作的速度远快于写操作的(不然做读写分离干嘛,做读写分离的意义就是因为读操作比较快,耗资源少),因此步骤(3)耗时比步骤(2)更短,这一情形很难出现。

    3.3 如何解决上述并发问题?

    首先,给缓存设有效时间是一种方案。其次,采用策略(二 )里给出的异步延时删除策略,保证读请求完成以后,再进行删除操作。

    3.4 还有其他造成不一致的原因么?

    有的,这也是缓存更新策略(二)和缓存更新策略(三)都存在的一个问题,如果删缓存失败了怎么办,那不是会有不一致的情况出现么。比如一个写数据请求,然后写入数据库了,删缓存失败了,这会就出现不一致的情况了。这也是缓存更新策略(二)里留下的最后一个疑问。

    如何解决?

    四、删除缓存重试机制

    不管是延时双删还是Cache-Aside的先操作数据库再删除缓存,如果第二步的删除缓存失败呢,删除失败会导致脏数据哦~

    删除失败就多删除几次呀,保证删除缓存成功呀~ 所以可以引入删除缓存重试机制

    image.png

    1. 写请求更新数据库
    2. 缓存因为某些原因,删除失败
    3. 把删除失败的key放到消息队列
    4. 消费消息队列的消息,获取要删除的key
    5. 重试删除缓存操作

    五、读取 biglog 异步删除缓存

    重试删除缓存机制还可以,就是会造成好多业务代码入侵。其实,还可以通过**数据库的 binlog 来异步淘汰 key **。

    image.png

    以 mysql 为例 可以使用阿里的 canal 将 binlog 日志采集发送到 MQ 队列里面,然后通过 ACK 机制确认处理这条更新消息,删除缓存,保证数据缓存一致性

    六、总结

    [外链图片转存中…(img-Fn5n3Rul-1647961388551)]

    以 mysql 为例 可以使用阿里的 canal 将 binlog 日志采集发送到 MQ 队列里面,然后通过 ACK 机制确认处理这条更新消息,删除缓存,保证数据缓存一致性

    六、总结

    推荐使用先更新数据库,再删除缓存。只有很低的概率会出现数据不一致的情况,而且使用 redis 就是为了快速,保证强一致性一定会有性能上的损失,只能保证最终一致性。

    展开全文
  • 实现MySQL和Redis数据一致性方案

    千次阅读 2022-02-22 15:51:06
    实现MySQL和Redis缓存一致方案延时双删策略操作步骤示例代码异步更新缓存(基于订阅binlog的同步机制)操作步骤示例代码 延时双删策略 操作步骤 示例代码 异步更新缓存(基于订阅binlog的同步机制) 操作步骤 示例代码...

    什么是一致性

    一致性就是数据保持一致,在分布式系统中一致性代表多个节点的数据保持一致

    • 强一致性:这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么,用户体验性好,但实现起来往往对系统的性能影响大;
    • 弱一致性:这种一致性级别约束了系统在写入成功后,不承诺立即可以读到写入的值,也不承诺多久之后数据能够达到一致,但会尽可能地保证到某个时间级别(比如秒级别)后,数据能够达到一致状态;
    • 最终一致性:最终一致性是弱一致性的一个特例,系统会保证在一定时间内,能够达到一个数据一致的状态。这里之所以将最终一致性单独提出来,是因为它是弱一致性中非常推崇的一种一致性模型,也是业界在大型分布式系统的数据一致性上比较推崇的模型;

    三种缓存使用模式

    • chche-aside
      Cache-Aside Pattern, 即旁路缓存模式。它的提出是为了尽可能地解决缓存与数据库的数据不一致问题。
      cache-aside读流程
      在这里插入图片描述
      读的时候先读缓存,缓存命中的话直接返回数据;缓存没有命中,就去读数据库,然后更新缓存,再返回数据
      cache-aside写请求流程
      在这里插入图片描述
      更新得到时候,先更新数据库,然后再删除缓存。
      当这个数据在下一次需要的时候,使用Cache-Aside模式将会在获取数据的时候,同时从数据仓库中获取数据,并且写到Cache之中
    • Read Through/Write Through
      Read Through流程
      在这里插入图片描述

    Read-Through 实际上只是在Cache-Aside之上进行了一层封装,它会让程序代码变得更加简洁,同时也减少数据源上的负载。
    Wirte Through流
    在这里插入图片描述

    • write-behind
      Write-behind跟Read-Through/Write-Through有很多相似的地方,都是由Cache Provider来负责缓存和数据库的读写。它们又有个很大的不同:Read/Write-Through是同步更新缓存和数据的,Write-Behind则是只更新缓存,不直接更新数据库,通过批量异步的方式来更新数据库
      write behind流程:
      在这里插入图片描述
      这种方式下,缓存和数据库的一致性不强,对一致性要求高的系统要谨慎使用。
      但是它适合频繁写的场景,MySQL的Innodb Buffer Pool机制就是用到这种模式。
    • 操作缓存的时候到底是更新缓存还是删除缓存
      日常开发中我们一般用的是cache-aside模式。但我们注意到cache-aside模式为什么是删除缓存而不是更新缓存
      例子:
      在这里插入图片描述
      线程A先发起一个写操作,第一步先更新数据库;线程B先发起一个写操作,第二步后更新数据库;但是由于网络等原因,线程B先更新了缓存;线程A更新缓存;
      此外,更新缓存相对于删除缓存,还有亮点劣势:
      如果你写入的缓存值,是经过复杂计算才得到的话,更新缓存频率高的话,就浪费性能了;
      在写数据库场景多、读数据场景少的情况下,数据很多时候还没被读取到,又被更新了,这也浪费了性能呢。
    • 双写的情况下,先更新数据库还是先更新缓存
      例子:
      在这里插入图片描述
      线程A发起一个写操作,第一步del cache;此时线程B发起一个读操作,cache miss;线程B继续读DB,读出来一个老数据,此时线程B把老数据设置入cache;线程A写入DB更新数据;
      这里就存在这样的一个问题了:缓存和数据库的数据不一致了。缓存保存的是老数据,数据库保存的是新数据。 因此,Cache-Aside缓存模式,选择了先操作数据库而不是先操作缓存
    • 数据库和缓存数据保持强一致,可以嘛?
      实际上是没有办法做到数据库与缓存达到强一致性
      加锁可以嘛?并发写期间加锁,任何读操作不写入缓存?缓存以及数据库封装CAS乐观锁,更新缓存时通过lua脚本?分布式事务,3PC?TCC?
      其实,这是由CAP理论 决定的。缓存系统适用的场景就是非强一致性的场景,它属于CAP中的AP 。个人觉得,追求绝对一致性的业务场景,不适合引入缓存。

    延时双删策略

    操作步骤

    在这里插入图片描述
    先删除缓存,在更新数据库,再休眠(例如1s),然后删除缓存
    这个休眠的时长,等于读业务逻辑数据的耗时 + 几百毫秒

    删除缓存重试机制

    操作步骤

    在这里插入图片描述
    写请求更新数据库;缓存因为某些原因,删除失败;把删除失败的key放到消息队列;消费消息队列的消息,获取要删除的key;重试删除缓存操作;

    异步更新缓存(基于订阅binlog的同步机制)

    操作步骤

    在这里插入图片描述

    展开全文
  • 保证分布式数据一致性的6种方案

    万次阅读 2018-07-30 17:17:07
    在电商等业务中,系统一般由个独立的服务组成,如何解决分布式调用时候数据一致性?  具体业务场景如下,比如一个业务操作,如果同时调用服务 A、B、C,需要满足要么同时成功;要么同时失败。A、B、C 可能是...
  • 解决缓存和数据库双写数据一致性问题缓存的作用缓存和数据库双写不一致的原因并发引发的一致性问题先更新数据库,后更新缓存先删除缓存,后更新数据库先更新数据库,后删除缓存如何保证「第二步操作失败」的双写一致...
  • 如何保证主从复制数据一致性

    千次阅读 2021-03-15 13:16:34
    导读MySQL主从复制环境中,如何才能保证主从数据一致性呢?关于主从复制现在常用的MySQL高可用方案,十有八九是基于 MySQL的主从复制(replication)来设计的,包括常规的一主一从、双主模式,或者半同步复制(semi-...
  • 微服务系统中的数据一致性,你都会了吗

    万次阅读 多人点赞 2021-09-17 23:11:34
    你好,我是看山。 从单体架构到分布式架构,从巨石架构到微服务...需要注意一下,本文所设计的数据一致性,不是数据副本之间保持数据一致性,而是系统之间的业务数据保持一致性。 本地事务 在早期的系统中,我们可.
  • 浅析数据一致性

    万次阅读 多人点赞 2016-02-19 15:27:38
    什么是数据一致性?  在数据有分副本的情况下,如果网络、服务器或者软件出现故障,会导致部分副本写入成功,部分副本写入失败。这就造成各个副本之间的数据不一致,数据内容冲突。 实践中,导致数据不一致的情况...
  • 背景  可用性(Availability)和一致性(Consistency)是分布式系统的基本问题,先有著名的CAP理论定义过分布式环境下二者不可兼... 在大数据场景下,分布式数据库的数据一致性管理是其最重要的内核技术之一,也...
  • 如果更新支付表成功,远程调用添加选课成功(选课数据库commit成功),最后更新支付表commit失败,此时出现操作不一致。 上边的问题涉及到分布式事务控制。 1、什么是分布式系统? 部署在不同结点上的系统通过网络...
  • ServiceComb中的数据最终一致性方案

    万次阅读 2017-10-30 15:23:37
    数据一致性是构建业务系统需要考虑的重要问题 , 以往我们是依靠数据库来保证数据的一致性。但是在微服务架构以及分布式环境下实现数据一致性是一个很有挑战的的问题。ServiceComb作为开源的微服务框架致力解决...
  • HDFS数据一致性

    千次阅读 2018-09-11 10:22:45
    2.NameNode如何保证元数据一致性 3.校验和 4.为实现高可用,HDFS采用的诸多策略 4.1 冗余副本 4.2 机架感知 4.3 心跳机制 4.4 安全模式 4.5 校验和 4.6 回收站 4.7 元数据保护 4.8 快照机制 ...
  • 问题的起源在电商等业务中,系统一般由个独立的服务组成,如何解决分布式调用时候数据的一致性?具体业务场景如下,比如一个业务操作,如果同时调用服务 A...为了便于讨论问题,先简单介绍下数据一致性的基础理论...
  • 面试官:谈谈Redis缓存和MySQL数据一致性问题

    千次阅读 多人点赞 2020-11-10 12:24:11
    解决方案 可以将查到的null设成该key的缓存对象。 当然,也可以根据明显错误的key在逻辑层就就行验证。 同时,你也可以分析用户行为,是否为故意请求或者爬虫、攻击者。针对用户访问做限制。 其他等等
  • 缓存一致性问题解决方案

    千次阅读 2022-04-07 11:26:30
    通常情况下,我们使用缓存的主要目的是为了提升查询的性能。大多数情况下,是这样使用缓存的: 当数据库有数据更新时,在很长的一段时间内(决定于缓存的...缓存一致性问题没有绝对可靠的方案,我们只能让两者尽量接
  • 如何保证分布式系统数据一致性

    万次阅读 多人点赞 2018-12-24 10:26:05
    面试的时候,有面试官问到:选取你比较熟悉的项目,谈谈如何在做容灾负载的时候数据一致性问题,具体点比如你里面的派单,如何保证一个司机不在同一时间内接到两个订单,然后保证实时性?  一般的解决方案是在派单...
  • 谈谈如何确保数据一致性

    千次阅读 2019-12-10 11:30:01
    谈谈如何确保数据一致性数据库必须具备的四个特性背景什么是接口的幂等性?幂等性在哪里会用到?技术方案总结 数据库必须具备的四个特性 1:原子性:事务包含的所有操作要么全部成功,要么全部失败回滚;成功必须要...
  • 数据一致性问题 写作背景:看了些视频,网上也看了很篇文章,感觉写得都很片面,不是很全,所以我整体总结了一些,我不喜欢重复造轮子,对于网上很篇复制机类型的文章(很文章所有字体相同)且很不正确严重...
  • 保证分布式系统数据一致性的6种方案

    万次阅读 多人点赞 2016-04-19 22:57:20
    保证分布式系统数据一致性的6种方案
  • 在满足实时性的条件下,不存在两者完全保存一致的方案,只有最终一致性方案,这里直接给出最终结论: 实时一致性方案:采用“先写 MySQL,再删除 Redis”的策略,这种情况虽然也会存在两者不一致,但是需要满足的...
  • 如何保证数据一致性、常见的缓存设计模式有哪些?
  • 高并发下如何保证数据一致性常用方法(JMM篇)

    万次阅读 多人点赞 2020-03-12 15:43:14
    最近复习了一下JMM的相关内容,总结了下如何处理线程间访问共享变量带来的数据一致问题的解决方案及原理说明,主要使用到的方法有synchronized关键字、volatile关键字、ReentrantLock同步锁、java.util....
  • 数据一致性问题

    万次阅读 2018-09-18 10:44:36
    2.一致性,在事务开始之前和结束之后,数据完整性不被破坏。 3.隔离性,允许并发事务对数据同时进行读写。防止个事务交叉执行而导致数据不一致。事务隔离分为读未提交、读提交、可重复读和串行化。 4.持久性,...
  • 细说分布式下的数据一致性

    万次阅读 2018-08-29 11:21:47
    细说分布式下的数据一致性 名词解释 强一致性 最终一致性 XA事物 JDBC事物、JTA事物 TCC 产生场景 单一数据库、单一系统无法支撑业务和数据的增长而出现拆分化的演进,数据存储于不同的事物管理单元但又要...
  • 数据库读写分离主要解决高并发...这就是读写分离数据库数据一致的根本原因。 下面给出两种方案去解决这个问题: 缓存标记法 上图流程: 1)A发起写请求,更新了主库,再在缓存中设置一个标记,代表此数据已经更新,

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 373,436
精华内容 149,374
关键字:

多用户数据一致性方案