2022-07-10 16:03:55
MySQL数据库和Redis缓存一致性的更新策略主要包括同步直写、异步缓写、双检加锁、延时双删、先更新数据库再删除缓存等方案,推荐采用“先更新数据库再删除缓存”结合消息中间件的方式实现最终一致性。 以下是具体策略的详细说明:
一、读写缓存策略同步直写策略写入数据库时同步更新Redis缓存,确保两者数据实时一致。适用于对一致性要求极高的场景(如金融交易),但可能因同步操作增加响应延迟。
异步缓写策略允许数据库更新后延迟更新Redis(如物流系统),通过消息队列(RabbitMQ/Kafka)补偿失败操作。适用于容忍短期不一致的场景,可提升系统吞吐量。
通过双重检查和互斥锁避免缓存穿透和并发问题:
先更新数据库,再更新Redis
问题:若Redis更新失败,导致数据不一致。
适用场景:无高并发写入的简单系统。
先更新Redis,再更新数据库
问题:多线程下可能导致Redis与数据库数据永久不一致(如线程1更新Redis后崩溃,未更新数据库)。
风险:高并发场景下极易出现数据错乱。
先删除缓存,再更新数据库
问题:删除缓存后,线程可能读取旧数据库值并回写到Redis,导致不一致。
改进方案:延时双删。
延时双删
流程:
删除Redis缓存;
更新MySQL;
延迟一段时间(如2秒)后再次删除Redis。
问题:延迟时间难以精准控制,且sleep操作降低系统性能。
代码示例:
流程:
更新MySQL;
删除Redis缓存;
若删除失败,通过消息中间件重试。
优势:避免延时操作,结合消息队列实现最终一致性。
完整方案:
更新数据库;
数据库binlog触发订阅程序;
订阅程序提取key并尝试删除Redis;
失败时将数据发送至消息队列;
消费者从队列获取数据并重试删除。
Master写入数据变更到二进制日志(binlog);
Slave通过I/O线程拉取binlog并保存为中继日志(relay log);
SQL线程重放relay log以同步数据。
强制读主库(牺牲高可用性);
延迟缓存删除时间(需评估业务容忍度);
使用中间件(如Canal)监听binlog并触发缓存更新。
总结:推荐采用“先更新数据库,再删除缓存”结合消息中间件的方式,通过异步补偿机制实现最终一致性,兼顾性能与可靠性。对于极端场景,可结合业务特点选择同步直写或分布式锁强化一致性。