mysql 与Redis 数据强一致方案

devtools/2025/1/15 17:06:49/

      • 前言
      • 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/devtools/150726.html

相关文章

【深度学习】PyTorch:手写数字识别

在这个技术博客中,我们将一起探索如何使用PyTorch来实现一个手写数字识别系统。这个系统将基于经典的MNIST数据集,这是一个包含60,000个训练样本和10,000个测试样本的手写数字(0-9)数据库。通过这个项目,你将了解如何使用PyTorch进行深度学习模型的构建、训练和评估。 文…

【2025最新】Poe保姆级订阅指南,Poe订阅看这一篇就够了!最方便使用各类AI!

1.Poe是什么? Poe, 全称Platform for Open Exploration。 Poe本身并不提供基础的大语言模型,而是整合多个来自不同科技巨头的基于不同模型的AI聊天机器人,其中包括来自OpenAI的ChatGPT,Anthropic的Claude、Google的PaLM&#xf…

如何在gitlab cicd中实现每月10号上午执行

在 GitLab CI/CD 中,可以通过设置定时触发器(Schedules)和脚本中的时间判断逻辑结合,确保任务只在每月 10 号的上午运行。 以下是实现的步骤: 1. 设置定时触发器 GitLab 提供了 Schedules 功能,可以指定每…

STM32入门教程-示例程序(按键控制LED光敏传感器控制蜂鸣器)

1. LED Blink(闪烁) 代码主体包含:LED.c key.c main.c delay.c(延时防按键抖动) 程序代码如下(涉及RCC与GPIO两个外设): 1.使用RCC使能GPIO时钟 RCC_APB2PeriphClockC…

vector的模拟实现(C++)

一、构造函数 vector() //构造函数:_start(nullptr),_finish(nullptr),_endofstorage(nullptr) {}vector(int n, const T& val T())//构造函数:_start(nullptr), _finish(nullptr), _endofstorage(nullptr) {reserve(n);while (n--){push_back(val);} }template<cla…

LeetCode2799 统计完全子数组的数目

计算完全子数组的数目&#xff1a;从暴力到优化的算法实现 在算法的世界里&#xff0c;常常会遇到各种有趣的数组问题&#xff0c;今天我们要探讨的是计算完全子数组的数目。这个问题来自LeetCode&#xff0c;题目如下&#xff1a; 给你一个由正整数组成的数组 nums。如果数组…

matlab实现了一个优化的遗传算法,用于求解注汽站最优位置的问题

function [best_chromosome, best_fitness] optimized_genetic_algorithm()%% 遗传算法参数初始化% 定义井信息&#xff0c;包括坐标、管道长度、流量、压力等wells defineWells(); % 返回井的结构体数组N length(wells); % 注汽井数量% 遗传算法相关参数L_chromosome 20; …

FPGA车牌识别

基于FPGA的车牌识别主要包含以下几个步骤&#xff1a;图像采集、颜色空间转换、边缘检测、形态学处理&#xff08;腐蚀和膨胀&#xff09;、特征值提取、模板匹配、结果显示。先用matlab对原理进行仿真&#xff0c;后用vivado和modelsim进行设计和仿真。 一、1.图像采集采用ov…