当前位置: 首页 > article >正文

mysql 与Redis 数据强一致方案

      • 前言
      • mysql与Redis能实现数据的强一致?
        • 分布式实现数据的强一致的方案是什么?mysql 与 Redis 能强一致吗?
          • Redis 的事务不适合实现强一致
          • 那怎么办?(mysql 与Redis 有强一致方案吗?)

前言

mysql与Redis一般不会使用强一致性因为不仅设计复杂并且性能差(典型的吃力不讨好类型),而是使用最终一致性

如果想了解mysql与Redis数据一致性问题可以看之前这篇:
https://blog.csdn.net/dengjiayue/article/details/145120778?fromshare=blogdetail&sharetype=blogdetail&sharerId=145120778&sharerefer=PC&sharesource=dengjiayue&sharefrom=from_link

mysql与Redis能实现数据的强一致?

我之前提了一个方案是,使用本地事务实现一致

伪代码逻辑

//开启事务
tx:=db.Start()

//更新 mysql 数据
err = tx.Update(data)
if err!=nil{
	tx.Rollback()
	return
}

//清除 Redis 数据
err = redis.Delete(key)
if err!=nil{
	tx.Rollback()
	return
}

//提交事务
err = tx.Commit()
if err!=nil{
	tx.Rollback()
	return
}

  1. 事务是强一致方案?
    事务(Redis 删除)不是强一致方案,

a. 对于 mysql 与 Redis 的数据来讲是最终一致性方案(要等到下一次查询,mysql 才与 Redis 的数据是一致的)

b. 对于数据查询来讲是查询到的一定是最新数据(Redis 清除后无法命中,只能查询 mysql 最新数据)
ⅰ. 只要用户点击更新数据接口并收到更新成功的返回,那么查询的数据就是更新的数据,不会查询到旧数据

c. 并且只适用于清除Redis数据, 如果更新数据将会有极大的 bug

如果是更新会怎么样?为什么只能删除?

  • 如果 Redis 更新成功了,但是在第二阶段 mysql 发送 commit 请求的时候失败了(比如mysql 宕机)那么 Redis 的数据与 mysql 的数据将会不一致(mysql 没有提交,所以是旧数据,而 Redis 是新数据),所以只适用与 Redis 清除的方案
分布式实现数据的强一致的方案是什么?mysql 与 Redis 能强一致吗?

分布式如何实现强一致
ⅰ. 共识算法(比如 raft)
ⅱ. 分布式事务

参考:
https://cn.pingcap.com/article/post/13082.html
https://juejin.cn/post/7316967969917009971(分布式事务 2pc/3pc实现强一致)
https://cloud.baidu.com/article/3076675

Redis 的事务不适合实现强一致

Redis 事务没有原子性,而是一个批量脚本,并不具备 像 mysql 那样的start 与 commit 的功能
ⅰ. 所以无法使用单纯的分布式事务(两阶段提交)来实现强一致性(Redis 无法持有数据的资源)

那怎么办?(mysql 与Redis 有强一致方案吗?)

mysql 与 Redis 实现强一致的方案: 分布式锁+补偿机制

  • 强一致的概念: mysql 与 Redis 数据同时生效,并且是相同的.
  1. 分布式锁解决的问题: Redis 无法持有数据资源的问题
  2. 补偿机制:解决Redis 无法回滚的问题(mysql 的回滚是通过 undo log 实现的 ,但是Redis 没有,只能记录数据之前 的状态来回滚)
    相当于给 Redis 赋予与 mysql 一样的事务的功能,然后再使用分布式事务两阶段提交的逻辑.

具体做法
● 更改时加分布式锁,拦截所有的读写请求
● 记录数据之前的状态(用于第二阶段提交失败的 Redis 补偿(恢复到没更新前的状态)
● 更新数据(先更新 mysql(不提交),再更新 Redis,再根据操作的结果决定是提交还是回滚)
● 事务 提交/回滚(Redis 补偿)

  • 提交/回滚 没有问题,释放分布式锁

这样做虽然能保持 mysql 与 Redis 的数据强一致,但是对于性能的影响非常大,所以一般不会使用
mysql 与 Redis 一般都是采用最终一致的方案(清除 Redis 数据等到下一次查询才最终一致)
不仅仅是 mysql 与 Redis,就算是mysql 主从之间,Redis 主从之间,以及其他分布式数据一致性的场景都不会使用强一致的方案,为了保证服务的性能都会采用最终一致的方案

思考:共识算法能实现强一致吗?怎么工作的?


http://www.kler.cn/a/504083.html

相关文章:

  • Jenkins简单的安装运行
  • 线程间通信
  • 当生活低迷时,如何醒过走出迷境?
  • SQL从入门到实战-2
  • Scala语言的字符串处理
  • 【某大型互联网企业】软件测试面试经验分享(1 ~ 3年)
  • MySQL表的增删改查(基础)-下篇
  • 面试: 工作中常用的linux命令
  • OpenCV基础:矩阵的创建、检索与赋值
  • Java Stream流操作List全攻略:Filter、Sort、GroupBy、Average、Sum实践
  • 在使用 GitLab API 时,如果只能获取少量的 Merge Request(MR)信息,而没有完整的数据
  • ubuntu 下生成 core dump
  • 2025制定一个高级java开发路线:分布式系统、多线程编程、高并发经验
  • SQL 详解数据库
  • Spring Boot中如何处理跨域请求(CORS)
  • 【Linux】Linux基础命令(二)
  • 《Openlayers零基础教程》第六课:地图控件
  • 《重生到现代之从零开始的数据结构生活》——单链表
  • MySQL:表的内外连接
  • Python爬虫基础——IP反爬虫的应对