redis和mysql数据一致性方案

7 篇文章 0 订阅

在这里插入图片描述
请求 A 更新数据 请求B读数据
在高并发情况下,A、B请求过程步骤相互穿插,就会出现图中的问题。

期望redis 的数据是11,最后变成了10

场景:先删除Redis,再更新 MySQL,不主动更新Redis,访问redis 没有数据,再访问MySQL 把数据回写到Redis。

在这里插入图片描述
请求 A、B 都是更新 Redis,然后再更新MySQL

在高并发情况下,如果请求 A 在更新MySQL 时卡了一会,请求 B 已经依次完成数据的更新,就会出现图中的问题。

期望redis 的数据是11,最后变成了10

分析:MySQL事物功能比Redis强大,可以严格保证原子性。 Redis宕机可能会丢失部分数据。以Redis为主处理异常成本高。

在这里插入图片描述
请求 A、B 都是先写 MySQL,然后再写 Redis

在高并发情况下,如果请求 A 在写 Redis 时卡了一会,请求 B 已经依次完成数据的更新,就会出现图中的问题。

期望redis 的数据是11,最后变成了10

场景:以MySQL 为主,事物成功,才更新Redis,

在这里插入图片描述
对于上面这种情况,对于第一次查询,请求 B 查询的数据是 10,但是 MySQL 的数据是 11,
存在这一次不一致的情况,对于不是强一致性要求的业务,可以容忍。
秒杀业务、库存服务等,需要考虑这个风险点。

在这里插入图片描述
这里需要满足条件:
1、缓存刚好自动失效或者删除;
2、B C请求同时访问,key未命中
3、B查询MySQL数据回写到redis 10。
4、A请求更新MySQL 为11 并且删除缓存
5、C回写之前的数据10。
因为正常情况更新MySQL 要比更新Redis耗时要长,这种情况发生概率极低, 在服务高负载情况下可能发生。
在这里插入图片描述
请求 A 更新数据 请求B读数据
在高并发情况下,A、B请求过程步骤相互穿插,如果“删除缓存 10”必须在“回写缓存10”前面会有异常。

期望redis 的数据是11,可能最后变成了10

优化:“删除缓存 10”必须在“回写缓存10”后面,为了让请求 A 的最后一次删除,等待一段时间,缺点可能会有性能问题造成进程排队。
场景: 先删除 Redis,更新 MySQL,再删除 Redis,用户读redis 没数据再访问MySQL回写Redis

在这里插入图片描述
通过消息队列的异步串行,实现最后一次删除。
删除失败加重试
尽量不用sleep 的方式,可能有性能风险。

在这里插入图片描述
这个方案可以保证数据最终一致性,但是带来了性能问题。对数据一致性比较敏感的服务可以采用这个方案。

在这里插入图片描述
这个方案,会保证 MySQL 和 Redis 的最终一致性,
但是如果中途请求 B 需要查询数据,如果缓存无数据,就直接查 DB;
如果缓存有数据,查询的数据也会存在不一致的情况。

总结:
除非读也要加锁, 不论采用那种方案极端情况下都会有某一个时刻数据不一致的情况。从技术上来说,无法保证Redis 和数据库的严格一致,所有的方案都是尽可能降低不一致的可能性和不一致时间。
方案4,5 加redis key设置过期时间 可以实现数据的最终一致。
方案6 牺牲了性能保证了数据最终一致性。
方案7 既保证了性能又能保证数据最终一致性,引入的中间件多,维护成本高。
方案6和方案7 因为所有的更新都会同步更新 redis ,redis 存储了所有数据,对redis内存空间要求大。

备注:绘图工具。
https://excalidraw.com/

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值