mysql 与Redis 数据强一致方案

embedded/2025/1/18 0:16:39/

      • 前言
      • 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

mysqlRedis_10">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__57">分布式实现数据的强一致的方案是什么?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__72">那怎么办?(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.ppmy.cn/embedded/154800.html

相关文章

使用 Vue.js 3 开发动态模块化组件:实现插件式表单系统

在现代前端开发中,模块化和可扩展性是开发复杂应用程序的核心目标。Vue.js 3 提供了很多强大的工具和功能,帮助我们实现这些目标。在本文中,我们将通过一个实际案例:构建动态模块化的插件式表单系统,深入了解如何高效利…

国内汽车法规政策标准解读:GB/T 44464-2024《汽车数据通用要求》

目录 背景介绍 概要General 标准适用范围 重要规定与要求 汽车数据安全管理体系要求 扩展:汽车数据安全管理体系(DSMS) 个人信息保护要求 个人信息处理通用要求 个人同意 个人信息收集 个人信息存储 个人信息使用 个人信息传输 个人信息删除 个人信息…

认识软件测试 - 软实力面试题

目录 1. 什么是测试 1.1 简单认识测试 1.2 为什么需要测试 1.3 软件测试的定义 2. 测试的岗位有哪些 2.1 面试题 [HR 面]: 测开和测试的区别是什么? 3. 软件测试 和 软件开发 3.1 测试和调试的区别 3.2 面试题: 走测试岗位为什么还要学开发知识? 4. 优秀软件测试人…

【Rust自学】12.7. 使用环境变量

12.7.0. 写在正文之前 第12章要做一个实例的项目——一个命令行程序。这个程序是一个grep(Global Regular Expression Print),是一个全局正则搜索和输出的工具。它的功能是在指定的文件中搜索出指定的文字。 这个项目分为这么几步: 接收命令行参数读取…

Kotlin函数类型探索:T.()->Unit的扩展函数、无参函数()->Unit与类型参数函数(T)->Unit

在Kotlin编程语言的丰富特性中,函数类型扮演着至关重要的角色。它们不仅定义了代码的行为,还通过灵活的类型系统促进了代码的重用和模块化。本文将深入探讨Kotlin中的三种核心函数类型:T.()->Unit的扩展函数、无参函数()->Unit以及类型…

C# OpenCV机器视觉:极大值抑制

在一个阳光有些慵懒的午后,阿强像往常一样窝在他那被各种电子元件和线路堆满的实验室里,周围的电脑屏幕闪烁着神秘的代码和复杂的图像,仿佛在诉说着一个个未被解开的科技谜题。阿强最近痴迷于机器视觉领域,而今天,他将…

什么是docker?关于docker容器的全面详细介绍

什么是 Docker Docker 是一种开源的容器化平台,旨在简化应用程序的开发、部署和运行过程。它提供了一种轻量级、可移植且自包含的容器化环境,使开发人员能够以一致的方式在不同的计算机上构建、打包和分发应用程序。 Docker 的出现改变了传统软件开发和…

webpack 4 升级 webpack 5

升级至最新的 webpack 和 webpack-cli npm run build 报错, unknown option -p 解决方案: 改成 --mode production npm run build 报错 unknown option --hide-modules 解决方案:直接移除 npm run build 报错:TypeError: Cannot a…