分享缩略图

分享到:
链接已复制
首页> 新闻中心>

如何保证Redis和MySQL的数据一致性?

2025-06-24 12:13:14

来源:新华网

字体:

如何保证Redis和MySQL的数据一致性?

简单来说。

该场景主要发生在阅读和写作并发时,数据不一致才会发生。

主要流程是先操作缓存(Redis),或者先操作数据库,操作也分为修改和删除。

一般修改要执行一系列业务代码,因此一般都是直接的。删除成本。较低。

如果我们。先删除Redis中的数据。,修改数据库数据时会出现,其他线程读取Redis,从数据库查󿀌并在Redis中写入,但这是脏数据,因此可以使用。延迟双删。战略,再次删除,之所以需要延迟,是因为当Redis在其他线程中设置旧数据时,不要延迟,新数据将被覆盖。。(所以一般要根据自己的业务逻辑来评估大概的时间。)如果需要在这个阶段确保数据一致性,那就只能。上锁,保证强一致性。,因为Redis和数据库是两个服务,原子性࿰只能通过加锁保证c;这影响了系统吞吐量(使用Redis来增加吞吐量࿰是违反的c;也就是说,AP和CP不能同时满足问题),所以一般都是保证。最终一致性。

如果。先修改数据库。,也会出现数据不一致的情况,在修改数据库处理时,其他线程还将读取旧数据󿀌处理完数据库后,将删除缓存,确保数据的最终一致性,(所以推荐这个操作)

但是,以上两者都会有删除Redis的失败,可以选择。异步发送消息。到MQ,MQ的线程监控。执行重试删除。

但这里的MQ代码过于耦合,如果需要解耦,你可以提取它们,使用阿里的一个。canal开源框架。主要用途是基于MySQL数据库。增量日志分析。,Canal提供各种语言,提供增量数据订阅和消费。客户端。,当Canal监视binlog的变化时༌会通知Canal的客户端,这个过程就是执行失败后,异步向MQ࿰发送消息c;Canal客户端监听到MQ消息进行重试。

详细来说。

1、引入。

Redis 缓存层࿰,用于实现应用和数据库之间的读取操作c;主要目的是减少数据库 IO,还可以提升数据 IO 性能。

当应用程序需要读取某个数据时,,先试试 Redis 内部加载󿀌如果命中,直接返回。如果没有命中󿀌从数据库查询,查询数据后,缓存数据 Redis 里面。

在这样的架构中,会出现问题,是一个数据,数据库和数据库同时保存 Redis 里面,当数据发生变化时,,需要同时更新 Redis 和 Mysql,因为更新有先后顺序,并且它不像 Mysql中的多表事务操作,可以满足 ACID 特性。因此,会出现数据一致性问题。

e27e36563ec144118801ddf5724ebd46.png

2、同步策略。

要确保缓存与数据库的双写一致,总共有四种方法,即4种同步策略:

先更新缓存,再次更新数据库; 先更新数据库,更新缓存; 先删除缓存,再次更新数据库; 先更新数据库,再次删除缓存。 从这四种同步策略中,࿱我们需要进行比较a;

哪种方法更适合更新缓存和删除缓存?#xff1f;是先操作数据库还是先操作缓存?f;

一般直接删除󿀌因为缓存的更新成本更高 (因为你写入数据库的值,很多情况下,缓存࿰不是直接写的c;在写入缓存之前,需要经过一系列复杂的计算。所以,每次写入数据库后再次计算写入缓存值无疑是浪费性能。显然,更适合删除缓存。)删除缓存操作简单,副作用只增加了一次 chache miss,建议大家使用这个策略。

一般先操作数据库,最终一致性￰更方便保证c;先往下看。

3、操作理解。

先操作缓存。

3f428d8e9f084cea8af330909520c273.png

如果我们。先删除Redis中的数据。,修改数据库数据时会出现,其他线程读取Redis,从数据库查󿀌并在Redis中写入,但这是脏数据,因此可以使用。延迟双删。战略,再次删除,之所以需要延迟,是因为当Redis在其他线程中设置旧数据时,不要延迟,新数据将被覆盖。。(所以一般要根据自己的业务逻辑来评估大概的时间。)如果需要在这个阶段确保数据一致性,那就只能。上锁,保证强一致性。,因为Redis和数据库是两个服务,原子性࿰只能通过加锁保证c;这影响了系统吞吐量(使用Redis来增加吞吐量࿰是违反的c;也就是说,AP和CP不能同时满足问题),所以一般都是保证。最终一致性。

先操作数据库。

2ed9f84a85764e61999bf3cdb820b72a.png

如果。先修改数据库。,也会出现数据不一致的情况,在修改数据库处理时,其他线程还将读取旧数据󿀌处理完数据库后,将删除缓存,确保数据的最终一致性,(所以推荐这个操作)

4、解决。

重试机制一般采用延迟双删和删除。

延迟双删。

发现缓存中没有相应的数据,查库,查询完毕。准备更新缓存期间,另一个写线程完成了写库和删除缓存。此时,数据库中的数据是新数据,读取线程将缓存更新为旧数据。),一般来说,,发生这种事件的概率很低,但使用延迟双删可以避免这个问题,进一步提高数据的一致性,但缺点是性能会下降。

根据您的具体业务确定具体的超时间,一般来说,几秒钟就足够了。

队列+重试机制。

在上述情况下,Redis删除失败,可采用重试机制。

例如,重试三次�如果三次都失败了,记录日志到数据库并发出警告,以便在高并发场景下人工干预,最好在重试中使用异步法,比如发消息到 mq 中间件,实现异步解耦。

也就是选择。异步发送消息。到MQ,MQ的线程监控。执行重试删除。

62bd2f223be64a768574793d5e4feb1c.png

解耦Cannal。

但这里的MQ代码过于耦合,如果需要解耦,你可以提取它们,使用阿里的一个。canal开源框架。主要用途是基于MySQL数据库。增量日志分析。,Canal提供各种语言,提供增量数据订阅和消费。客户端。,当Canal听到binlog的变化时,#xff0c;会通知Canal的客户端,这个过程就是执行失败后,异步向MQ࿰发送消息c;Canal客户端监控MQ消息执行重试。

MySQL的binlog可以通过这个框架订阅,而canal模仿mysqlslave数据库的备份请求,Redis的数据更新达到了同样的效果。 RocketMQ可用于MQ消息中间的推送。

3b04924a27fc454fbc99cc0906f248b4.png

【责任编辑:新华网】
返回顶部