高并发下数据一致性问题:数据库+缓存双写模式分析

这篇具有很好参考价值的文章主要介绍了高并发下数据一致性问题:数据库+缓存双写模式分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

随着互联网业务的发展,其中越来越多场景使用了缓存来提升服务质量。从系统角度而言,缓存的主要目标是减轻数据库压力(特别是读取压力)并提高服务响应速度。引入缓存就不可避免会涉及到缓存与业务数据库数据一致性的问题,而不同的业务场景对数据一致性的要求也有所不同。本文将针对常见的数据库+缓存双写模式进行数据一致性分析。

数据库+缓存双写

数据库+缓存双写模式是一种常见的数据处理模式,它结合了数据库和缓存的优势。所以,说白了,数据库+缓存双写就是值,在数据处理过程下,写操作会同时更新数据库和缓存

当数据需要被写入时,首先会将更新操作应用于数据库,确保数据的持久性和一致性。接下来,更新的数据也会被写入缓存,以提高后续读取请求的响应速度。

这种双写模式确保了数据的可靠性和一致性(其实在高并发情况下,并会有数据不一致的情况,后面将详细分析)。读取数据时,系统首先检查缓存,如果缓存中存在所需数据,则直接从缓存中获取,减轻了对数据库的负载。如果缓存中不存在所需数据,系统会从数据库中获取,并将获取到的数据写入缓存,以便将来的读取请求能够从缓存中获得更快的响应。

通过使用数据库+缓存双写模式,系统能够在保持数据一致性的同时,提高读取请求的效率和响应速度。然而,这种模式也增加了系统复杂性,因为需要确保数据库和缓存之间的数据一致性,并处理双写可能带来的同步和并发问题。

更新缓存还是删除缓存?

答案是:删除缓存
原因如下:

  1. 在实际业务中,缓存的数据可能不是直接来自数据库表,也许来自多张底层数据表的聚合。比如上面提到的商品详情信息,在底层可能会关联商品表、价格表、库存表等,如果更新了一个价格字段,那么就要更新整个数据库,还要关联的去查询和汇总各个周边业务系统的数据,这个操作会非常耗时。
  2. 从另外一个角度,不是所有的缓存数据都是频繁访问的,更新后的缓存可能会长时间不被访问(利用大量计算和时间去做更新,最后却没有被访问,不一定有价值),所以说,从计算资源和整体性能的考虑,更新的时候删除缓存,等到下次查询命中再填充缓存,是一个更好的方案。
  3. 系统设计中有一个思想叫 Lazy Loading,适用于那些加载代价大的操作,删除缓存而不是更新缓存,就是懒加载思想的一个应用。

参考:40 经典问题:先更新数据库,还是先更新缓存?

缓存更新(删除)策略

情况1:先删除缓存,后更新数据库 —— 更大概率出现数据不一致

举个例子:
线程1 刚刚 删除了 k = 1的缓存,并且打算去数据库更新k 1 -> 2(注意:数据库更新是一个慢操作);在这个时候,线程2 发现 缓存中 k 不存在,那么线程2 就去数据库中查k,由于线程1更新操作很慢,因此在线程2查询k的时候 线程1并未完成对 k = 2的更新,此时线程2就读到了旧数据k=1,并且线程1还要去更新缓存k = 1(这个过程很快)。过了一会儿,线程1才完成数据库更新k=2,然而此时缓存中k=1,所以数据不一致发生了。

结合下面的图来看(蓝色的条表示操作需要的时间,虚线代表此时DB和Cache的情况)
高并发下数据一致性问题:数据库+缓存双写模式分析

可以发现,在更新DB k = 2的时候,存在很长时间的空窗让其他线程读到旧的数据并且更新旧的数据到缓存,因此这种情况,有很大概率出现数据不一致。

情况2 : 先更新数据库,再删除缓存——减少不一致的发生时间

情况A:读缓在更新完数据库且删缓存之前读到的

线程1查不到缓存,就查数据库k = 2,并且将缓存写入 k = 2,但是此时线程2更新数据库 k = 1,并且删除缓存(还没完成),而假设此时有第三个线程3是在线程2更新数据库完成但删除缓存未完成读到了缓存 k = 2,此时数据就不一致了。但是,由于缓存删除其实很快,这种情况很少。
高并发下数据一致性问题:数据库+缓存双写模式分析

情况B:写缓存是在删缓存之后造成的不一致

线程1查缓存不存在,所以去查DB 得到 k =1 ,然后打算写缓存 k = 1(但是还没完成),此时,线程2更新完数据库 k = 2,打算删除缓存,然而此时线程1完成写缓存k = 1,此时数据不一致了。

解决方案 —— 延迟双删策略

针对这种情况,采用延迟双删策略
刚才的情况是因为写缓存是在删缓存之后造成的不一致,所以我们可以在删缓存之后设置一个定时任务或者延时队列MQ,比如在发送删除缓存命令延迟1秒(由业务决定)之后才真正执行,让写缓存先完成。

异步串行化:解决“先删缓存,后更新DB”情况下的数据不一致问题。

参考:高并发场景下的缓存 + 数据库双写不一致问题分析与解决方案设计

刚才的情况是,还没更新数据库的就查数据库读到旧数据吗?不就是因为读在更新前面了吗?那我就让你排队执行呗。

我们考虑在系统内部维护n个内存队列,更新数据的时候,根据数据的唯一标识,将该操作路由之后,发送到其中一个jvm内部的内存队列中(对同一数据的请求发送到同一个队列)。读取数据的时候,如果发现数据不在缓存中,并且此时队列里有更新库存的操作,那么将重新读取数据+更新缓存的操作,根据唯一标识路由之后,也将发送到同一个jvm内部的内存队列中。然后每个队列对应一个工作线程,每个工作线程串行地拿到对应的操作,然后一条一条的执行。

这样的话,一个数据变更的操作,先执行删除缓存,然后再去更新数据库,但是还没完成更新的时候,如果此时一个读请求过来,读到了空的缓存,那么可以先将缓存更新的请求发送到队列中,此时会在队列中积压,排在刚才更新库的操作之后,然后同步等待缓存更新完成,再读库。

参考:干货 | 携程最终一致和强一致性缓存实践文章来源地址https://www.toymoban.com/news/detail-489917.html

到了这里,关于高并发下数据一致性问题:数据库+缓存双写模式分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • redis和数据库的一致性问题的解决方案

    当前没有框架能够保证redis的数据和数据库的完全一致性,所以需要 我们自己在性能和一致性上作取舍。 下图就是两种在redis缓存数据库内容时的使用。 那么如一个节点的两个图: 缓存的生成,是在首次查询或者缓存过期时间到或者缓存被其他业务删除,进而需要在数据库

    2023年04月08日
    浏览(29)
  • 缓存和数据库一致性

    项目的难点是如何保证缓存和数据库的一致性。无论我们是先更新数据库,后更新缓存还是先更新数据库,然后删除缓存,在并发场景之下,仍然会存在数据不一致的情况(也存在删除失败的情况,删除失败可以使用异步重试解决)。有一种解决方法是延迟双删的策略,先删

    2024年01月17日
    浏览(33)
  • Redis 原理缓存过期、一致性hash、雪崩、穿透、并发、布隆、缓存更新策略、缓存数据库一致性

    redis的过期策略可以通过配置文件进行配置 redis会把设置了过期时间的key放在单独的字典中,定时遍历来删除到期的key。 1).每100ms从过期字典中 随机挑选20个,把其中过期的key删除; 2).如果过期的key占比超过1/4,重复步骤1 为了保证不会循环过度,导致卡顿,扫描时间上限

    2024年02月08日
    浏览(43)
  • Redis和数据库保持数据一致性方案

    Redis和数据库一致性又称为“双写一致性”,在分布式系统中,由于多个节点之间的并发读写操作,可能导致数据不一致的情况发生。本文将着重介绍如何通过使用Redis与数据库相结合的方案来实现数据一致性。 首先,读取数据时都是先查询Redis,命中则直接返回,未命中则先

    2024年02月11日
    浏览(76)
  • 如何保证缓存和数据库的数据一致性

    若数据库更新成功,删除缓存操作失败,则此后读到的都是缓存中过期的数据,造成不一致问题。 同删除缓存策略一样,若数据库更新成功缓存更新失败则会造成数据不一致问题。 若缓存更新成功数据库更新失败, 则此后读到的都是未持久化的数据。因为缓存中的数据是易

    2023年04月19日
    浏览(41)
  • 分布式数据库-事务一致性

    version: v-2023060601 author: 路__ 分布式数据库的“强一致性”应该包含两个方面: serializability(串行) and linearizability(线性一致) ,上述图为“Highly Available Transactions: Virtues and Limitations”论文中对于一致性模型的介绍。图中箭头表示一致性模型之间的关系。对于异步网络上的分

    2024年02月08日
    浏览(39)
  • 如何保证ES和数据库的数据一致性?

    在业务中,我们通常需要把数据库中的数据变更同步到ES中,那么如何保证数据库和ES的一致性呢?通常有以下几种做法: 双写 在代码中,对数据库和ES进行双写,并且先操作本地数据库,后操作ES,而且还需要把两个操作放到一个事务中:  在以上逻辑中,如果写数据库成功

    2024年04月28日
    浏览(32)
  • redis实战-缓存数据&解决缓存与数据库数据一致性

    缓存( Cache),就是数据交换的 缓冲区 ,俗称的缓存就是 缓冲区内的数据 ,一般从数据库中获取,存储于本地代码。防止过高的数据访问猛冲系统,导致其操作线程无法及时处理信息而瘫痪,这在实际开发中对企业讲,对产品口碑,用户评价都是致命的;所以企业非常重视缓存技术,

    2024年02月12日
    浏览(40)
  • 怎样保证数据库和redis里的数据一致性

    使用缓存更新策略:在更新数据库时,同时更新Redis中相应的数据。这可以通过编写代码来实现,在数据库更新操作完成后,同步更新Redis中对应的数据。这可以通过在代码中使用事务来保证更新的原子性,确保数据库和Redis中的数据保持一致。 使用消息队列:可以将数据库更

    2024年02月19日
    浏览(35)
  • Redis如何保证缓存和数据库一致性?

    现在我们在面向增删改查开发时,数据库数据量大时或者对响应要求较快,我们就需要用到Redis来拿取数据。 Redis:是一种高性能的内存数据库,它将数据以键值对的形式存储在内存中,具有读写速度快、支持多种数据类型、原子性操作、丰富的特性等优势。 优势: 性能极高

    2024年01月16日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包