精华内容
下载资源
问答
  • 延迟双删
    千次阅读
    2022-06-20 20:38:21

    什么是redis的延迟双删呢?redis的延迟双删是指在并发的情况下,修改了数据的数据,然后缓存的数据没有来的及修改,就已经被线程取到了,所以这时候获取到的数据是不对的。这时候就需要使用延迟双删来做处理。

    简单的来讲就是:先把redis缓存的数据删掉,然后在修改数据库数据,这时候sleep一下(即延迟),然后在把redis缓存的数据删掉,就OK了

    注意sleep休眠的时间不能小于修改数据库数据的时间小,基本上1s就够了。

    更多相关内容
  • 07.MySQL与Redis延迟双删策略

    1.mysql与redis如何实现数据同步问题?
    2.什么是缓存延迟双删策略
    3.为什么不建议使用延迟双删
    4.先删除缓存,在更新db还是?先更新db在删除缓存?
    5.什么是双写一致性协议
    6.并发的情况下如何保证双写一致性问题
    7.分布式锁如何解决双写一致性问题
    8.mysql行锁机制如何解决双写一致性问题
    9.为何说分布式情况下强一致性几乎很难实现

    20点25准时开始

    概述

    作者:余胜军 微信:yushengjun644 QQ644064065

    该内容为原创,未经过允许的情况下 请勿转载!

    在高并发的情况下,我们会使用Redis缓存减轻数据库访问压力,先查询缓存,如果缓存中没有数据在查询数据库,将数据库的数据在缓存到Redis中,如果db数据发生了更新,需要同步到Redis中,同步的过程中需要保证:MySQL与Redis数据一致性问题,mysql与redis数据同步过程中,需要花费短暂的时间,所以会产生短暂的延迟,属于正常现象。

    一致性情况:如果缓存中有数据,需要与MySQL中数据保持一致性;

    img

    String value=getRedisKey(key);//先查询Redis 如果redis中有数据,则不会查询db
    if(!StringUtils.isEmpty(value)){
      return value;
    }
    // 如果redis缓存没有数据,则查询db,将db中的数据放入缓存中。
    UserDo userDb=userMapper.getUser(userId);
    if(userDb==null){
      return null;
    }
    RedisUtils.set(key,userDb); // 将db数据放入到缓存中
    return userDb;
    

    mysql与redis数据如何保证一致性?

    延迟双删策略

    先删除缓存,在更新DB

    无并发的情况

    伪代码:

    deleteMayiktRedis(key);// 先删除缓存
    updateDB(user);// 更新db中的数据
    

    1.如果A请求删除缓存成功,但是更新DB失败呢,导致Redis与mysql数据一致性,另外请求过来有从新查询db数据老的数据放入到缓存中;

    解决办法:

    1.采用MQ异步的形式,先删除缓存在更新db中的数据,MQ消费者如果消费失败了,MQ服务器端自动

    触发重试策略,保证该msg必须消费成功。

    高并发的情况

    img

    1.t1线程先删除缓存;

    2.t2线程读取缓存为null,同步db数据到缓存中;

    3.t1线程更新db中的数据;

    4.t3线程查询缓存中数据是旧数据;

    如何解决该问题:延迟双删策略

    t1线程更新完DB后,让它sleep一段时间,再删除缓存 ;

    ---------延迟双删 谁提出的?不靠谱?

    为何要sleep一段时间,再删除缓存?

    T2线程如果读取到DB旧的数据,再把旧的数据写入缓存,然后,T1线程延迟再进行删除。
    所以,T1 sleep的时间,就需要大于T2读取数据再写入缓存的时间。

    延迟的时间如何确定?

    在业务程序运行时,统计业务逻辑执行读数据和写缓存的操作时间,以此为基础来进行估算。因为这个方案会在第一次删除缓存值后,延迟一段时间再次进行删除,所以称为“延迟双删”。----不推荐大家使用延迟双删

    deleteMayiktRedis(key);// 先删除缓存
    updateMayiktDB(user);// 更新db中的数据
    Thread.sleep(u);// 延迟一段时间,在删除该缓存key
    deleteMayiktRedis(key);// 先删除缓存
    

    先更新DB,在删除缓存

    img

    t1线程 先更新db;

    t2线程查询命中缓存 返回旧的数据;

    t1线程在删除缓存

    假设t1线程更新完db,预计5毫秒删除完缓存key 在5毫秒内 其他线程查询缓存结果还是为旧的数据,但是

    5毫秒后查询缓存结果是为空,在从新将db最新的结果同步到Redis中。

    分布式数据同步的过程中,延迟是非常正常的,所以该情况发生的延迟对业务的影响其实很小。

    但是如果发生了,删除缓存失败呢?

    1.不断重试----如果是在http协议接口中 会导致接口响应变慢 调用该接口 会发生响应超时—

    2.或者通过mq异步的形式同步

    确保缓存删除成功。

    img

    updateMayiktDB(user);// 更新db中的数据
    deleteMayiktRedis(key);// 先删除缓存
    

    方案如何选择?

    绝大多数场景都会将Redis作为只读缓存:

    1.先删除缓存值再更新数据库—更新db完成之后 延迟双删策略 延迟时间多久

    是很难控制的。

    2.也可以先更新数据库再异步 mq消费者删除缓存;----推荐

    3.因为先更新db,在删除缓存,其他线程在读过程中只是短暂读取到数据是旧数据,只要及时的将该缓存key删除,其他线程就可以读取到最新的数据。

    4.而先删除缓存,在更新db 有可能将旧的数据缓存到Redis中,导致其他线程一直查询的数据是为旧的数据,

    需要考虑延迟双删问题,延迟双删时间不是很好控制。

    所以推荐使用 先更新,在删除缓存。

    双写一致性协议原理

    什么是双写?

    updateDB

    updateRedis

    直接更新 Cache

    1.更新完db后,同步更新Redis; 更新db操作与更新redis操作 是一样的 不是 直接删除Redis缓存key 俗称:双写

    例如

    1.updateMayiktDB(user);
    2.updateMayiktRedis(user);
    1.deleteMayiktDB(user);
    2.deleteMayiktRedis(user);
    1.insertMayiktDB(user);
    2.insertMayiktRedis(user);
    

    先更新完db后,在同步到redis的过程中会存在短暂的延迟, 影响的业务其实很小。

    但是如果在并发的情况下做双写会存在同步Redis数据不一致问题。

    并发情况下如何保证双写一致性

    概述:

    在多个线程同时修改db和redis;

    在db 层面 mysql 行锁机制 多个线程 同时修改同一行数据

    最终只会有一个线程能够修改成功;在底层存储引擎层面

    保证数据线程安全性问题。

    例如:

    t1 先执行 updatedb name=xiaowei

    t2 在执行 updatedb name=xiaojun

    最终db层面 name=xiaojun

    t1和t2同时更新Redis

    t2线程 先执行 update redis name=xiaojun

    在执行t1 线程 update redis name=xiaowei

    db层面 name=xiaojun Redis name=xiaowei

    如何解决?锁的形式解决

    1.分布式锁的形式 ----不推荐 效率很低 最终 代码执行 变成单线程。

    2.通过mysql 行锁形式

    img

    t1和t2线程 同时对db数据做修改操作,同时需要更新redis缓存。

    但是在同时更新redis缓存过程中 ,会存在顺序执行问题,导致数据不一致。

    begin;
    t1线程
    updatemayiktDb(name)---mayikt
    updatemayiktRedis(name)---mayikt
    commit/rollback
    begin;
    t2线程
    updatemayiktDb(name)---xiaojun
    updatemayiktRedis(name)---xiaojun
    commit/rollback
    

    解决办法:

    1.分布式锁解决多个线程同时执行双写业务逻辑,最终只会有一个获取到分布式锁线程才可以执行,没有获取到分布式锁线程则阻塞等待,这样确保线程执行双写 不会被其他线程干扰,但是效率非常低;

    2.mysql 行锁实现 ,多个线程同时获取行锁,最终只会有一个线程获取行锁成功,

    获取行锁成功的线程 如果更新Redis 成功,就可以提交事务,如果更新redis 失败

    可以采用重试策略,重试多次更新到redis还是失败的话,直接回滚事务,同时释放行锁,行锁-----提交或者回滚事务。 但是效率非常低;不推荐

    mysql 数据同步到Redis----该网络传输的过程中 需要花费时间

    redis 与mysql 如何保证数据一致性问题

    1.先删除缓存,在更新db-----延迟双删的 不推荐

    2.先更新db,在删除缓存----mq 确保删除缓存 一定成功

    3.双写一致性协议 并发的情况下 结合锁的形式 避免

    数据同步到redis发生了不一致。

    4.canal+kafka+消息顺序一致性—

    推荐mq异步 双写 没有锁的竞争效率比较高 —延迟问题

    展开全文
  • redis的延迟双删策略总结

    万次阅读 2022-03-20 00:35:14
    1、什么是延迟双删延迟双删策略是分布式系统中数据库存储和缓存数据保持一致性的常用策略,但它不是强一致。其实不管哪种方案,都避免不了Redis存在脏数据的问题,只能减轻这个问题,要想彻底解决,得要用到同步...

    1、什么是延迟双删?

            延迟双删策略是分布式系统中数据库存储和缓存数据保持一致性的常用策略,但它不是强一致。其实不管哪种方案,都避免不了Redis存在脏数据的问题,只能减轻这个问题,要想彻底解决,得要用到同步锁和对应的业务逻辑层面解决。

    2、为什么要进行延迟双删?

            一般我们在更新数据库数据时,需要同步redis中缓存的数据,所以存在两种方法:

            第一种方案:先执行update操作,再执行缓存清除。

            第二种方案:先执行缓存清除,再执行update操作。

            这两种方案的弊端是当存在并发请求时,很容易出现以下问题:

            第一种方案:当请求1执行update操作后,还未来得及进行缓存清除,此时请求2查询到并使用了redis中的旧数据。

            第二种方案:当请求1执行清除缓存后,还未进行update操作,此时请求2进行查询到了旧数据并写入了redis。

    3、如何实现延迟双删?

            所以此时我们需要使用第三种方案:先进行缓存清除,再执行update,最后(延迟N秒)再执行缓存清除。

    4、需要注意的点

            上述中(延迟N秒)的时间要大于一次写操作的时间,一般为3-5秒。

            原因:如果延迟时间小于写入redis的时间,会导致请求1清除了缓存,但是请求2缓存还未写入的尴尬。。。

            ps:一般写入的时间会远小于5秒

    5、小结

    • 延迟双删用比较简洁的方式实现 mysql 和 redis 数据最终一致性,但它不是强一致。
    • 延迟,是因为 mysql 和 redis 主从节点数据同步不是实时的,所以需要等待一段时间,去增强它们的数据一致性。
    • 延迟是指当前请求逻辑处理延时,而不是当前线程或进程睡眠延迟。
    • mysql 和 redis 数据一致性是一个复杂的课题,通常是多种策略同时使用,例如:延迟双删、redis 过期淘汰、通过路由策略串行处理同类型数据、分布式锁等等。

    展开全文
  • MySql与Redis延迟双删策略

    千次阅读 2022-02-20 16:31:34
    2. 什么是缓存延迟双删策略? 见第4点先删除缓存再更新db中的延迟双删方案 3. 为什么不建议使用延迟双删? 见第4点先删除缓存再更新db中的方案选择 4. 先更新db再删除缓存 or 先删除缓存再更新db? 先

    个人博客

    欢迎访问个人博客: https://www.crystalblog.xyz/

    备用地址: https://wang-qz.gitee.io/crystal-blog/

    1. MySql与Redis如何实现数据同步问题?

    见第4点先更新db再删除缓存 or 先删除缓存再更新db的详解.

    2. 什么是缓存延迟双删策略?

    见第4点先删除缓存再更新db中的延迟双删方案

    3. 为什么不建议使用延迟双删?

    见第4点先删除缓存再更新db中的方案选择

    4. 先更新db再删除缓存 or 先删除缓存再更新db?

    先更新db, 再删除缓存, 会结合MQ异步删除缓存, 延迟比较高.

    伪代码:

    updateDB(user); // 更新db数据
    sendMqMsgToDeleteRedis(key); // 先删除缓存
    

    如果更新db成功, 但是删除缓存失败如何处理? MQ重试机制, 保证该message消息必须消费成功.

    先删除缓存, 再更新db, 延迟低.

    伪代码:

    deleteRedis(key); // 先删除缓存
    updateDB(user); // 更新db数据
    

    如果A请求删除缓存成功, 但是更新db失败, 其他请求过来又重新查询db的旧数据存入到Redis缓存中, 会导致Redis与mysql数据一致性问题. 如何解决呢, 初始解决方案—延迟双删

    延迟双删方案

    T1线程线删除缓存再更新db , T1线程更新db完成之前T2线程如果读取到db旧的数据, 会再把旧的数据写入Redis缓存, 此时T1线程延迟一段时间后再删除Redis缓存操作. 当其他线程再读取缓存为null时会查询db最新数据重新进行缓存, 保证了Mysql和Redis缓存的数据一致性.

    所以, T1线程sleep的时间, 就需要大于T2线程读取数据再写入Redis缓存的时间.

    延迟时间如何确定?

    在业务程序运行时, 统计业务逻辑执行读取数据和写Redis缓存的操作时间, 以此为基础进行估算. 因为这个方案会在第一次删除缓存值后, 延迟一段时间再次进行删除, 所以称为"延迟双删" . — 不推荐大家使用延迟双删.

    伪代码:

    deleteRedis(key); // 先删除缓存
    updateDB(user); // 更新db数据, 事务未完成
    sleep(seconds); // 延迟一段时间,待其他线程读取db旧数据缓存到Redis完成
    deleteRedis(key); // 再删缓存
    

    延迟双删方案方案如何选择?

    绝大多数场景都会将Redis作为只读缓存:

    (1) 先删除缓存, 再更新db. 更新db完成之前, 其他线程在读取缓存时发现数据为null, 会将旧数据重新缓存到Redis中, 导致其他线程一直查询的数据为旧的数据. 需要考虑延迟双删问题, 延迟双删的时间不是很好控制.

    (2) 也可以先更新db再结合MQ异步删除Redis缓存; 因为先更新db, 再删除缓存, 其他线程在读过程中只是短暂读取到数据(旧数据), 只要及时将该缓存key删除, 其他线程就可以读取到最新的数据.

    所以推荐使用先更新db, 再删除缓存.

    5. 什么是双写一致性协议?

    更新完db后, 同步更新Redis缓存; 更新db操作与更新Redis缓存是一样的, 不是直接删除Redis缓存key, 俗称 “双写”.

    6. 并发的情况下如何保证双写一致性?

    请添加图片描述
    t1线程先更新db, 再更新Redis缓存; 如果t1线程在更新Redis缓存完成之前, t2线程优先完成Redis缓存的更新, 然后t1线程再完成Redis缓存的更新, 导致db数据xiaojun和Redis缓存的数据mayikt不一致问题.

    导致不一致的时间线:

    t1线程更新db – t2线程更新db – t2线程更新缓存 – t1线程更新缓存.

    理想结果的时间线:

    t1线程更新db – t1线程更新缓存-- t2线程更新db – t2线程更新缓存.

    初始解决方案:

    可以将更新db的事务放到更新完缓存后提交(Mysql行锁保证数据一致性). 但是性能很低.

    伪代码:

    begin(transaction); // 开启事务
    updateDB(user); // 更新db
    updateRedis(key); // 更新缓存
    commit(transaction); // 提交或回滚事务
    

    进阶解决方案:

    zookeeper等分布式锁.

    最终解决方案:

    推荐MQ异步双写, 没有锁的竞争, 效率比较高. 但是会有延迟问题. 能够保证最终一致性.

    可以使用canal + kafka + 消息顺序一致性

    请添加图片描述

    7. 分布式锁如何解决双写一致性问题?

    见第6点的并发的情况下如何保证双写一致性?中的进阶解决方案

    8. MySql行锁机制如何解决双写一致性问题?

    见第6点的并发的情况下如何保证双写一致性?中的初始解决方案

    9. 为何说分布式情况下强一致性几乎很难实现?

    保证最终一致性, 见第6点的并发的情况下如何保证双写一致性?中的最终解决方案

    展开全文
  • redis中延迟双删策略

    千次阅读 2022-05-17 14:20:47
    延迟双删执行过程分为: 1.先删除redis中数据 2.执行修改操作 3.延迟5秒 4.再删除redis 延迟5秒是在执行更新数据库操作,数据库的各个子节点不会立马更新数据, 双删的策略就是保证每次在数据修改的时候去把...
  • Mysql与Resi延迟双删策略原理解析

    千次阅读 2020-12-27 21:52:52
    MySQL与Redis延迟双删策略原理解读? 课程内容: 1.MySQL与Redis数据一致性协议方案有那些? 2.到底是先删除缓存?还是先更新数据库? 3.为什么不推荐使用更新数据,在更新缓存? 4.如何利用延迟双删除策略?实现...
  • Redis实现延迟双删存在的问题
  • 浅谈延迟双删策略

    万次阅读 热门讨论 2021-09-09 19:58:28
    在谈延时双删之前我们先来了解一下一般场景下数据库和redis的同步机制 上面这种同步机制会有什么问题? 在我们访问redis时,redis中的数据不是热点数据,即此时
  • 代码实践 | 延迟双删实现

    千次阅读 2021-08-08 19:25:22
    高并发场景,为了提高性能,解决数据库压力,一般数据会对数据进行缓存,减轻数据压力,但是如果使用缓存,会有一个缓存不一致的情况,一般缓存不一致的一种解决方案是延迟双删。 通用延迟器 public class ...
  • redis缓存延迟双删

    千次阅读 2021-09-01 21:00:59
    高并发场景使用redis作为缓存存储数据,当数据更新时,如何保证缓存一致性,延迟双删的策略: 先删除缓存,然后更新数据库数据,休眠sleep,最后再次删除缓存数据。休眠的时间略微大于从数据库查询数据的时间。当...
  • 为什么要延迟双删,来保证缓存一致性
  • redis延迟双删的策略

    千次阅读 2021-03-03 14:09:44
    redis延迟双删的策略 1.为什么要进行延迟双删 一般我们在更新数据库数据时,需要同步redis中缓存的数据 所以存在两种方法: (1)第一种方案:先执行update操作,再执行缓存清除。 (2)第二种方案:先执行缓存清除...
  • 三、延迟双删 3.1 Cache Aside Pattern不一致场景 3.2 延迟双删解决极端场景数据不一致 专栏链接: IT老齐架构300讲笔记 一、为什么不能直接更新缓存 不要考虑去update更新缓存 二、Cache Aside ...
  • 文章目录延迟双删总结流程设置缓存过期时间 延迟双删 这个问题是涉及到缓存redis和主从mysql的数据更新,在高并发中,是很容易出现缓存和数据库之间数据不一致问题的。 如果出现不一致的情况是很危险的,比如我们...
  • 在高并发的场景下,数据库处理数据增改查很是薄弱。有一些数据查询的频率远大于修改频率,就需要使用缓存技术,让先去请求redis,redis存在返回缓存数据,redis不存在就查询数据库,返回数据的同时将数据缓存到...
  • redis延时双删第一次删除的作用是什么呀 redis延时双删第一次删除的作用是什么呀 redis延时双删第一次删除的作用是什么呀
  • 不太完善的办法,下面有延迟双删(有小bug)的办法。 ★★后期询问老师后知道了,需要new一个线程完成延时的操作,当前线程直接相应客户端。★★ 延迟双删实现缓存同步 双写一致性。 所谓缓存同步(双写一致性)当...
  • 先删除缓存,再更新数据库》问题:删除缓存后,更新数据库前会有B线程重新读到旧值,放到redis中,然后A线程再更新数据库,导致数据库更新成功,redis还是旧值 先删除缓存,再更新数据库,再延迟删除缓存》问题延迟...
  • SpringBoot AOP Redis实现延时双删功能实战 一、业务场景 1、此时存在的问题 2、解决方案 3、为何要延时500毫秒? 4、为何要两次删除缓存? 二、代码实践 1、引入Redis和SpringBoot AOP依赖 2、编写自定义aop注解和...
  • redis数据一致性之延时双删详解

    千次阅读 2022-03-23 10:53:28
    在使用redis时,需要保持redis和数据库数据的一致性,最流行的解决方案之一就是延时双删策略,今天我们就来详细刨析一下 注意:要知道经常修改的数据表不适合使用redis,因为双删策略执行的结果是把redis中保存的那...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,702
精华内容 6,280
关键字:

延迟双删

友情链接: chat.rar