MySQL 与 Redis 数据一致性保证方案

讲述链条

延迟双删问题 → 缓存击穿场景 → 热点数据三级防护 → Canal + Binlog 方案 → 最终一致性实现

核心表述

MySQL 与 Redis 保证一致性的传统方案是延迟双删:先删除缓存,更新数据库,延迟 500ms 后再删除缓存。但这个方案在热点数据场景下存在缓存击穿问题:延迟期间缓存为空,大量请求同时发现缓存 MISS,全部打到数据库造成压力。

针对热点数据,我们采用三级防护体系。Level 1 使用本地缓存 Caffeine 防止 Redis 过载;Level 2 是 Redis 分布式缓存;Level 3 是数据库查询,加分布式锁 Redisson RLock 防止击穿,使用 tryLock 尝试加锁最多等待 100ms,抢到锁的线程负责查询数据库并重建缓存,其他线程等待后重试。重建缓存时设置随机过期时间防止缓存雪崩,并缓存空对象防止缓存穿透。

更优雅的方案是 Canal + Binlog。Canal Server 伪装成 MySQL Slave 订阅 Binlog,解析 INSERT/UPDATE/DELETE 事件后通知应用客户端异步更新 Redis。这样更新数据库时直接覆盖缓存而非删除,不会出现”缓存不存在”的情况,空窗期从 500ms 缩短到 10-100ms,几乎无感知。业务代码只需更新数据库,Canal 自动同步到 Redis,实现最终一致性。