Redis与DataBase保持数据一致性
文章目录
- 1. 读取数据
- 2. 写数据
- 2.1 先操作缓存
- 2.2 先操作数据库
在我们系统中缓存最常用的策略是:服务端需要同时维系DB和Cache,并且是以DB的结果为准,
Cache-Aside Pattern
(缓存分离模式、旁路缓存)。
1. 读取数据
当用户查询数据时,首先先到Redis中进行查询,如果没有命中,则到数据库中进行查询。在数据库中查询到数据后,将数据返回,并且存入到Redis中,设置过期时间,设置过期时间是为了避免长时间未使用的数据一直存放在Redis中,占用内存空间。
2. 写数据
用户在写入数据时,要操作Redis和DataBase。有以下几种操作:
先操作Redis缓存
- 先更新缓存,再更新数据库
- 先删除缓存,再更新数据库
先操作DataBase数据库
- 先更新数据库,再更新缓存
- 先更新数据库,再删除缓存
对于是更新Redis中的数据,还是删除Redis中的数据,其实更推荐是删除Redis中的数据。
因为,如果是选择修改Redis数据,而不是删除,那么如果再修改Redis数据成功后,再去更新数据库中的数据时失败,这样就会导致Redis和DataBase中的数据不一致。再或者如果先成功更新了数据库中的数据,再去更新Redis中的数据时失败了,那么下次查询到Redis中的数据虽然存在,但是为错误数据。
在更新缓存与删除缓存之中,我们确定了是使用删除Redis缓存中的数据。那么剩下的一个问题就是,先更新数据库,还是先删除Redis缓存?
对于这两种情况,我们分别进行讨论。
2.1 先操作缓存
先操作缓存,也就是先将Redis中的数据删除,然后再更新DataBase中的数据。
数据不一致
考虑这种情况下会出现的问题:
- Redis中的数据成功被删除了。
- 在数据被写入数据库之前,此时有线程2存在,线程2读取DataBase中的数据,读取成功后存入了Redis中。
- 线程2从DataBase中读取数据后,线程1的新数据写入DataBase。
- 此时再去读取数据时,因为Redis中数据存在,所以会直接读取Redis中的数据,但是Redis中的数据是旧数据,此时就出现了数据不一致问题。
出现上述这种情况时,该如何解决呢?
(双删)有一种解决方法:
- Redis中的数据成功被删除了
- 在数据被写入数据库之前,此时有线程2存在,线程2读取DataBase中的数据,读取成功后存入了Redis中。
- 线程2从DataBase中读取数据后,线程1的新数据写入DataBase。
- 线程1的新数据写入DataBase后,再次执行将Redis中的数据删除。
- 此时再去读取数据时,因为Redis中数据不存在,所以会到DataBase中查询数据,再将查询到的数据存入Redis中,这样保证了数据的一致性。
但是,这种处理方法,还是存在一种缺陷。如以下情况:
- 线程1更新数据,Redis中的数据成功被删除了。
- 线程2读取数据,先查缓存,缓存中数据不存在,查询数据库,查询到旧数据。
- 线程1删除Redis数据成功后,将新数据写入数据库。
- 线程1将新数据写入数据库后,删除Redis中的缓存数据。
- 线程2将查询到的旧数据返回,并将数据写入到Redis中。
- 此时,Redis中的数据为旧数据,又导致了Redis与数据库中数据不一致的问题。
为了解决上述问题,我们可以将第5步操作进行延迟。在上诉例子中,也就是让线程2先将旧数据存入到Redis中,线程1再去删除Redis中的数据。这种处理方法称为延迟双删。
对于先操作缓存,再操作数据库的情况中,处理数据不一致性问题,我们一般采用延迟双删的方法进行处理。
2.2 先操作数据库
先操作数据库,也就是先更新DataBase中的数据,然后再将Redis中的数据删除。
此时,线程2存在,如果数据再Redis中存在,那么不会出现数据不一致问题。
线程2查询数据,首先查询缓存,数据存在直接返回,只是线程2可能查到的为旧数据,但是这并不影响Redis与DataBase的数据一致性。
除了这种情况外,还有一种情况存在。Redis中不存在被更新的该数据。那么就会出现以下情况:
- 线程2查询数据,先查询Redis中的数据,数据不存在,到数据库中查询数据,查询到旧数据。
- 线程1更新数据库中的数据。
- 线程1更新完数据库中的数据后,执行对Redis中数据的删除操作。
- 线程2将查询到的旧数据存储到Redis中。此时就出现了数据不一致行问题。
对于这种情况,我们对于图中第4步操作还是采用延迟删除进行处理。
但是这种情况下,也会存在一种问题,就是第3步操作,删除缓存失败。针对这种删除缓存失败的情况,我们可以采用删除重试机制进行解决。我们可以引入MQ消息队列。
但是,加入了删除重试后,非业务代码和业务代码耦合度太高了。
我们想解耦的话,就可以采用另一个组件,叫做canal。
canal是阿里的一款开源框架,主要用途是基于MySQL数据库增量日志解析,提供增量数据订阅和消费。
Canal提供了各种语言的客户端,当Canal监听到binlog变化时,会通知Canal的客户端。
相关文章:

Redis与DataBase保持数据一致性
文章目录 1. 读取数据2. 写数据2.1 先操作缓存2.2 先操作数据库 在我们系统中缓存最常用的策略是:服务端需要同时维系DB和Cache,并且是以DB的结果为准, Cache-Aside Pattern(缓存分离模式、旁路缓存)。 1. 读取数据 当…...

解决 MacOS 连接公司 VPN 成功但是不能网络的问题
目录 解决办法2024 Mac mini 爆料 解决办法 操作比较简单,修改配置文件即可(如果没有则需要手动创建)。 sudo vim /etc/ppp/options在此文件下,加入 plugin L2TP.ppp: plugin L2TP.ppp如果文件里有l2tpnoipsec&…...

【Kubernetes】k8s集群之Pod容器资源限制和三种探针
目录 一、Pod容器的资源限制 1.资源限制 2.Pod 和容器的资源请求与限制 3.CPU 资源单位 4.内存资源单位 二、Pod容器的三种探针 1.探针的三种规则 2.Probe支持三种检查方法: 一、Pod容器的资源限制 1.资源限制 当定义 Pod 时可以选择性地为每个容器设定所…...

从古代驿站体系看软件安全管控@安全历史04
在古代,车、马都很慢,信息传递很不顺畅,中央的政令又是如何传达至地方的呢?实际上,很多朝代都有专门的驿站制度,可以保障全国各地的信息传递,对于维护统治和稳定有着关键作用。 若将国家比作一个…...

8.8 哈希表简单 1 Two Sum 141 Linked List Cycle
1 Two Sum class Solution { public:vector<int> twoSum(vector<int>& nums, int target) {//给的target是目标sum 要返回vector<int> res(2,0);是在num中找加数//首先假设每个输入都是由唯一的结果,而且不适用相同的元素两次一共有n*(n-1)种…...

动态规划之——背包DP(完结篇)
文章目录 概要说明分组背包模板例题1思路code模板例题2思路code 有依赖的背包问题模板例题思路code 背包问题求方案数模板例题思路code 背包问题求具体方案模板例题思路code 概要说明 本文讲分组背包、有依赖的背包、 背包问题求方案数以及背包问题求具体方案 入门篇(01背包和…...

Advanced IP Scanner - 网络扫描工具介绍
Advanced IP Scanner 是一款免费、快速且用户友好的网络扫描工具。它能够帮助用户扫描局域网(LAN)中的所有设备,提供详细的设备信息,包括IP地址、MAC地址、设备名称和厂商信息。该工具对IT管理员和普通用户都非常有用,…...

数据库事务的四大特性ACID
数据库事务的四大特性ACID 数据库事务(Transaction)是数据库管理系统(DBMS)执行过程中的一个逻辑单位,由一个或多个SQL语句组成,这些语句作为一个整体一起向系统提交,要么全部执行,…...

ELK架构介绍
一、ELK简介 ELK 是由三个开源软件组成的,分别是:Elasticsearch、Logstash和Kibana,这三个软件各自在日志管理和数据分析领域发挥着重要作用。Elasticsearch提供分布式存储和搜索能力;Logstash负责数据收集和处理,而K…...

Vscode下ESP32工程函数定义无法跳转
1.删除.vscode 2.按下 ctrlshiftp,搜索 ESP-IDF:Add vscode Configuration Folder...

liquibase.exception.LockException: Could not acquire change log lock.
项目场景: 启动应用花了好长时间,最后报出异常. 问题描述 启动应用花了好长时间,最后报出异常. 异常: Caused by: liquibase.exception.LockException: Could not acquire change log lock. Currently locked by LAPTOP-OQ9VB…...

【多线程-从零开始-捌】阻塞队列,消费者生产者模型
什么是阻塞队列 阻塞队里是在普通的队列(先进先出队列)基础上,做出了扩充 线程安全 标准库中原有的队列 Queue 和其子类,默认都是线程不安全的 具有阻塞特性 如果队列为空,进行出队列操作,此时就会出现阻…...

数据结构——栈(Stack)
目录 前言 一、栈的概念 1、栈的基本定义 2、栈的特性 二、栈的基本操作 1.相关操作概念 2.实现方式 (1)顺序栈 (2)链式栈 三、栈的应用 总结 前言 栈(Stack)是一种常见且重要的数据结构,它遵循…...
修改pom.xml为阿里云仓库并且让他生效
一、项目pom.xml添加 <repositories><repository><id>aliyun-central</id><name>Aliyun Maven Central</name><url>https://maven.aliyun.com/repository/central</url></repository><repository><id>aliyu…...

step13:qml/qt程序打包
文章目录 0.文章介绍1.软件发布2.准备打包软件3.双击开始运行打包软件4.点击安装5.参考连接 0.文章介绍 1.软件发布 打包之前需要先发布,参考教程连接 2.准备打包软件 官方下载地址:http://www.jrsoftware.org/isdl.php#stable 下载之后一路点击下一…...

招聘求职小程序
本文来自:ThinkPHPFastAdmin招聘求职小程序 - 源码1688 应用介绍 一款基于ThinkPHPFastAdmin开发的原生微信小程序招聘管理系统。 前端小程序演示: 后台管理网址: https://fastadmin.site100.cn/PbfhegDBAJ.php/index/login 网盘链接&#x…...

10分钟学会docker安装与使用
文章目录 1、docker简介2、docker的基本组成3、docker的安装与配置4、docker的常用命令 1、docker简介 什么是容器? 它是一种虚拟化的方案,是操作系统级别的虚拟化,只能运行相同或相似内核的操作系统,依赖于Linux内核特性&#x…...

vue3、uniapp-vue3模块自动导入
没有使用插件 使用插件,模块自动导入 安装: npm i -D unplugin-auto-importvite.config.js (uniapp没有此文件,在项目根目录下创建) import { defineConfig } from "vite"; import uni from "dcloudio/vite-plugin-uni"; import AutoImport from &qu…...
Ubantu设置国内镜像(阿里云、华为云)
1. 确定系统版本 国内有很多 Ubuntu 的镜像源,包括阿里的、网易的,还有很多教育网的源,比如:清华源、中科大源等。 不同的 ubantu 版本对应的镜像源有所不同,所以需要先查看系统的版本号: lsb_release -a…...

Redis远程字典服务器(3)——常用数据结构和单线程模型
目录 一,常用数据结构 1.0 前言 1.1 string 1.2 hash 1.3 list 1.4 set 1.5 zset 1.6 演示 二,关于单线程模型 2.1 关于Redis的单线程 2.2 Redis为什么快 一,常用数据结构 1.0 前言 Redis是采用键值对的方式来存储数据的&#…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...

iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...

C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
ThreadLocal 源码
ThreadLocal 源码 此类提供线程局部变量。这些变量不同于它们的普通对应物,因为每个访问一个线程局部变量的线程(通过其 get 或 set 方法)都有自己独立初始化的变量副本。ThreadLocal 实例通常是类中的私有静态字段,这些类希望将…...