延迟双删

"延迟双删"是一种 在使用缓存(如 Redis)时保证缓存与数据库一致性 的策略,主要用于解决缓存与数据库之间可能出现的数据不一致问题


一、为什么需要延迟双删?

背景:

在使用缓存时,典型的写流程是:

复制代码
更新数据库 → 删除缓存

高并发下可能会出现脏数据。例如下面这个顺序:

复制代码
线程1 读取缓存(此时缓存存在旧数据)
线程2 更新数据库 + 删除缓存
线程1 把旧数据重新写入缓存(造成脏数据)

最终缓存中保存的仍然是旧数据,数据库是新数据,导致缓存与数据库不一致。


二、延迟双删的核心思想

在第一次删除缓存后,等待一段时间,再删除一次缓存。

流程图:

复制代码
1. 更新数据库
2. 删除缓存(第一次)
3. 休眠一段时间(例如500ms)
4. 再次删除缓存(第二次)

三、延迟双删的流程图示例:

复制代码
用户发起更新请求
        ↓
数据库更新成功
        ↓
第一次删除缓存(此时其他线程如果读到了旧缓存会写回)
        ↓
休眠(等待潜在的写回)
        ↓
第二次删除缓存(把前面写回的旧数据再删掉)

四、代码示例(Java伪代码)

复制代码
public void updateData(String key, Object newData) {
    // 1. 更新数据库
    db.update(key, newData);
    
    // 2. 删除缓存
    redis.del(key);

    // 3. 延迟双删(异步线程中执行)
    new Thread(() -> {
        try {
            Thread.sleep(500); // 500ms 视情况可调
            redis.del(key);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
}

五、延迟双删适用场景

  • 高并发更新数据 且数据一致性要求高。

  • 热点数据存在并发读写的风险

  • 系统已经在使用 Redis 做缓存,但未引入复杂的缓存一致性机制(如消息队列等)。


六、延迟双删优缺点

✅ 优点:

  • 实现简单

  • 能显著降低缓存脏读的概率

  • 无需引入额外中间件(如MQ)

❌ 缺点:

  • 延迟时间不好设置,可能因业务不同而有偏差

  • 不能百分百解决一致性(极端情况下仍然可能失败)

  • 存在一定的资源浪费(多次删除缓存)


七、与其他方案对比

方案 特点 一致性保障 实现复杂度
先删缓存再更新数据库 不推荐,会有并发写丢失问题 简单
更新数据库后删缓存 普通方案,但有并发问题 简单
延迟双删 在前者基础上改进,容错更强 较好 简单
消息队列同步删除 通过MQ异步删除缓存 更好 中等
缓存一致性中间件(如 Canal + MQ) 高一致性保证 最好 复杂

八、总结

延迟双删是一种简单有效的缓存与数据库一致性保护手段,适用于多数读多写少、并发不是极端高的业务系统。对于大规模分布式场景,可结合 Canal、Binlog、消息队列等更强一致性方案。

相关推荐
艾伦~耶格尔4 小时前
【数据结构进阶】
java·开发语言·数据结构·学习·面试
爪洼传承人4 小时前
18- 网络编程
java·网络编程
smileNicky4 小时前
SpringBoot系列之从繁琐配置到一键启动之旅
java·spring boot·后端
祈祷苍天赐我java之术4 小时前
Java 迭代器(Iterator)详解
java·开发语言
David爱编程5 小时前
为什么必须学并发编程?一文带你看懂从单线程到多线程的演进史
java·后端
我命由我123455 小时前
软件开发 - 避免过多的 if-else 语句(使用策略模式、使用映射表、使用枚举、使用函数式编程)
java·开发语言·javascript·设计模式·java-ee·策略模式·js
long3165 小时前
java 策略模式 demo
java·开发语言·后端·spring·设计模式
摇滚侠5 小时前
HTML <iframe> 标签 如何把html写入iframe标签
java
云间月13146 小时前
飞算JavaAI:从智能调度到出行服务的全链路技术升级
java·redis·飞算javaai炫技赛
柏油6 小时前
Spring @Cacheable 解读
redis·后端·spring