一文彻底搞定Redis与MySQL的数据同步
Redis 和 MySQL 一致性问题是企业级应用中常见的挑战之一,特别是在高并发、高可用的场景下。由于 Redis 是内存型数据库,具备极高的读写速度,而 MySQL 作为持久化数据库,通常用于数据的可靠存储,如何保证两者数据的一致性需要具体业务场景的设计与优化。
下面我们将结合几个典型的业务场景,逐步分析如何在不同的场景下保证 Redis 和 MySQL 之间的数据一致性。
1. 缓存更新策略:Cache Aside Pattern(旁路缓存模式)
场景:
在大部分业务系统中,Redis 作为缓存层用于提升系统的读取性能,而 MySQL 作为持久化存储,用于保证数据的可靠性。最常见的场景是:
- 系统先查询 Redis 缓存,如果缓存中没有数据,再从 MySQL 中查询并将数据写入 Redis 缓存。
- 更新数据时,更新 MySQL 并删除 Redis 缓存,使缓存数据失效,保证下次读取时能拿到最新数据。
典型业务场景:
- 商品详情页面:当用户请求某个商品详情时,首先查询 Redis 缓存,如果缓存中没有,则查询 MySQL,将查询结果缓存到 Redis 中;如果商品信息发生变更时,更新 MySQL 并删除 Redis 中的缓存。
方案分析:
- 读取路径:从 Redis 获取缓存,如果缓存命中则直接返回数据;如果缓存未命中,则查询 MySQL,将结果写入 Redis,并返回数据。
- 写入路径:更新时先操作 MySQL,然后删除 Redis 缓存中的数据。下次读取时,由于缓存未命中,会重新从 MySQL 中获取最新数据。
如何保障一致性:
缓存淘汰策略:MySQL 数据更新后立即删除 Redis 缓存,确保下次读取时能获取到最新数据。即通过 "删除缓存" 的方式避免脏数据存在于缓存中。
并发问题:当并发请求较高时,可能会出现“缓存雪崩”或“缓存击穿”问题。例如:A 更新 MySQL 数据,B 在缓存失效的瞬间读取了旧数据,再次缓存到 Redis。为解决此问题,可以采用 延迟双删策略:
- 删除 Redis 缓存。
- 更新 MySQL。
- 适当延迟(如 500ms),再次删除 Redis 缓存,确保在并发情况下不存在缓存不一致问题。
业务实例:
// 更新商品详情的伪代码
public void updateProduct(Product product) {
// 1. 更新数据库
updateProductInMySQL(product);
// 2. 删除缓存
deleteProductCache(product.getId()); // 3. 延迟双删,解决并发下不一致问题
try {
Thread.sleep(500); // 可以根据实际业务场景调整
} catch (InterruptedException e) {
// handle exception
}
deleteProductCache(product.getId());
}
2. 先更新缓存再更新数据库
场景:
在某些实时性要求较高的场景中,可以考虑先更新 Redis 缓存,然后再异步更新 MySQL 数据库。
典型业务场景:
- 秒杀系统:例如商品库存的扣减,用户购买商品时,首先更新 Redis 中的库存数量,保证极低延迟的实时性体验。然后将变更异步写入 MySQL,确保持久化存储的一致性。
方案分析:
- 读取路径:读取 Redis 缓存的库存信息,能够提供快速的读取响应。
- 写入路径:更新 Redis 中的库存数量后,使用消息队列或其他异步机制将更新同步到 MySQL。
如何保障一致性:
数据最终一致性:Redis 作为前端实时数据的缓存,MySQL 作为后端数据的持久化存储,采用异步更新策略时,一致性无法保证是强一致性,但可以通过使用消息队列等手段来保证最终一致性。异步写入 MySQL 时,如果操作失败,可以通过重试机制或补偿机制恢复一致性。
业务实例:
// 扣减库存的伪代码
public void reduceStock(Long productId, int amount) {
// 1. 先更新 Redis 中的库存
redisTemplate.decrement("stock:" + productId, amount); // 2. 通过消息队列异步更新 MySQL 中的库存
sendUpdateStockMessage(productId, amount);
} // 消费消息队列更新 MySQL
@RabbitListener(queues = "stock_update_queue")
public void updateStockInMySQL(UpdateStockMessage msg) {
// 从 MySQL 中扣减库存
productRepository.reduceStock(msg.getProductId(), msg.getAmount());
}
一致性保证策略:
- 幂等性保障:确保消息的处理是幂等的,即相同的消息即使被处理多次,也不会导致库存重复扣减。
- 消息重试机制:如果消费消息时更新 MySQL 失败,可以设置重试机制或消息补偿机制,保证最终数据一致性。
3. 双写操作(缓存与数据库同时更新)
场景:
有时业务需要同时更新 Redis 和 MySQL 的数据,如用户余额更新、积分奖励系统等场景中,Redis 和 MySQL 需要同步写入。
典型业务场景:
- 积分系统:用户消费时增加或减少积分,需要同时更新 Redis 和 MySQL 中的积分记录。
方案分析:
- 同步写入:当更新用户积分时,Redis 和 MySQL 同时更新数据。由于需要保证两个存储的同步性,必须考虑事务性问题。
- 分布式事务:如果系统架构分布式,可能需要使用分布式事务(如
2PC
,或者更轻量的解决方案如TCC
)来确保一致性。
如何保障一致性:
双写一致性问题:如果同时写 Redis 和 MySQL,可能会面临一致性问题。常见解决方案是通过事务补偿机制来实现。具体步骤:
- 使用数据库事务保证 MySQL 写入成功。
- 如果 Redis 写入失败,可以尝试重试,或在事务结束后通过补偿机制将失败的数据写入 Redis。
业务实例:
@Transactional
public void updateUserPoints(Long userId, int points) {
// 1. 更新 MySQL 中的积分
userRepository.updatePoints(userId, points); // 2. 同步更新 Redis 中的积分
redisTemplate.opsForValue().set("user:points:" + userId, points);
}
事务性保障:
- 本地事务:在单体系统中,可以依赖数据库事务和 Redis 的操作保证一致性。如果操作失败,通过重试机制来恢复一致性。
- 分布式事务:在微服务架构中,双写操作涉及分布式事务,可能需要使用
TCC
(Try, Confirm, Cancel)等模式,或使用消息队列进行最终一致性补偿。
4. 数据回写(Write Back)策略
场景:
数据回写模式适用于 Redis 作为缓存层,MySQL 作为持久化存储层,但 Redis 中数据修改后并不立即同步更新 MySQL,而是在特定时机触发数据回写。
典型业务场景:
- 广告计费系统:广告点击量保存在 Redis 中,以减少频繁的数据库写入压力,定期将 Redis 中的统计数据批量写入 MySQL。
方案分析:
- 延迟回写:可以通过定时任务或者触发器将 Redis 中的数据定期回写到 MySQL,这样既减少了 MySQL 的压力,又保证了数据一致性。
如何保障一致性:
- 持久化与批量同步:通过 Redis 的持久化机制(如 RDB、AOF),在 Redis 崩溃时不会丢失数据。通过定时器或事件驱动系统触发批量同步 MySQL。
总结
Redis 和 MySQL 的一致性保障在不同的业务场景中需要结合场景特性来进行权衡,主要的策略包括:
- Cache Aside Pattern(旁路缓存模式):常用于读多写少的场景,写操作时删除缓存。
- 异步更新(Write Behind):先更新缓存再异步写入 MySQL,保证最终一致性。
- 双写策略:同时更新 Redis 和 MySQL,配合事务机制确保一致性。
- 延迟回写:通过定时批量写入 MySQL 减少频繁数据库操作。
每种策略有不同的适用场景,设计时需要考虑一致性、性能和可用性之间的平衡。这算得上是全网最全最详细的,货真价实的同步方案分析了,完全结合真实业务场景来考虑设计。所谓赠人玫瑰,手留余香,希望对你有帮助作用。
一文彻底搞定Redis与MySQL的数据同步的更多相关文章
- 掘地三尺搞定 Redis 与 MySQL 数据一致性问题
Redis 拥有高性能的数据读写功能,被我们广泛用在缓存场景,一是能提高业务系统的性能,二是为数据库抵挡了高并发的流量请求,点我 -> 解密 Redis 为什么这么快的秘密. 把 Redis 作 ...
- redis和mySql的数据同步的解析
1.同步MySQL数据到Redis (1) 在redis数据库设置缓存时间,当该条数据缓存时间过期之后自动释放,去数据库进行重新查询,但这样的话,我们放在缓存中的数据对数据的一致性要求不是很高才能放入 ...
- redis实现mysql的数据缓存
环境设定base2 172.25.78.12 nginx+phpbase3 172.25.78.13 redis端base4 172.25.78.14 mysql端# 1.在base2(nginx+p ...
- 两台Mysql数据库数据同步实现
两台Mysql数据库数据同步实现 做开发的时候要做Mysql的数据库同步,两台安装一样的系统,都是FreeBSD5.4,安装了Apache 2.0.55和PHP 4.4.0,Mysql的版本是4.1. ...
- Goldengate完成Mysql到Mysql的数据同步
文档参考地址:http://blog.csdn.net/u010587433/article/details/49305019 需求: 使用Goldengate完成Mysql到Mysql的数据同步,源 ...
- 一文搞定 Redis 复制(全会的举个手看看)
阅读本文大概需要 5 分钟. 本文大纲 复制过程 数据间的同步 全量复制 部分复制 心跳 异步复制 总结 一.复制过程 Step 1:从节点执行 slaveof 命令. Step 2:从节点只是保存了 ...
- 搞定redis面试--Redis的过期策略?手写一个LRU?
1 面试题 Redis的过期策略都有哪些?内存淘汰机制都有哪些?手写一下LRU代码实现? 2 考点分析 1)我往redis里写的数据怎么没了? 我们生产环境的redis怎么经常会丢掉一些数据?写进去了 ...
- Redis(1.8)Redis与mysql的数据库同步(缓存穿透与缓存雪崩)
[1]缓存穿透与缓存雪崩 [1.1]缓存和数据库间数据一致性问题 分布式环境下(单机就不用说了)非常容易出现缓存和数据库间的数据一致性问题,针对这一点的话,只能说,如果你的项目对缓存的要求是强一致性的 ...
- 怎么通过 Mysql 实现数据同步呢?
怎么使 mysql 数据同步先假设有主机 A 和 B ( linux 系统),主机 A 的 IP 分别是 1.2.3.4 (当然,也可以是动态的),主机 B 的 IP 是 5.6.7.8 .两个主机都 ...
- MySQL主从数据同步延时分析
一.MySQL数据库主从同步延迟 要了解MySQL数据库主从同步延迟原理,我们 ...
随机推荐
- 机器学习中的两个重要函数--sigmoid和softmax
机器学习中,常常见到两个函数名称:sigmoid和softmax.前者在神经网络中反复出现,也被称为神经元的激活函数:后者则出现在很多分类算法中,尤其是多分类的场景,用来判断哪种分类结果的概率更大. ...
- 【共建开源】手把手教你贡献一个 SeaTunnel PR,超级详细教程!
Apache SeaTunnel是一个非常易于使用的.超高性能的分布式数据集成平台,支持海量数据的实时同步.每天可稳定高效同步数百亿数据,已被近百家企业投入生产使用. 现在的版本不支持通过jtds的方 ...
- springcloud线上发布超时方案之终极杀招:预热(测试用例)
springcloud线上发布超时系列文章: springcloud线上发布超时之feign(ribbon饥饿加载) springcloud线上发布超时之grpc springcloud线上发布超时方 ...
- [Linux]yum下载慢!!
有全局代理,但是yum下载特别慢,怎么办? 确保/etc/yum.conf文件中代理配置的语法正确,包括代理服务器的地址和端口号,如下所示: proxy=http://your_proxy_serve ...
- API 接口是什么?怎么对接 API?
API接口是预先定义的函数,允许应用间共享数据和功能.对接API涉及获取接口文档,通过POST请求调用如http://域名地址/queryLoginWx的URL,使用特定Headers.成功返回会包含 ...
- Python wheel
在 Python 的生态系统中,wheel 是一种打包格式,用于分发和安装 Python 项目.它是 Python 包的标准格式之一,旨在提高安装速度和可靠性. Wheel 的优势 快速安装:因为 w ...
- MyBatis分页实现
目录 分页实现 limit实现分页 RowBounds分页 分页实现 limit实现分页 为什么需要分页? 在学习mybatis等持久层框架的时候,会经常对数据进行增删改查操作,使用最多的是对数据库进 ...
- exceptionless 在 windows 上 手动部署,非docker 详细步骤
关于exceptionless 是什么我就不多说了,能看到这篇文章的都知道了.网上几乎都是docker部署的,docker部署的确十分方便,但是有的人没有条件用docker,像我就不想花这个钱去多服务 ...
- Typora mac激活
typora mac版本激活 我也是第一次使用mac电脑,在安装时基本上都是付费的,在mac下载使用typora是试用一段时间后是需要付费购买的,苦无能力有限只能绕一下,感谢网上的各位大佬的分享 来源 ...
- Entity Framework Plus: 让 EF Core 开发如虎添翼
EF Core介绍 Entity Framework (EF) Core 是轻量化.可扩展.开源和跨平台版的常用 Entity Framework 数据访问技术,EF Core 是适用于 .NET 的 ...