如何保证 Redis 和 MySQL 的数据一致性?

考查重点:缓存失效与最终一致性。读缓存未命中查库回填,写先提交库再删缓存;失效失败可靠重试并设 TTL,接受并监测短暂旧读

本题目录

参考答案

核心回答

常见做法是以 MySQL 为权威数据源,采用 Cache Aside:读时先查 Redis,未命中再查数据库并回填;写时先提交数据库事务,再删除对应缓存。 配合可靠失效重试和 TTL,目标是最终一致,不能保证所有时刻都没有旧读。

需要分别处理三个问题:

  1. 提交后、删除前的窗口:这段时间仍可能命中旧缓存。把删除放在事务提交之后,避免因提前失效而让并发请求在提交前回源旧数据;业务必须明确能否接受这个窗口。
  2. 删除失败或进程退出:不能只在内存里重试。可以把失效事件与业务更新写入同一个数据库事务的 Outbox 表,再异步投递和重试;也可以通过 CDC 订阅已提交的变更触发删除。
  3. 并发旧值回填:读请求可能先读到旧值,等写请求提交并删完缓存后,才把旧值写回。删除重试和 TTL 只能缓解,要求更高时还需设计覆盖读写路径的版本校验或互斥协议。

对于余额、库存校验等不能依赖陈旧值的关键判断,应走权威数据库的事务读写路径,明确隔离与读写语义,不能仅靠缓存双删来保证。

为什么通常先提交数据库,再删缓存?

先删缓存、再写数据库,会主动制造一个缓存未命中窗口:并发读请求可能在数据库更新前读到旧值、回填缓存,随后写请求提交,旧缓存却留下了。

先提交数据库、再删除缓存,能让删除之后发起的回源有机会读到新值,也避免数据库回滚后缓存提前失效。这里的“先写数据库”包括事务提交成功,不是在事务方法里执行完一条更新语句就立刻删缓存。

选择删除而非直接更新,是因为缓存可能由多表数据聚合而来,按需重建可以少做无用计算;并发写请求直接更新缓存时,还可能因到达顺序不同,让旧版本覆盖新版本。但删除并没有消除所有并发窗口。

删除成功了,为什么还会出现旧数据?

关键是读请求取得数据和回填缓存之间也有时间差。下面按发生顺序展示一次交错执行:写请求的操作都成功,缓存仍被迟到的读请求写旧。

flowchart TD
    R[读请求:缓存未命中<br/>从数据库取得旧值 v1] --> W[写请求:提交新值 v2<br/>删除缓存成功]
    W --> L[读请求:迟到回填 v1]
    L --> X[数据库是 v2<br/>缓存却是 v1]

因此,不能仅凭“数据库写得慢、Redis 写得快”就忽略旧值回填;慢查询、网络延迟或线程暂停都可能改变时序。回源若走延迟副本,也可能再次取得旧值。

延迟再删一次,可以清理一部分迟到回填,但固定延迟覆盖不了任意长的暂停,第二次删除本身也可能失败。需要更严格控制时,可让相关读写使用同一协调协议,或根据独立维护的版本水位拒绝旧版本回填。只给写请求加锁,或者只在已被删除的缓存值里保存版本号,都不足以挡住所有迟到回填。

怎样让失效事件不因故障丢失?

“数据库提交成功后发一条消息”仍有缺口:进程可能在提交后、发消息前退出。提交后的回调解决了执行顺序,不能单独解决事件丢失。

**事务消息表(Outbox)**的做法是在一个 MySQL 事务中同时更新业务数据、记录待处理失效事件。事务提交后,后台任务把事件投递出去,消费者删除对应缓存;失败继续重试,并对积压和最终失败告警。删除成功后再确认处理进度,重复删除通常不会把数据改旧,但可能带来额外未命中。

**CDC**则从数据库变更日志获取已提交的变化,映射出受影响的缓存键,再执行删除。它能覆盖不经过当前应用的写入,但要维护订阅位点、延迟、重放和表到缓存键的映射;聚合缓存还要识别一条变更影响哪些结果。

这两种方式可靠衔接了数据库变更与缓存失效任务,仍然是异步链路。它们不能把 MySQL 提交与 Redis 删除变成一个原子操作,也不能自动解决已经执行完删除之后才发生的旧值回填。

TTL 能保证多快一致吗?

TTL 是兜底:未能主动失效的条目最终过期,下次读取再从数据库重建。选择时要同时考虑业务可接受的陈旧时间和回源压力,不能不断给命中的旧值续期。

TTL 限制的是某次写入缓存后的存活时间,并不等于“从数据库更新起最多旧这么久”。迟到回填会重新开始计时;如果回源仍读到旧副本,旧值还可能再次进入缓存。因此应同时监控失效事件延迟、重试积压和陈旧读,而不是只检查是否配置了 TTL。

常见追问

给更新操作加 Redis 锁,能做到强一致吗? 不能自动做到。读请求若不参与同一协议,仍可能读旧或回填旧值;锁的租约、故障切换和进程暂停也要处理。Redis 内部的原子操作同样不能覆盖 MySQL 的事务。

点赞用户放 Redis、计数放 MySQL,也是这套方案吗? 先看哪份数据是权威。如果 Redis 是可重建的查询副本,可以按失效与重建处理;如果点赞只先写 Redis、之后异步落库,就要另外设计可靠事件、幂等消费与对账,不能把它当成普通查询缓存。

参考资料

相关面经

56 篇

美团

Java 后端
秋招二面
查看原面经 →
Redis 与 MySQL 的一致性怎么保证?

百度

后端
实习一面
查看原面经 →
如何保证 Redis 和 MySQL 的数据一致性

百度

Agent 开发工程师
一面
查看原面经 →
redis和数据库不一致怎么办

虎牙

全栈开发
校招秋招一面
查看原面经 →
如何保证 Redis 和 MySQL 的数据一致性

公司未注明

后端开发工程师
查看原面经 →
你提到库存同时存储在 MySQL 和 Redis 中,那么如何保证两者之间的数据一致性?如果要求强一致性,你会采用什么方案?
展开剩余 51 篇面经

字节跳动

后端开发工程师
一面
查看原面经 →
如何保证数据库与缓存的一致性?并发读写时出现旧数据怎么办?

懂车帝

后端开发工程师
秋招一面
查看原面经 →
● 如何保证 Redis 和 MySQL 的双写一致性?

美团

全栈开发实习生
日常实习一面
查看原面经 →
Redis 和数据库的一致性怎么保证?三种方案分别是什么?
追问
缓存和数据库操作的先后顺序怎么选?binlog 方案怎么做?

小红书

面经合集
查看原面经 →
缓存一致性:本地缓存和Redis、Redis和DB之间的一致性怎么保证?

携程

AI 应用开发实习生
实习一面
查看原面经 →
数据库和缓存各有一份数据,数据库发生修改后,怎么让两者保持最终一致?

极兔速递

后端开发工程师
一面
查看原面经 →
点赞用 ZSet 存储用户 DB 存计数,你是怎么保证这个缓存和这个 DB 双写一致的呢?

字节跳动

AI 全栈开发工程师
校招秋招一面
查看原面经 →
追问
你同时用了 MySQL 和 Redis, 会有啥问题吗?
追问
保证 MySQL 和 Redis 的数据一致性的方案有哪些, 了解过没?

蚂蚁集团

面经合集
查看原面经 →
如何保证 Redis 缓存与 DB 数据一致性?

蚂蚁集团

面经合集
查看原面经 →
怎么保证 Redis 缓存和 DB 数据一致

SHEIN

后端开发
二面
查看原面经 →
项目中用Redis设计一个类似于具有事务性的这样一个原子化的操作,那有考虑过比如说数据库和缓存的这个数据怎么一致吗?

去哪儿

后端开发
一面
查看原面经 →
使用 Redis 缓存并访问数据库时,如何保证二者的数据一致性?有哪些常用做法?

度小满

AI 全栈开发
二面
查看原面经 →
MySQL 和 Redis 的数据一致性通常采用什么方案?
你实际工作场景中使用的是哪一种?

携程

AI 应用开发实习生
日常实习一面
查看原面经 →
9.1 数据库更新后如何保证缓存最终一致性
追问
9.2 除 binlog 外还有哪些缓存一致性方案

赛诺贝斯

AI 应用开发
一面
查看原面经 →
redis具体怎么用到,如何更新,如何防止不一致。

百度

后端开发
秋招二面
查看原面经 →
怎么保证redis与数据库的一致性?

去哪儿旅行

AI智能应用开发
校招秋招
查看原面经 →
数据库和redis如何保持数据一致性。

广电数科

Java 开发工程师
实习
查看原面经 →
redis写入数据库的时机
如何保证缓存和数据库的一致性

字节跳动

后端开发工程师
一面
查看原面经 →
MySQL 和 Redis 如何保证一致性?

车300

Java 开发工程师
实习
查看原面经 →
Redis 怎么解决缓存一致性?

字节跳动

后端开发工程师
一面
查看原面经 →
现在这套方案涉及 Redis 往数据库同步,又涉及数据库往 Redis 同步,有没有别的方案可以做得更好一点?还要保证数据不丢失、准确不丢失。

字节跳动

AI 全栈开发工程师
秋招一面
查看原面经 →
怎么保证缓存和数据库的一致性

去哪儿

Agent 应用开发 / 测试开发
秋招
查看原面经 →
Redis 缓存一致性问题解决方案

百度

后端开发工程师
校招秋招二面
查看原面经 →
Redis缓存与数据库之间数据不一致问题的处理方案

游族网络

游戏后端开发
实习一面
查看原面经 →
Redis 缓存成功后直接返回,如果 MySQL 操作失败怎么办?(一致性)

小红书

AI 后端开发
一面
查看原面经 →
数据库缓存一致性

百度

后端开发
秋招一面
查看原面经 →
缓存和数据库数据不一致,怎么保证最终是新的?

拼多多

后端开发工程师
秋招一面
查看原面经 →
缓存一致性怎么保证

滴滴

国际化后端开发
社招一面、二面、三面
查看原面经 →
缓存一致性问题、穿透、雪崩的方案

字节跳动

后端开发实习生
暑期实习一面、二面、三面、四面
查看原面经 →
怎么保证数据库和缓存之间的一致性?

百度

Java 开发工程师(智能客服)
实习二面
查看原面经 →
并发更新缓存时,可能出现什么数据一致性问题?

腾讯

测试开发工程师
实习一面
查看原面经 →
怎么保证Redis和MySQL的数据一致性(答旁路缓存模式,延迟双删)

阿里巴巴

后端开发
日常实习一面
查看原面经 →
Redis和MySQL的数据一致性怎么保证?了解哪些方案?

京东

后端开发工程师(智能运维)
实习暑期一面
查看原面经 →
26 MySQL与Redis一致性是怎么实现的

腾讯

后台开发
查看原面经 →
Cache Aside 模式是怎么解决缓存一致性的?

高德

Agent 后端开发
日常实习一面
查看原面经 →
i. 如何确保Redis的性能和数据一致性,在高并发场景下

腾讯

后端开发工程师(AI)
实习
查看原面经 →
Redis和MySQL是怎么配合使用的?如果有一个点赞,怎么落库,详细说过程?

阿里巴巴

后端开发工程师(AI)
实习一面
查看原面经 →
Redis和MySQL的数据一致性怎么保证?了解哪些方案?

飞牛、网易、米连、迅雷、LiblibAI、百度、阿里巴巴、趣丸、小满科技、京东、腾讯、滴滴、BIGO

面经合集社招
查看原面经 →
缓存一致性怎么保障的

阿里巴巴

AI 应用开发工程师
实习一面
查看原面经 →
数据库缓存了解的深吗,怎么保证一致性
redis实现会话管理,怎么保证redis和数据库中的数据一致 性

美团

全栈
一面
查看原面经 →
Redis和数据库的数据一致性如何保证

蚂蚁集团

AI后端开发
实习一面
查看原面经 →
如果让你用Redis做MySQL的缓存,你会采取什么样的更新策略?

字节跳动

一面
查看原面经 →
mysql和redis都存了什么,数据一致性是怎么保证的
redis里的数据一直在更新,你这个时候怎么补偿呢

网新软件

后端开发工程师
一面、二面
查看原面经 →
缓存一致性

快手

后端开发
日常实习一面
查看原面经 →
d. 引入缓存后,怎么解决缓存和 DB 之间的一致性?

字节跳动

Agent 后端开发实习生
实习暑期一面
查看原面经 →
更新策略?Redis旧数据库新咋办?

阿里巴巴

AI 工程
一面
查看原面经 →
数据库缓存了解的深吗,怎么保证一致性
redis实现会话管理,怎么保证redis和数据库中的数据一致#牛客AI配图神器# 性

美团

后端开发
日常实习一面
查看原面经 →
引入缓存后,怎么解决缓存和 DB 之间的一致性?

龙旗科技

Java 开发
实习一面、二面
查看原面经 →
Redis和数据库数据怎么保证一致性

超星集团

Java开发
春招一面
查看原面经 →
如何保证缓存(Redis)和数据库的一致性?

小鹏汽车

Java 后端
一面、二面
查看原面经 →
数据库与缓存一致性怎么保证?常用的模式有哪些?

MetaApp

后端开发
一面、二面
查看原面经 →
如何保证 Redis 缓存与 MySQL 数据库的数据一致性?
刚刚提到在写操作时加锁,是加什么样的锁?
除了加锁,还有哪些技术手段可以保证缓存数据的一致性?
如果采用“先更新数据库,事务提交成功后再删除缓存”的方案,会有什么问题?

收录题集

1 个来源,共1 份题集

系统设计与后端基础

阿东玩 AI · AgentGuide · 1 条原题

查看题集 →

相关题目

4 题