首页 > 数据库 >缓存与数据库双写一致性几种策略分析

缓存与数据库双写一致性几种策略分析

时间:2023-04-19 16:12:21浏览次数:37  
标签:缓存 策略 数据库 db 更新 场景 一致性 双写

作者:京东零售 于泷

一、背景

在高并发场景中,为防止大量请求直接访问数据库,缓解数据库压力,常用的方式一般会增加缓存层起到缓冲作用,减少数据库压力。引入缓存,就会涉及到缓存与数据库中数据如何保持一致性问题,本文将对几种缓存与数据库保证数据一致性的使用方式进行分析。为保证高并发性能,以下分析场景不考虑执行的原子性及加锁等强一致性要求的场景,仅追求最终一致性。

二、读取过程

• 读缓存

• 如果缓存里没有值,那就读取数据库的值

• 同时把这个值写进缓存中

三、更新过程

更新操作有多种策略,各有优劣,主要针对此场景进行分析

策略1:先更新db,再删除缓存(常用的Cache-Aside Pattern旁路缓存)

问题:

1.如果更新db成功,删缓存失败,将导致数据不一致

2.极端场景,请求A读,B写

1)此时缓存刚好失效 2)A查库得到旧值 3)B更新DB成功

4)B删除缓存 5)A将查到的旧值更新到缓存中

此场景的发生需要步骤2)查db 始终慢于 3)的更新db,才能导致4)先于5)执行,通常db的查询是要快于写入的,所以此极端场景的产生过于严格,不易发生

策略2:先更新db,再更新缓存

问题:

1.并发更新场景下,更新缓存会导致数据不一致

2.根据读写比,考虑是否有必要频繁同步更新缓存,而且,如果构造缓存中数据过于复杂,或者数据更新频繁,但是读取并不频繁的情况,还会造成不必要的性能损耗

此种方式不推荐

策略3:先更新缓存,再更新db

同上,不推荐

策略4:先删缓存,再更新db

先删缓存,虽然解决了策略1中,后删缓存如果失败的场景,但也会发生不一致的问题

例如:请求 A 删除缓存,这时请求B来查,就会击穿到数据库,B读取到旧的值后写入缓存,A正常更新db,由于时间差导致数据不一致的情况

策略5:缓存延时双删

该策略兼容了策略1和策略4,解决了先删缓存还是后删缓存的问题,如策略1中,更新db后删缓存失败和策略4中的不一致场景,该策略可以将延时时间内(比如延时10ms)所造成的缓存脏数据,再次删除。但是,如果延时删缓存失败,策略4中不一致问题还会发生,同时延时的实现,如创建线程,或者引入mq异步,可能会增加系统复杂度问题。

策略6:变种双删,前置缓存过期时间

该策略针对策略1中后删缓存失败的场景,前置一层缓存数据过期时间(具体时间根据自身系统本身评估,如可覆盖db读写耗时或一致性容忍度等),更新db后就算删缓存失败,在expire时间后也能保证缓存中无数据。同时,前置expire失败,或者更新db失败,都不会影响数据一致。

能够解决策略4中的问题:请求 A 删除缓存,这时请求B来查,就会击穿到数据库,B读取到旧的值后写入缓存,A正常更新db,由于时间差导致数据不一致的情况,描述图如下:

本策略中步骤1为expire缓存,不会发生击穿缓存到数据库的情况,数据将直接返回。除非更极端情况,如下图:

expire时间没有覆盖住更新db的耗时,类似策略1中极端场景,此处不赘述

四、总结

对于每种方案策略,各有利弊,但一致性问题始终存在(文章开头排除了原子性和锁),只是发生的几率在一点点慢慢变小了,方案的评估不仅要根据自身系统的业务场景,如读写比、并发量、一致性容忍度,还要考虑系统复杂度,投入产出比等,寻找最合适的方案。

标签:缓存,策略,数据库,db,更新,场景,一致性,双写
From: https://www.cnblogs.com/jingdongkeji/p/17333646.html

相关文章

  • 6.1.4 MySQL缓存策略
    LinuxC/C++服务器MySQL缓存策略大部分场景下MySQL的读要远远大于写的需求的,急需要解决的问题是提升读的性能......
  • ASP.NET Core - 缓存之分布式缓存
    分布式缓存是由多个应用服务器共享的缓存,通常作为访问它的应用服务器的外部服务进行维护。分布式缓存可以提高ASP.NETCore应用的性能和可伸缩性,尤其是当应用由云服务或服务器场托管时。与其他将缓存数据存储在单个应用服务器上的缓存方案相比,分布式缓存具有多个优势。当分发......
  • 缓存空间优化实践
    作者:京东科技董健导读缓存Redis,是我们最常用的服务,其适用场景广泛,被大量应用到各业务场景中。也正因如此,缓存成为了重要的硬件成本来源,我们有必要从空间上做一些优化,降低成本的同时也会提高性能。下面以我们的案例说明,将缓存空间减少70%的做法。场景设定1、我们需要将POJO存储到缓......
  • http 缓存方案
    1、强缓存:强制缓存由Cache-Control,Exipres(HTTP1.0)控制。浏览器直接读本地缓存2、协商缓存:协商缓存由Last-Modified/IfModified-Since,Etag/If-None-Match实现,每次请求需要让服务器判断一下资源是否更新过,从而决定浏览器是否使用缓存,如果是,则返回304,否则重新完整响应。在H......
  • Linux服务器如何清除dns缓存
    DNS缓存是一个临时数据库,用于存储已解释的DNS查询信息。换句话说,每当你访问网站时,你的操作系统和网络浏览器都会保留域名和相应IP地址的记录。这消除对远程DNS服务器重复查询,并允许你的操作系统或浏览器快速解析网站的域名。但是在某些情况下,例如对网络问题进行故障排除或者在更改D......
  • SqlServer 从执行计划缓存发现问题sql
    注意以下sql都较复杂,在数据库中执行时间可能较长,不要执行过于频繁。一、隐式转换sql版本1--找到含有隐式转换且会导致indexseek变为indexscan的语句–findalltheplansandquerywhicharebeingcomparedwithwrongdatatypeinqueriesandthuscasuingtheconversio......
  • 15天玩转redis —— 第七篇 同事的一次缓存操作引起对慢查询的认识
       上个星期同事做一个业务模块,需要将一个80M的数据存入到redis缓存中,想法总是好的,真操作的时候遇到了HSet超时,我们使用的是C#的StackExchange.Redis驱动。<redisCacheClientallowAdmin="true"ssl="false"connectTimeout="5000"abortConnect="false"database="......
  • 【Azure Redis 缓存】Azure Redis 遇见的连接不上问题和数据丢失的情况解答
    问题描述PHP应用再连接AzureRedis服务时,出现ConnectionTimedout。当通过升级提高AzureRedis的性能时候,发现之前的数据丢失了。 问题解答当Redis服务出现Timeout的情况时,可以从Redis服务的指标(Metrics)开始查看,如果出现负载(ServiceLoad)很高的情况,表明当前Redis服务的资源已......
  • 【Azure Redis 缓存】Azure Redis 遇见的连接不上问题和数据丢失的情况解答
    问题描述PHP应用再连接AzureRedis服务时,出现ConnectionTimedout。当通过升级提高AzureRedis的性能时候,发现之前的数据丢失了。 问题解答当Redis服务出现Timeout的情况时,可以从Redis服务的指标(Metrics)开始查看,如果出现负载(ServiceLoad)很高的情况,表明当前Redis服务的......
  • 缓存空间优化实践
    作者:京东科技董健导读缓存Redis,是我们最常用的服务,其适用场景广泛,被大量应用到各业务场景中。也正因如此,缓存成为了重要的硬件成本来源,我们有必要从空间上做一些优化,降低成本的同时也会提高性能。下面以我们的案例说明,将缓存空间减少70%的做法。场景设定1、我们需要将POJO存......