Redis 和 Mysql 数据库数据如何保持一致性

一、操作

我们在实际项目中经常会使用到Redis缓存用来缓解数据库压力,但是当更新数据库时,如何保证缓存及数据库一致性,一般我们采用延时双删策略。

目前系统中常用的做法是一个查询接口,先查询Redis,如果不存在则查询数据库,并将结果放入到Redis中。

为什么是删除缓存,而不是更新缓存呢?主要是如果缓存的内容是带有树型结构或者List,Map,那么更新其中一个内容相对较慢。

本文所讲操作,均是按照如果缓存不存在,查询数据库后,再放入Redis。

二、 常见更新策略

  • 1 先删缓存,再更新数据库

  • 2 先更新数据库,再删除缓存

  • 3 普通双删

  • 4 延迟双删

三、图解

1 、先删缓存,再更新数据库

线程A删除缓存数据,此时还没更新数据库

线程B查询缓存没有数据,查询数据库还是旧数据,放入缓存

线程C及其他线程使用旧缓存数据,缓存和数据库不一致

2、先更新数据库,再删除缓存

线程A更新数据库,此时还没有删除缓存

线程B及其他线程此时使用的还是旧缓存数据,和数据库内容不一致

3 、普通双删

线程A先删除缓存,再更新数据库,再删除缓存

线程B查询缓存没有数据,在线程A更新数据库之前,查询到旧数据,此时系统时间片切换到线程A执行删除缓存,之后又轮到线程B放入缓存旧数据

线程C针对于线程A,查询缓存没有数据,查询到旧数据,放入缓存旧数据

都不能满足缓存和数据一致性。

4、延迟双删

线程A先删除缓存,之后更新数据库

线程B和线程C发现缓存没数据,查询数据库。线程B查询到的是旧数据,线程C查询到的是新数据。之后纷纷放入缓存

线程A延时3-5秒(时间一般要大于SQL执行时间+线程切换执行时间100ms足够),再将缓存删除。之后其他线程再查询缓存,发现没数据,再次查询数据库及放入缓存都是新数据

极端情况就是线程D,所以延时双删还是不一定能保证缓存及数据一致。

四、总结:

1、加锁

在发现缓存没有数据后,在执行查询数据库前,对该Key进行加锁,查询数据库并放入缓存后再解锁,这样可以避免缓存击穿问题,当某个redis数据不存在时,大量线程并发查询数据库。

在需要执行双删前,对该Key进行加锁,之后执行删除缓存,更新数据库,放入新数据到缓存,在解锁。保证缓存和数据一致性。

加锁的Key都需要设置过期时间,避免因为宕机造成死锁。

2、使用Canal 分布式数据库同步工具,结合mq中间件

相关推荐
阿标在干嘛21 小时前
政策平台的推送系统:消息队列、定时任务、AB测试的工程实践
服务器·数据库·ab测试
Upsy-Daisy21 小时前
Hermes Agent 学习笔记 02:安装、配置与第一次运行
java·前端·数据库
小二·21 小时前
Redis 7 分布式缓存架构实战
redis·分布式·缓存
Tongpao_SSDHDD1 天前
希捷酷鹰ST6000VX008实测解析:中小安防监控高性价比存储方案
大数据·数据库·人工智能
蓝鸟19741 天前
Oracle超大DMP备份文件瘦身、日志精简、磁盘空间优化实战方案日志
数据库·oracle·数据库运维·生产运维实战·oracle避坑·磁盘空间优化·oracle日志清理
梦想的旅途21 天前
企业微信外部群主动调用:RPA 接口与官方 API 的技术边界
网络·mysql·自动化·企业微信·rpa
金融支付架构实战指南1 天前
CQRS + 命令模式 + 事件驱动 + 数据库持久化
数据库·ddd·命令模式·领域驱动模型
sevenll071 天前
DocKit agentic MongoDB GUI 客户端 - 用自然语言和你的数据对话
数据库·mongodb·nosql·agent·桌面客户端
团象科技1 天前
从一线实操案例拆解不同出海团队落地海外VPS运维独立站的路径细节
大数据·数据库·人工智能
小马爱打代码1 天前
框架 - 组件 - 中间件:生产级参数配置指引
数据库·中间件