Redis与数据库一致性面试题:Cache Aside、CDC、版本与补偿
| 问题 | 标准回答 | 原理页 |
|---|---|---|
| Cache Aside怎样读写 | 读先查缓存,未命中查库并回填;写先提交数据库,再删除缓存。数据库是事实源。 | Cache Aside |
| 为什么不直接更新缓存 | 数据库和缓存无法普通本地事务原子提交,更新顺序和并发容易让旧值覆盖新值;删除让后续读从事实源重建。 | Cache Aside |
| 为什么不先删缓存再写库 | 删除后并发读可能查到旧数据库值并回填,随后数据库更新,缓存却长期保持旧值。 | 并发窗口 |
| 先写库再删缓存绝对一致吗 | 不是。极端窗口中读请求可在写提交前读旧值,并在写线程删除后把旧值回填;概率较低但仍要TTL、版本或CDC兜底。 | 极端窗口 |
| 延迟双删是什么 | 写库后立即删除,再等待可能的旧读回填窗口后第二次删除;延迟要覆盖读库与回填耗时,但睡眠和失败使它不是严格证明。 | 延迟双删 |
| CDC怎样修正缓存 | 订阅binlog提交事实,按主键删除或更新缓存,消费位点、重复、乱序和失败需要幂等与监控。 | Binlog CDC |
| 为什么事务提交后再删 | 事务未提交前删缓存,其他读仍可能读到旧库值;应注册afterCommit动作,只在提交成功后删除。 | After Commit |
| 删除缓存失败怎么办 | 记录可靠重试意图或Outbox,异步重试、告警和补偿,TTL最终兜底;不能捕获异常后静默忽略。 | 删除失败 |
| TTL能保证一致吗 | 不能保证实时一致,只限制陈旧值最长生命周期;TTL过长扩大不一致窗口,过短增加回源压力。 | TTL |
| 版本号怎样防旧值回写 | 缓存携带业务版本,原子比较只允许更高或相同合法版本写入;还要处理Key不存在、删除墓碑和版本来源。 | 版本防护 |
| 热点Key怎么重建 | 使用逻辑过期、单飞锁、请求合并或后台刷新,等待者有界;锁只是防击穿,版本仍防止旧值覆盖。 | 热点重建 |
| 本地缓存为什么更难一致 | 每个实例有独立副本,Redis删除不会自动清除本地缓存;需消息失效、短TTL、版本和实例漏通知恢复。 | 本地缓存 |
| 怎样保证读己之写 | 写后短时间绕过缓存读主库、返回新版本Token、会话粘性或等待缓存达到写版本。 | 读己之写 |
| 用户看到旧数据怎么排查 | 对齐数据库版本、Redis值/TTL、删除日志、CDC位点、本地缓存和请求路由,确认旧值在哪一层被回填。 | Runbook |
本章小结
缓存一致性不是选择一个删除顺序就结束,而是事务提交、失败重试、版本、TTL、CDC和排查闭环。
