2020-09-12 13:57:00
MySQL与Redis保证数据一致性,主要涉及最终一致性和强一致性两种策略,具体实现需结合业务场景权衡性能与数据准确性。以下是详细方案:
一、最终一致性:容忍短时不一致,最终达到一致适用于对实时性要求不高的场景,通过设计减少不一致的时间窗口。
1. 先删除Redis缓存,后更新MySQL删除缓存后,未完成数据库更新时,其他请求发现缓存为空,从数据库读取旧数据并写入缓存,导致脏数据。
双删策略:
删除Redis缓存。
更新MySQL数据库。
延迟一段时间(如1秒)后再次删除Redis缓存(确保其他请求已完成数据库读取并写入缓存)。
读写分离场景:
若MySQL使用主从架构,查询请求可能从从库读取到旧数据。此时需强制查询主库填充缓存。

数据库更新完成后,线程宕机导致缓存未删除,后续请求持续读取旧缓存。
消息队列补偿:
更新数据库后,尝试删除缓存。
若删除失败,将缓存Key发送至消息队列(如RabbitMQ)。
消费者监听队列并重试删除缓存。
缺点:业务代码与补偿逻辑耦合,需额外维护消息队列。

适用于对实时性要求极高的场景,通过技术手段确保缓存与数据库同步更新。
1. 订阅MySQL Binlog实现同步Canal:阿里开源的Binlog解析组件,模拟MySQL从库行为,订阅主库Binlog并解析为JSON格式,推送至消息队列或直接更新Redis。
Maxwell:轻量级Binlog解析工具,支持将数据变更写入Kafka、RabbitMQ等消息队列,再由消费者更新Redis。
MySQL开启Binlog(需配置log-bin=mysql-bin)。
Canal/Maxwell监听Binlog变更事件。
解析变更事件并生成Redis更新命令(如SET key value)。
执行Redis更新操作。

性能开销大,高并发场景下延迟高。
需协调多个系统,实现复杂。
使用主从复制(Master-Slave)或哨兵模式(Sentinel)提高可用性。
读写分离:写请求发往主节点,读请求分散至从节点。
RDB:定时生成数据快照,适合数据恢复但可能丢失最后一次快照后的数据。
AOF:记录所有写操作命令,支持appendfsync always/everysec/no三种模式,平衡性能与数据安全性。
混合模式:结合RDB与AOF,兼顾恢复效率与数据安全。
现象:大量缓存同时失效,请求直接打入数据库,导致数据库崩溃。
解决方案:
随机过期时间:为缓存Key设置随机过期时间,避免集中失效。
多级缓存:使用本地缓存(如Caffeine)与分布式缓存(如Redis)分层存储。
现象:查询不存在的数据,缓存未命中且数据库也无数据,导致每次请求均访问数据库。
解决方案:
布隆过滤器:预存所有可能存在的Key,查询前先过滤非法Key。
空值缓存:对数据库查询为空的Key设置短时间缓存(如1分钟),避免重复查询。
实际选择方案时,需根据业务对一致性的容忍度、系统性能要求及运维成本综合评估。