解决MySQL与Redis缓存一致性的问题

背景

考试系统中,教师会在后台发布一场考试,考试会存储在MySQL和Redis里面,考试有时候是会出错的,我们需要后台修改,如果多个教师在后台并发修改(概率不大),可能会出现数据库缓存不一致的问题,我们需要解决一下,刚好联系一下这一块的知识

基础知识理论

四种解决办法:

  1. 先更新数据库,再更新缓存
  2. 先更新缓存,后更新数据库
  3. 先删除缓存,后更新数据库
  4. 先更新数据库,后删除缓存

这四种情况,都会出现缓存不一致的问题,但是第四种出现缓存不一致的情况概率上比较低,因为缓存的写入回远远快于数据库的写入,我们可以使用【先更新数据库+再更新缓存】的方式来解决数据库不一致的问题,为了确保万无一失,我们还可以加上一个过期时间。

但是有两个问题

  1. 我们需要保证先更新数据库+再更新缓存是一个原子操作,不然如果更新缓存失败了,导致缓存中的数据还是旧值
  2. 「先更新数据库,再删除缓存」的方案虽然保证了数据库与缓存的数据一致性,但是每次更新数据的时候,缓存的数据都会被删除,这样会对缓存的命中率带来影响。

对于第一个问题,解决办法是消息队列重试机制、订阅MySQL binlog,再操作缓存

对于第二个问题是,我们使用「更新数据库 + 更新缓存」的方式来实现,但是这个方案本身固有一些问题,解决办法是,分布式锁和过期时间

另外先删除缓存,再更新数据库的解决方案是延迟双删

实战-先更新数据库,后删除缓存

此种方案存在问题是两个操作不是原子性的,如何保证两个操作都能成功呢?

方案一:gin框架+消息队列

我们实现一个中间件

func Canal() gin.HandlerFunc {
	//封装成一个中间件,当我们更新考试的时候,会自动监测到
	return func(c *gin.Context) {
		c.Next()
		redisDB := global.GVA_REDIS
		get, exists := c.Get("DeleteRedisKey")
		DeleteKey := get.(string)
		if exists {
			err := redisDB.Del(context.Background(), DeleteKey).Err()
			if err == redis.Nil {
				//无需删除
				c.Next()
			} else if err != nil {
				//删除失败,加入到redis异步队列中,再次删除
				addToDelayedQueue(context.Background(), redisDB, DeleteKey, time.Now().Add(10*time.Second))
			}else {
				global.GVA_LOG.Info("更新数据成功")
			}
		} else {
			zap.L().Info("redis中不存在该键,无需删除")
		}
	}
}

我们在继承这个中间件的接口中的使用c.Set方法传递要删除的redisKey,然后我们在上述中间件中使用c.Get方法来接收要删除的redisKey,然后加入到异步队列中删除

现在来模拟一下是否能够成功,项目启动之后,把redis停机,然后删除redis的key就会失败,然后该key就会加入延时队列

方案一:消息队列订阅binlog

里面有两个难点,一个是订阅binlog服务,一个是消息队列

 如何订阅binlog服务,我们使用阿里巴巴的canal ,支持Go语言,具体参考Golang通过alibabaCanal订阅MySQLbinlog_大杯无糖的博客-CSDN博客

接下来是用redis的zset实现一个异步消息队列

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/70988.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

企业中商业智能BI,常见的工具和技术

商业智能(Business Intelligence,简称BI)数据可视化是通过使用图表、图形和其他可视化工具来呈现和解释商业数据的过程。它旨在帮助组织更好地理解和分析他们的数据,从而做出更明智的商业决策。 常见的商业智能数据可视化工具和技…

【二分+贪心】CF1622 C

Problem - 1622C - Codeforces 题意: 思路: 首先,观察样例可知,肯定是把原本的最小值减到某个值,然后再复制几次 复制的时候肯定是从大到小复制 那把最小值减到哪个值是不确定的,考虑枚举这个值&#x…

预测知识 | 神经网络、机器学习、深度学习

预测知识 | 预测技术流程及模型评价 目录 预测知识 | 预测技术流程及模型评价神经网络机器学习深度学习参考资料 神经网络 神经网络(neural network)是机器学习的一个重要分支,也是深度学习的核心算法。神经网络的名字和结构,源自…

实例036 使窗体标题栏文字右对齐

实例说明 窗口标题栏中的文字是窗口的重要说明,该文字可以标示窗口的功能、状态或名称等信息,一般该文字是居左显示的,在本例中设计一个标题栏文字右对齐的窗口。本实例运行结果如图1.36所示。 技术要点 在C# 2.0中实现这一功能非常容易&am…

Qt应用开发(基础篇)——拆分器窗口 QSplitter QSplitterHandle

一、前言 QSplitter继承于QFrame,QFrame继承于QWidget,是Qt的一个部件容器工具类。 框架类QFrame介绍 QSplitter拆分器,用户通过拖动子部件之间的边界来控制子部件的大小,在应用开发中数据分模块展示、图片展示等场景下使用。 二、…

第三节:在WORD为应用主窗口下关闭EXCEL的操作(1)

【分享成果,随喜正能量】夏日里的遗憾,一定都会被秋风温柔化解。吃素不难,难于不肯捨贪口腹之心。若不贪口腹,有何吃素之不便乎。虽吃华素,不吃素日,亦须少吃。以一切物类,皆是贪生怕死&#xf…

最强自动化测试框架Playwright(11)- 录制视频

视频 使用playwright,您可以录制测试视频。 录制视频 视频在测试结束时在浏览器上下文关闭时保存。如果手动创建浏览器上下文,请确保等待 browser_context.close()。 context browser.new_context(record_video_dir"vid…

机器学习基础08-回归算法矩阵分析(基于波士顿房价(Boston House Price)数据集)

回归算法通常涉及到使用矩阵来表示数据和模型参数。线性回归是最常见的回归算法之一,它可以用矩阵形式来表示。 考虑一个简单的线性回归模型: y m x b y mx b ymxb,其中 y y y 是因变量, x x x 是自变量, m m m 是…

基于 JMeter API 开发性能测试平台

目录 背景: 常用的 JMeter 类和功能的解释: JMeter 编写性能测试脚本的大致流程示意图: 源码实现方式: (1) 环境初始化 (2) 环境初始化 (3) 创建测试计划 (4) 创建 ThreadGroup (5) 创建循环控制器 (6) 创建 Sampler (…

Linux安装配置nginx+php搭建以及在docker中配置

Linux安装配置nginxphp搭建以及在docker中配置 文章目录 Linux安装配置nginxphp搭建以及在docker中配置1.nginx源码包编译环境和安装相应的依赖1.1 安装编译环境1.2 安装pcre库、zlib库和openssl库 2.安装nginx2.1 在[nginx官网](https://nginx.org/en/download.html)上获取源码…

ffmpeg+nginx实现rtsp协议摄像头web端播放

ffmpegnginx实现rtsp协议摄像头web端播放 环境准备准备nginx环境添加rtmp模块添加hls转发 使用ffmpeg,将摄像头rtsp转为rtmp并推送到nginxVLC播放验证 环境准备 nginx(需要安装rtmp模块)ffmpeg 6.0vlc播放器(本地播放验证&#x…

如何让ES低成本、高性能?滴滴落地ZSTD压缩算法的实践分享

前文分别介绍了滴滴自研的ES强一致性多活是如何实现的、以及如何提升ES的性能潜力。由于滴滴ES日志场景每天写入量在5PB-10PB量级,写入压力和业务成本压力大,为了提升ES的写入性能,我们让ES支持ZSTD压缩算法,本篇文章详细展开滴滴…

青大数据结构【2014】

一、单选 二、简答 为了解决顺序队列的假溢出问题,提出了循环队列,即把存储队列的表从逻辑上看成一个环 判别队列空和满有三种方法: 1)采用计数器判别,空时,计数器为0;满时,计数器…

智谷星图赵俊:让人才和区块链产业“双向奔赴”丨对话MVP

区块链产业需要什么样的人才?赵俊很有发言权。 赵俊是北京智谷星图科技有限公司的技术总监,也是FISCO BCOS官方认证讲师。他2017年接触区块链,随后选择人才培育领域深耕。“为区块链行业引进更多人才这件事很有价值,跟我的职业理…

shell脚本开发

shell脚本语言属于弱类型的语言,无需声明变量类型,直接定义使用 shell语言定义的变量,数据类型默认都是字符串类型 调用历史记录命令:! 历史记录id

【C语言】分支语句(选择结构)详解

✨个人主页: Anmia.🎉所属专栏: C Language 🎃操作环境: Visual Studio 2019 版本 目录 什么是分支语句? if语句 if if - else单分支 if - else if - else ...多分支 if - if嵌套 switch语句 基本语…

3.6 Spring MVC文件上传

1. 文件上传到本地 实现方式 Spring MVC使用commons-fileupload实现文件上传,注意事项如下: l HTTP请求方法是POST。 l HTTP请求头的Content-Type是multipart/form-data。 SpringMVC配置 配置commons-fileupload插件的文件上传解析器CommonsMultip…

【工程优化问题】基于鲸鱼、萤火虫、灰狼优化算法的张力、压缩弹簧设计问题研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

负载均衡–HAProxy安装及搭建tidb数据库负载服务

作为一名开发人员,随着经验的增加和技术的沉淀,需要提高自己架构方面的知识,同时对于一个企业来说,搭建一套高可用、高性能的技术架构,对于公司的业务开展和提高服务的性能也是大有裨益的。本文重点从软件安装和搭建ti…

1、Java简介+DOS命令+编译运行+一个简单的Java程序

Java类型: JavaSE 标准版:以前称为J2SE JavaEE 企业版:包括技术有:Servlet、Jsp,以前称为J2EE JavaME 微型版:以前称为J2ME Java应用: Android平台应用。 大数据平台开发:Hadoo…