高并发场景下,如何保证 Redis 与数据库的一致性?为什么推荐使用“缓存双删策略”?

引言

在高并发系统中,Redis 凭借高性能成为缓存首选。但你是否遇到过这样的问题:数据库更新了,但 Redis 读取的还是老数据?

今天我们就深入剖析高并发场景下的数据一致性问题,并揭示一种被广泛推荐的解决方案 —— 缓存双删策略,帮你彻底解决 Redis
与数据库不同步的问题!


📌一、为什么 Redis 与数据库会出现不一致?

典型的场景如下:

// 1. 先删除缓存
redis.del("user:1001");

// 2. 再更新数据库
update user set name = 'Tom' where id = 1001;

看似完美,但问题出在并发!


⚠️二、三种常见写操作流程及其并发漏洞分析

🔴 场景一:先更新数据库,再删除缓存

update user set name = 'Tom' where id = 1001;
redis.del("user:1001");

并发流程图:

时间线程A(读)线程B(写)
T1读取缓存,命中旧值
T2更新数据库
T3删除缓存
T4返回旧缓存给用户

❌ 缓存中的旧数据未被及时清除,用户读到脏数据!


🟡 场景二:先删除缓存,再更新数据库

redis.del("user:1001");
update user set name = 'Tom' where id = 1001;

并发流程图:

时间线程A(读)线程B(写)
T1删除缓存
T2读取缓存为空
T3读取数据库旧数据
T4写入旧数据到缓存更新数据库

❌ 缓存被写回旧数据,数据库是新数据,数据不一致!


🔵 场景三:先删除缓存 → 更新数据库 → 延迟再删缓存(缓存双删)✅

redis.del("user:1001");
update user set name = 'Tom' where id = 1001;
Thread.sleep(500);
redis.del("user:1001");

并发流程图:

时间线程A(读)线程B(写)
T1删除缓存
T2读取缓存为空
T3查数据库(旧数据)更新数据库
T4写入旧数据到缓存延迟 500ms 后再次删除缓存(清除脏数据)

✅ 缓存虽然短暂写入了旧数据,但被延迟删除彻底清除,最终一致!


✅ 三、为什么推荐缓存双删策略?

  • 第一次删除缓存: 减少读到旧数据的风险
  • 第二次延迟删除: 清除被并发请求误写入的旧缓存
  • 最终保证: Redis 与数据库数据最终一致

🔍 四、完整 Java 实战示例

public void updateUser(User user) {
    String redisKey = "user:" + user.getId();

    // 第一次删除缓存
    redisTemplate.delete(redisKey);

    // 更新数据库
    userMapper.updateById(user);

    // 异步线程延迟再次删除缓存(避免主线程阻塞)
    CompletableFuture.runAsync(() -> {
        try {
            Thread.sleep(500); // 延迟500ms
            redisTemplate.delete(redisKey);
        } catch (InterruptedException e) {
            log.error("延迟删除缓存失败", e);
        }
    });
}

🧠 五、实践注意事项

问题建议
延迟多长时间?300ms~1s,避免主从同步延迟
双删失败怎么办?使用补偿机制,或记录日志重试
多实例服务是否有效?✅ 有效,延迟删除由每个实例独立控制

📚 六、还有哪些一致性方案?

策略说明适用场景
延迟双删最简单有效常规场景
Canal + Binlog 监听实时订阅数据库变更高一致性需求
异步 MQ 通知清缓存确保每次更新都清除缓存分布式场景
分布式事务(TCC/SAGA)保证全链路一致性跨服务更新场景

✅ 七、总结

缓存是性能优化的利器,但数据一致性不能忽视。

  • 更新数据库前后执行两次删除缓存(双删策略)
  • 在高并发下,避免旧数据回写 Redis
  • 适配大多数场景,简单、实用

📢 如果你觉得本文有帮助,欢迎点赞收藏 👍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿Mr.wu

你的鼓励师我创造最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值