高并发架构系列:Redis缓存和MySQL数据一致性方案详解

本文涉及的产品
RDS Agent(兼容OpenClaw),2核4GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS DuckDB + QuickBI 企业套餐,8核32GB + QuickBI 专业版
简介: 一、需求起因 在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节。所以,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问MySQL等数据库。 这个业务场景,主要是解决读数据从Redis缓存,一般都是按照下图的流程来进行业务操作。

一、需求起因

在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节。所以,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问MySQL等数据库。

这个业务场景,主要是解决读数据从Redis缓存,一般都是按照下图的流程来进行业务操作。

读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)间的数据一致性问题。

不管是先写MySQL数据库,再删除Redis缓存;还是先删除缓存,再写库,都有可能出现数据不一致的情况。举一个例子:

1.如果删除了缓存Redis,还没有来得及写库MySQL,另一个线程就来读取,发现缓存为空,则去数据库中读取数据写入缓存,此时缓存中为脏数据。
2.如果先写了库,在删除缓存前,写库的线程宕机了,没有删除掉缓存,则也会出现数据不一致情况。
因为写和读是并发的,没法保证顺序,就会出现缓存和数据库的数据不一致的问题。

如来解决?这里给出两个解决方案,先易后难,结合业务和技术代价选择使用。

二、缓存和数据库一致性解决方案

1.第一种方案:采用延时双删策略
在写库前后都进行redis.del(key)操作,并且设定合理的超时时间。
伪代码如下:

public void write(String key,Object data){
redis.delKey(key);

db.updateData(data);
Thread.sleep(500);
redis.delKey(key);
}

具体的步骤就是:

  • 先删除缓存;
  • 再写数据库;
  • 休眠500毫秒;
  • 再次删除缓存。

那么,这个500毫秒怎么确定的,具体该休眠多久呢?

需要评估自己的项目的读数据业务逻辑的耗时。这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。

当然这种策略还要考虑redis和数据库主从同步的耗时。最后的的写数据的休眠时间:则在读数据业务逻辑的耗时基础上,加几百ms即可。比如:休眠1秒。

设置缓存过期时间

从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案。所有的写操作以数据库为准,只要到达缓存过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存。

该方案的弊端

结合双删策略+缓存超时设置,这样最差的情况就是在超时时间内数据存在不一致,而且又增加了写请求的耗时。

2、第二种方案:异步更新缓存(基于订阅binlog的同步机制)

技术整体思路:
MySQL binlog增量订阅消费+消息队列+增量数据更新到redis
读Redis:热数据基本都在Redis
写MySQL:增删改都是操作MySQL
更新Redis数据:MySQ的数据操作binlog,来更新到Redis

Redis更新

1)数据操作主要分为两大块:

一个是全量(将全部数据一次写入到redis)
一个是增量(实时更新)
这里说的是增量,指的是mysql的update、insert、delate变更数据。

2)读取binlog后分析,利用消息队列,推送更新各台的redis缓存数据。

这样一旦MySQL中产生了新的写入、更新、删除等操作,就可以把binlog相关的消息推送至Redis,Redis再根据binlog中的记录,对Redis进行更新。

其实这种机制,很类似MySQL的主从备份机制,因为MySQL的主备也是通过binlog来实现的数据一致性。

这里可以结合使用canal(阿里的一款开源框架),通过该框架可以对MySQL的binlog进行订阅,而canal正是模仿了mysql的slave数据库的备份请求,使得Redis的数据更新达到了相同的效果。

当然,这里的消息推送工具你也可以采用别的第三方:kafka、rabbitMQ等来实现推送更新Redis。

以上就是Redis和MySQL数据一致性详解,觉得不错请点赞支持。

【mikechen优知】往期博文:

码了几年代码的程序员,有一定的开发经验,应该如何提升自己?

分布式消息系列:详解RocketMQ的简介与演进、架构设计、关键特性与应用场景

高并发架构系列:Kafka、RocketMQ、RabbitMQ的优劣势比较

Java 面试题目最全集合1000+ 大放送,能答对70%就去BATJTMD试试~

相关文章
|
8月前
|
网络协议 NoSQL API
转转客服IM系统的WebSocket集群架构设计和部署方案
客服IM系统是转转自研的在线客服系统,是用户和转转客服沟通的重要工具,主要包括机器人客服、人工客服、会话分配、技能组管理等功能。在这套系统中,我们使用了很多开源框架和中间件,今天讲一下客服IM系统中WebSocket集群的的实践和应用。
642 141
|
7月前
|
缓存 NoSQL 关系型数据库
MySQL 与 Redis 如何保证双写一致性?
我是小假 期待与你的下一次相遇 ~
828 7
|
8月前
|
运维 监控 关系型数据库
MySQL高可用方案:MHA与Galera Cluster对比
本文深入对比了MySQL高可用方案MHA与Galera Cluster的架构原理及适用场景。MHA适用于读写分离、集中写入的场景,具备高效写性能与简单运维优势;而Galera Cluster提供强一致性与多主写入能力,适合对数据一致性要求严格的业务。通过架构对比、性能分析及运维复杂度评估,帮助读者根据自身业务需求选择最合适的高可用方案。
|
10月前
|
关系型数据库 应用服务中间件 nginx
Docker一键安装中间件(RocketMq、Nginx、MySql、Minio、Jenkins、Redis)
本系列脚本提供RocketMQ、Nginx、MySQL、MinIO、Jenkins和Redis的Docker一键安装与配置方案,适用于快速部署微服务基础环境。
|
7月前
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
849 6
|
8月前
|
消息中间件 监控 Cloud Native
高效设计:支持亿级用户社交关系的100W QPS架构方案
面对亿级用户与百万QPS的高并发场景,性能测试成为系统稳定的关键。本文剖析真实业务痛点,详解从接口压测、全链路监控到瓶颈定位的完整性能体系,助你掌握大厂级性能优化能力,从容应对卡顿、宕机等线上挑战。
|
8月前
|
存储 监控 NoSQL
Redis高可用架构全解析:从主从复制到集群方案
Redis高可用确保服务持续稳定,避免单点故障导致数据丢失或业务中断。通过主从复制实现数据冗余,哨兵模式支持自动故障转移,Cluster集群则提供分布式数据分片与水平扩展,三者层层递进,保障读写分离、容灾切换与大规模数据存储,构建高性能、高可靠的Redis架构体系。
|
9月前
|
存储 关系型数据库 MySQL
修复.net Framework4.x连接MYSQL时遇到utf8mb3字符集不支持错误方案。
通过上述步骤大多数情况下能够解决由于UTF-encoding相关错误所带来影响,在实施过程当中要注意备份重要信息以防止意外发生造成无法挽回损失,并且逐一排查确认具体原因以采取针对性措施解除障碍。
637 12
|
边缘计算 Kubernetes 物联网
Kubernetes 赋能边缘计算:架构解析、挑战突破与实践方案
在物联网和工业互联网快速发展的背景下,边缘计算凭借就近处理数据的优势,成为解决云计算延迟高、带宽成本高的关键技术。而 Kubernetes 凭借统一管理、容器化适配和强大生态扩展性,正逐步成为边缘计算的核心编排平台。本文系统解析 Kubernetes 适配边缘环境的架构分层、核心挑战与新兴解决方案,为企业落地边缘项目提供实践参考。
765 0
|
9月前
|
监控 NoSQL 关系型数据库
保障Redis与MySQL数据一致性的强化方案
在设计时,需要充分考虑到业务场景和系统复杂度,避免为了追求一致性而过度牺牲系统性能。保持简洁但有效的策略往往比采取过于复杂的方案更加实际。同时,各种方案都需要在实际业务场景中经过慎重评估和充分测试才可以投入生产环境。
499 0

推荐镜像

更多