如何保证redis和mysql数据一致性方案对比

一. 先更新数据库再更新缓存

  1. 业务代码中先 DB 后 Cache(不推荐)

updateDB();

updateCache();

原因:

  1. DB成功,Cache失败 缓存不一致 无法进行回滚

为啥使用@Transactional不能保证数据一致性?

@Transactional

public void update() {

updateDB(); // 数据库

updateCache(); // Redis / 本地缓存

}

上面代码的执行顺序:

1.updateDB() → 执行 SQL(未提交)

2.updateCache() → Redis 已更新

3.方法结束

4.事务提交(或回滚)

@Transactional满足条件?

@Transactional 的本质基于数据库的事务。

它只能保证:

1.多条数据库 SQL

2.在同一个数据源

3.同一个线程

4.同一个事务上下文

  1. 业务代码中先 DB ,再删除 Cache(推荐)但是会出现短暂不一致

@Transactional

public void update() {

updateDB();

}

public void afterUpdate() {

deleteCache();

}

流程:

更新 DB(事务)

提交成功

删除缓存

下次读 → 回源 DB → 重建缓存

二. 先更新缓存再更新数据库

结论:

先更新缓存再更新数据库的做法,永远无法保证数据严格的一致性。

原因:事务A更新缓存成功,更新数据库失败,就会导致redis和mysql的

数据不一致。

绝大多数场景不使用先更新缓存再更新数据库。

特殊场景:缓存为主,DB为辅。

思路:缓存是主存储,数据库只是持久化备份

适用场景:

游戏排行榜 / 计分系统

高频访问、对性能要求极高的热点数据

热点缓存需要立即生效,DB 延迟可接受

高吞吐、读多写少的场景

DB 写操作是瓶颈,先更新缓存可以减少 DB 压力

三. 双删策略

并发问题:并发读写导致的缓存脏数据

假设有 三个事务 A、B、C,涉及 DB + Redis 缓存?

事务A:

deleteCache() // 删除缓存

updateDB() // 更新数据库

DB还没有更新完成

还没执行第二次删除缓存

事务 B(读操作):

cache miss // 缓存已被删除

read DB // 读到旧值(事务 A 还没提交/更新完成)

write cache // 回写旧值到缓存

事务C:

读取缓存中旧的数据

四 . canal监听Binlog日志

双删策略对比canal监听Binlog日志的劣势?

双删策略缺点?

  1. 时间窗口不太好控制

如果 sleep 太短 → 不一致仍可能

如果 sleep 太长 → 延迟大,业务性能受影响

  1. 业务耦合

每个更新操作都要手动加双删逻辑

多服务、多表、多缓存的情况下,维护成本高

  1. 无法扩展到多个下游系统

比如缓存 + Elasticsearch + MQ

双删只能针对单个缓存,无法保证其他下游系统同步

canal 监听 Binlog 的优势?

DB update → MySQL binlog → Canal → 消费端处理 → 更新缓存 / 下游系统

  1. 完全解耦业务

业务代码只管 DB,不用关心缓存

不会增加每个更新的复杂度

  1. 可扩展性

一个Canal消费端可以同时同步缓存,搜索引擎,消息队列等。

多个下游系统共享同一条 Binlog 数据,保证最终一致性

统一容错处理

Canal 自带消费重试

消费失败可以回溯 binlog

远比双删"sleep+delete"可控

五、为什么大规模系统不用双删而用 Canal

维度 双删 Canal

业务 耦合 强,每个更新都要写双删 弱,业务只管 DB

多下游系统 每个系统都要自己写双删 一条 Binlog 可以同步多个系统

可靠性 不可控,sleep 仍可能不一致 可控,Binlog 消费可重试

扩展性 差 好,适合微服务和大流量系统

可维护性 差 好, 统 一逻辑

双删适合小型、单服务、低流量场景;

Canal + Binlog 更新缓存适合大型、分布式、高并发场景,因为它解耦、统一、可重试,维护成本更低。

相关推荐
jiayou641 天前
KingbaseES 表级与列级加密完全指南
数据库·后端
用户3074596982072 天前
Redis 延时队列详解
redis
GBASE2 天前
G术时刻 |GBase 8s数据库事务并发控制之封锁技术介绍(下)
数据库
烤代码的吐司君2 天前
Redis 数据结构 ZSet, BIT, HyperLogLog,Geo 空间数据
redis·后端
xiezhr2 天前
逛GitHub发现了一款免费的带AI功能的数据库管理工具
数据库·ai编程·dba
唐青枫3 天前
MySQL JSON 实战详解:从存储、查询、更新到 JSON_TABLE 与索引
sql·mysql
吃糖的小孩3 天前
给 QQ AI 机器人设计“可控记忆”:会话摘要、手动长期记忆与角色卡边界
数据库
小满8783 天前
5.Mysql事务隔离级别与锁机制
mysql
笃行3504 天前
金仓数据库数据安全双防线:静态存储加密与传输加密实战
数据库
笃行3504 天前
金仓数据库物理备份实战:sys_rman 全流程演练与误覆盖抢救
数据库