关于 Redis 缓存一致

news/2025/3/26 1:58:58/

        为了提升系统性能,常常会引入 Redis 作为缓存。数据通常会存储在持久化的数据源(如 MySQL 数据库)中,同时在 Redis 中保存一份副本。当数据源中的数据发生变化时,如果不能及时同步到 Redis 缓存,或者缓存中的数据更新操作出现异常,就会导致缓存和数据源的数据不一致。这种不一致可能会给业务带来严重影响,比如展示给用户的信息是过时的,或者业务逻辑基于错误的数据进行处理。

缓存不一致的原因:

  • 并发读写问题:在高并发场景下,多个客户端可能同时对缓存和数据源进行读写操作,这就容易造成数据不一致。例如,客户端 A 更新了数据源,但还没来得及更新缓存,此时客户端 B 读取了缓存中的旧数据。
  • 缓存更新失败:在更新数据源后,尝试更新缓存时可能会因为网络问题、Redis 服务异常等原因导致更新失败,从而使缓存和数据源的数据不一致。
  • 缓存过期策略:若缓存设置了过期时间,在缓存过期但还未重新加载数据时,也会出现数据不一致的情况。

缓存模式

Cache - Aside(旁路缓存

  • 读流程
    • 应用程序首先尝试从 Redis 缓存中读取所需数据。
    • 缓存命中(即缓存中存在该数据),则直接返回缓存中的数据,避免了访问数据源的开销,提高了读取性能。
    • 缓存未命中,应用程序会从数据源(如数据库)中读取数据,然后将读取到的数据存入 Redis 缓存,以便后续的读请求可以直接从缓存获取,最后将数据返回给应用程序。
  • 写流程
    • 应用程序先更新数据源中的数据,确保数据源中的数据是最新的。
    • 然后删除 Redis 缓存中对应的数据。这样做的目的是避免缓存中的旧数据影响后续的读操作。当下次有读请求时,由于缓存中没有该数据(缓存未命中),会重新从数据源加载最新数据到缓存中,保证了缓存数据的一致性。
  • 一致性问题及解决
    • 问题:在高并发场景下,可能会出现更新数据库和删除缓存这两个操作不是原子性的问题。例如,线程 A 更新数据库后,在删除缓存之前,线程 B 读取缓存未命中,从数据库读取到旧数据并更新到缓存中,之后线程 A 才删除缓存,此时缓存中又变成了旧数据。
    • 解决:可以使用分布式锁来保证更新数据库和删除缓存这两个操作的原子性,或者采用延迟双删策略,即更新数据库后先删除缓存,然后在一段时间后再次删除缓存,以尽量避免上述问题。

延时双删:在更新数据库之前,先将 Redis 中对应的缓存数据删除。这样做是为了避免在更新数据库的过程中,有其他线程读取到旧的缓存数据。执行数据库的更新操作,将最新的数据写入数据库

        在更新数据库之后,等待一段时间(这个时间要根据业务场景和系统的实际情况来确定),然后再次删除 Redis 中的缓存延时的目的是为了确保在更新数据库和第一次删除缓存之后,可能存在的读取旧数据并更新到缓存的操作已经完成,再次删除缓存可以避免缓存中残留旧数据。


Read/Write - Through(读写穿透)

  • 读流程
    • 应用程序向缓存系统发起读请求。
    • 缓存命中,直接返回缓存中的数据。
    • 缓存未命中,缓存系统会自动从数据源中读取数据,并将数据更新到缓存中,然后再将数据返回给应用程序。这种模式下,应用程序只与缓存系统交互,不需要关心数据是从缓存还是数据源获取的。
  • 写流程
    • 应用程序将数据写入缓存系统。
    • 缓存系统负责将数据同步更新到数据源中。这样可以保证缓存和数据源的数据始终保持一致。
  • 一致性问题及解决
    • 问题缓存系统更新数据源失败时,会导致数据不一致。
    • 解决:可以采用重试机制,当更新数据源失败时,进行多次重试;也可以引入消息队列,将更新操作发送到消息队列中,由专门的消费者进行处理,确保数据最终一致性。

Write - Behind(异步写回)

  • 写流程
    • 应用程序直接将数据写入缓存系统。
    • 缓存系统会异步地将数据更新到数据源中。这种模式可以显著提高写操作的性能,因为应用程序不需要等待数据写入数据源的操作完成。
  • 一致性问题及解决
    • 问题:由于数据是异步更新到数据源的,在更新完成之前,如果有读请求,可能会读取到缓存中的新数据和数据源中的旧数据,导致数据不一致。
    • 解决:可以设置一个较短的缓存过期时间,让缓存中的数据尽快过期,从而促使后续的读请求从数据源获取最新数据;也可以在缓存系统中记录数据的更新状态,在读请求时进行判断,如果数据正在更新到数据源中,则从数据源读取数据。

解决缓存一致性问题的具体策略

缓存失效策略

  • 更新数据源后删除缓存:这是 Cache - Aside 模式常用的方法。在更新数据源后,立即删除对应的缓存数据,让后续的读请求重新从数据源加载最新数据。例如,在一个电商系统中,当商品的价格更新时,先更新数据库中的商品价格,然后删除 Redis 中该商品的缓存信息。
  • 分布式锁保证删除操作原子性:在高并发场景下,为了避免多个线程同时操作缓存和数据源导致的数据不一致问题,可以使用分布式锁。例如,使用 Redis 的 SETNX(SET if Not eXists)命令实现简单的分布式锁,确保在更新数据库和删除缓存这两个操作期间,不会有其他线程干扰。

缓存更新策略

  • 消息队列异步更新:在更新数据源后,发送一条消息到消息队列(如 Kafka、RabbitMQ)中,由专门的消费者从消息队列中读取消息,并更新 Redis 缓存。这样可以将缓存更新操作异步化,提高系统的吞吐量和性能。例如,在一个社交系统中,当用户的个人信息更新时,更新数据库后发送一条消息到消息队列,消费者接收到消息后更新 Redis 中该用户的缓存信息。
  • Redis 事务或 Lua 脚本:对于一些复杂的缓存更新操作,如需要同时更新多个缓存键的情况,可以使用 Redis 的事务或 Lua 脚本来保证操作的原子性。例如,在一个游戏系统中,当玩家升级时,需要同时更新玩家的等级、经验值等多个缓存信息,可以使用 Lua 脚本来保证这些更新操作的原子性。

缓存过期策略

  • 合理设置过期时间:根据数据的更新频率和业务需求,合理设置缓存的过期时间。对于更新频繁的数据,设置较短的过期时间,如几分钟;对于不经常更新的数据,设置较长的过期时间,如几小时甚至几天。例如,在一个新闻系统中,新闻的标题和摘要更新频率较低,可以设置较长的过期时间;而新闻的评论数量更新频率较高,设置较短的过期时间。
  • 主动刷新缓存:在数据更新后,主动刷新缓存中的数据。可以通过定时任务或者在数据更新的业务逻辑中添加刷新缓存的代码来实现。例如,在一个金融系统中,每天收盘后,通过定时任务刷新 Redis 中股票的收盘价等缓存信息。

分布式锁

  • 使用分布式锁:在高并发场景下,使用分布式锁(如 Redis 的 Redlock)来保证对缓存和数据源的操作是线程安全的。例如,在多个服务实例同时对同一个缓存键进行读写操作时,通过 Redlock 保证只有一个服务实例能够获取锁并进行操作,避免出现数据不一致的问题。

http://www.ppmy.cn/news/1583103.html

相关文章

Netty源码—3.Reactor线程模型四

大纲 5.NioEventLoop的执行总体框架 6.Reactor线程执行一次事件轮询 7.Reactor线程处理产生IO事件的Channel 8.Reactor线程处理任务队列之添加任务 9.Reactor线程处理任务队列之执行任务 10.NioEventLoop总结 8.Reactor线程处理任务队列之添加任务 (1)Reactor线程执行一…

带你了解Java无锁并发CAS

带你了解Java无锁并发CAS 在多核处理器时代,并发编程已成为提升系统性能的核心手段。传统的同步机制(如synchronized和ReentrantLock)通过互斥锁实现线程安全,但其存在以下关键问题: 性能损耗:线程阻塞/唤…

常见中间件漏洞攻略-Tomcat篇

一、 CVE-2017-12615-Tomcat put方法任意文件写入漏洞 第一步:开启靶场 第二步:在首页抓取数据包,并发送到重放器 第三步:先上传尝试一个1.txt进行测试 第四步:上传后门程序 第五步:使用哥斯拉连接 二、后…

《Python实战进阶》No26: CI/CD 流水线:GitHub Actions 与 Jenkins 集成

No26: CI/CD 流水线:GitHub Actions 与 Jenkins 集成 摘要 持续集成(CI)和持续部署(CD)是现代软件开发中不可或缺的实践,能够显著提升开发效率、减少错误并加速交付流程。本文将探讨如何利用 GitHub Actio…

1 存储过程学习: 使用DMSQL程序的优点

DMSQL程序具有以下优点: 与SQL语言的完美结合 SQL语言已成为数据库的标准语言,DMSQL程序支持所有SQL数据类型和所有SQL函数,同时支持所有DM对象类型。在DMSQL程序中可以使用SELECT、INSERT、DELETE、UPDATE数据操作语句,事务控制…

“张江引擎 人形启程”,AI 机器人开启上海进化新范式

当AI从虚拟算法跃入物理世界,机器人正以技术攻关、产品迭代、场景落地为着力点,为上海塑造现代化产业体系提供重要支撑。 在张江机器人谷这片创新热土上,青龙机械臂在产线精准起舞,开普勒物流机器人走出仓库化身“物流小哥”&…

AI加速,制造企业如何用数据驱动质量管理数字化变革?

2025年是“十四五”规划收官之年,政府工作报告提出持续推进“人工智能”行动,将数字技术与制造业优势、市场优势结合,推动人工智能在实体经济领域的深度应用。根据工信部规划,“人工智能制造”行动将聚焦行业大模型研发、生产流程…

项目日记 -云备份 -服务端配置信息模块

博客主页:【夜泉_ly】 本文专栏:【项目日记-云备份】 欢迎点赞👍收藏⭐关注❤️ 代码已上传 gitee 目录 前言配置信息文件文件配置类getInstance 获得实例readConfigFile 读取配置信息文件 测试补充 #mermaid-svg-wxyW2tnvC3hMEro7 {font-fam…