高并发系统中缓存更新到底是先删缓存还是先更新数据库

 更新时间:2026年07月02日 09:33:49   作者:名侦探722  
在Redis缓存系统中,缓存与数据库之间的数据一致性是经典难题,这篇文章主要介绍了高并发系统中缓存更新到底是先删缓存还是先更新数据库的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

一、为什么会有一致性问题

在高并发系统中,数据库通常作为最终数据源,Redis 作为缓存层提升查询性能。典型读流程是:先查缓存,缓存未命中再查数据库,并把结果写入缓存。

问题出现在写请求上。数据库和缓存是两个独立组件,更新操作无法天然保证原子性。只要其中一步失败,或者并发读写交错,就可能出现缓存和数据库数据不一致。

二、两种更新策略

1.先删除缓存,再更新数据库

当线程 1 先删除缓存后,如果在更新数据库的时候阻塞住了,这个时候线程 2 先去读缓存,缓存不存在,然后去数据库中读取数据,读到数据后重建缓存,这个时候缓存中仍然是旧的数据。

所以这种方案一般不推荐。(解决方案看后续的延迟双删模块)

2. 先更新数据库,再删除缓存

这种方案看起来更加合理一些。但是可能会出现短暂的数据不一致,导致读到旧的缓存。不过这种情况一般都是可以接受的,可以保证最终的一致性。

三、延迟双删:解决先删缓存的问题

使用延迟双删缓解解决先删缓存存在的问题。

删除缓存 -> 更新数据库 -> 延迟一段时间 -> 再次删除缓存

第二次删除是为了解决重建的缓存是旧的数据。

为什么要进行延迟删除?

延迟删除的目的是为了防止出现线程 2 还没来得及进行旧数据缓存的重建,导致删除是空的缓存,旧的数据缓存还是被重建了这种情况。但是延迟的时间一般是不太好控制的。

延迟双删保证了最终一致性,解决了重建的是旧数据缓存,请求拿到的是旧的数据的问题。

四、MQ 补偿:解决删除缓存失败

无论是先删除缓存还是先更新数据库,都有可能出现删除缓存失败的情况,为了解决删除缓存失败,可以使用 MQ 做补偿。

更新数据库
删除缓存
如果删除失败,发送 MQ 消息
消费者异步重试删除缓存
多次失败后记录日志/告警

示例伪代码:

public void updateData(Data data) {
    updateDatabase(data);

    try {
        redis.delete(cacheKey);
    } catch (Exception e) {
        mq.send(new CacheDeleteMessage(cacheKey));
    }
}

消费者

public void consume(CacheDeleteMessage message) {
    redis.delete(message.getKey());
}

六、Canal:进一步解耦业务和缓存删除

MQ 补偿虽然能解决失败重试,但业务代码里还是要写删除缓存或发送消息的逻辑。为了进一步解耦,可以使用 Canal 监听 MySQL binlog。

业务只更新 MySQL
MySQL 产生 binlog
Canal 监听 binlog
解析变更表和主键
发送缓存删除消息
消费者删除 Redis

优点:

  • 业务代码不需要关心缓存删除
  • 多个服务修改同一张表,也能统一监听
  • 缓存失效逻辑集中处理
  • 更适合复杂系统

总结

缓存一致性的关键不是追求绝对强一致,而是明确数据库是最终事实来源,缓存是可丢弃的加速层,通过删除缓存、失败重试、TTL 和 binlog 监听等方式保证最终一致。

到此这篇关于高并发系统中缓存更新到底是先删缓存还是先更新数据库的文章就介绍到这了,更多相关高并发系统缓存更新内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • KingbaseES金仓数据库:ksql 命令行从建表到删表实战(含增删改查)

    KingbaseES金仓数据库:ksql 命令行从建表到删表实战(含增删改查)

    本文详细介绍了KingbaseES数据库中使用ksql命令行进行表的创建、查看、数据操作(增删改查)、结构修改以及删除的全生命周期管理,涵盖了表的创建语法、常用数据类型、约束、表结构查看方法、数据操作命令、表结构修改命令以及删除表的操作,还列举了常见问题的解决方案
    2026-01-01
  • 使用sqlplus创建DDL和DML操作技巧

    使用sqlplus创建DDL和DML操作技巧

    这篇文章主要介绍了使用sqlplus创建DDL和DML操作技巧,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-05-05
  • 数据库同步优化技巧分享

    数据库同步优化技巧分享

    这篇文章主要介绍了数据库同步优化技巧分享,需要的朋友可以参考下
    2015-10-10
  • Hive实现连续N天登陆语法实例代码

    Hive实现连续N天登陆语法实例代码

    在用户行为数据分析中,常常需要分析用户的连续登录行为,下面这篇文章主要介绍了Hive实现连续N天登陆语法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2026-04-04
  • Hive日期格式转换方法总结

    Hive日期格式转换方法总结

    这篇文章主要为大家介绍了Hive日期格式转换方法总结,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • dbeaver工具连接达梦数据库的完整步骤

    dbeaver工具连接达梦数据库的完整步骤

    DBeaver数据库连接工具是我用了这么久最好用的一个数据库连接工具,拥有的优点,支持的数据库多、快捷键很赞、导入导出数据非常方便,下面这篇文章主要给大家介绍了关于dbeaver工具连接达梦数据库的完整步骤,需要的朋友可以参考下
    2023-05-05
  • 用计算列实现移动加权平均算法

    用计算列实现移动加权平均算法

    昨天有人让我帮忙写个算移动加权平均的SQL语句,我想了半天终于写出来正确的了。现在发出来供大家参考、讨论。
    2009-09-09
  • sql注入教程之类型以及提交注入

    sql注入教程之类型以及提交注入

    所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,这篇文章主要给大家介绍了关于sql注入教程之类型以及提交注入的相关资料,需要的朋友可以参考下
    2021-07-07
  • Spark SQL操作JSON字段的小技巧

    Spark SQL操作JSON字段的小技巧

    这篇文章主要给大家介绍了关于Spark SQL操作JSON字段的小技巧,文中通过示例代码介绍的非常详细,对大家学习或者使用spark sql具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-04-04
  • SQL SERVER的字段类型说明

    SQL SERVER的字段类型说明

    以下为SQL SERVER 7.0以上版本的字段类型说明。SQL SERVER6.5的字段类型说明请参考
    2008-04-04

最新评论