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

redis:四、双写一致性的原理和解决方案(延时双删、分布式锁、异步通知MQ/canal)、面试回答模板

双写一致性

场景导入

如果现在有个数据要更新,是先删除缓存,还是先操作数据库呢?当多个线程同时进行访问数据的操作,又是什么情况呢?

以先删除缓存,再操作数据库为例

多个线程运行的正常的流程应该如下:
线程1先访问数据,它首先删除缓存,然后更新数据库。之后线程2来查询缓存,未命中后查询数据库,随后写入缓存。
也就是说,线程1负责删除缓存并更新数据库,线程2负责查询数据库并写入缓存。
在这里插入图片描述

但如果线程2在线程1还未更新数据库的时候,就查询数据库了,那么就会出问题。
在这里插入图片描述

以先操作数据库,再删除缓存为例。

正常流程应该如下:
线程2负责更新数据库并删除缓存。线程1负责查询数据库,并写入缓存。
其实也可以说

线程1负责更新数据库并删除缓存。线程2负责查询数据库,并写入缓存。

我把上面的“以先删除缓存,再操作数据库为例”搬过来了,可以对比一下。

也就是说,线程1负责删除缓存并更新数据库,线程2负责查询数据库并写入缓存。

发现就是前半部分顺序颠倒了而已。
在这里插入图片描述
同样的,

但如果线程1在线程2还更新数据库的时候,就查询数据库了,那么就会出问题。

我同样把上面的异常情况搬过来对比。

但如果线程2在线程1还未更新数据库的时候,就查询数据库了,那么就会出问题。

在这里插入图片描述

定义

当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致

解决方案

能保障强一致性:延时双删、分布式锁
不能保障强一致性,只能保障最终的一致性:异步通知

延时双删(强一致性)

延时双删就是正常删除缓存、修改数据库后还要延时一会再次删除缓存。
在这里插入图片描述
因为从上面的场景导入,我们发现,无论是先删除缓存还是先修改数据库,都会有数据不一致,即脏数据的风险。

再次把先删除缓存,再修改数据库的异常流程图拿过来,我们发现整个流程走完后,线程1更新数据库,拿到的是正确的值。而线程2拿到的是错误的值,这时只要我们以数据库为主,删除缓存,再写入数据库的值,那么就能拿到正确的值。

在这里插入图片描述
此外,延时一会是因为一般数据库都是主从分离,读写分离的。延时是为了让主库有时间通知到从库,所有数据库的更新操作全部走完。
延时双删极大程度上避免了脏数据的风险,但因为有延时的存在,延时时间不好控制,所以也不能说百分百避免。

分布式锁(强一致性)

互斥锁

直接加互斥锁能保障数据的强一致性,但是性能较低。此时我们就需要优化一下互斥锁。因为存入缓存的数据,一般都是读多写少。为此我们引入两个单独的锁,分别叫共享锁和排他锁。

共享锁/读锁

共享锁,又叫读锁(readLock),加锁之后,其他线程可以共享读操作。

排他锁/独占锁

排他锁,又叫独占锁(writeLock),加锁之后,阻塞其他线程读和写操作。

混合使用的流程和代码

在这里插入图片描述
我们想要拿到共享锁或者排他锁,都需要先拿到读写锁。
通过固定代码可以拿到读写锁。

RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("ITEM_READ_WRITE_LOCK");

随后分别拿到共享锁和排他锁。(注意两个锁需要是同一把读写锁)

RLock readLock = readWriteLock.readLock();
RLock writeLock = readWriteLock.writeLock();

读操作的代码

public void getById(Integer id){RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("ITEM_READ_WRITE_LOCK");RLock readLock = readWriteLock.readLock();try{readLock.lock();System.out.println("readLock...");Item item = (Item) redisTemplate.opsForValue().get("item"+id);if(item != null){return item;}item = new Item(id, "华为手机", "华为手机", 5999.00);redisTemplate.opsForValue().set("item"+id, item);return item;}finally{readLock.unlock();}
}

写操作的代码

public void updateById(Integer id){RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("ITEM_READ_WRITE_LOCK");RLock writeLock = readWriteLock.writeLock();try{writeLock.lock();System.out.println("writeLock...");Item item = new Item(id, "华为手机", "华为手机", 5299.00);try{Thread.sleep(10000);}catch(InterruptedException e){e.printStackTrace();}redisTemplate.delete("item"+id);}finally{writeLock.unlock();}
}

异步通知

异步通知的也有两个主流方案:MQ、Canal
在这里插入图片描述


在这里插入图片描述
canal的方案对于业务代码几乎是零侵入的。

面试回答模板

redis为缓存,mysql的数据如何与redis进行同步呢?

背熟以下回答,大概用时1min。

这个要看业务需求,如果要求数据的强一致性,那么一般使用读写锁来实现。读写锁是一种分布式锁机制,里面包括两种锁,一个叫共享锁,在读的时候添加共享锁,可以保证读读不互斥,读写互斥。一个叫排他锁,在写的时候添加排他锁,可以保证读写都互斥,避免脏数据的风险。
如果不要求数据的强一致性,那么就可以用基于MQ或者canal中间件的异步通知,来实现redis和mysql的双写一致性。

你的项目中用到了redis,那你mysql的数据如何与redis进行同步呢?

——————————————强一致性策略——————————————————

以我最近做的这个项目为例,里面有xxxx(根据自己的简历上写)的功能,需要让数据库与redis高度保持一致,因为要求时效性比较高,我们当时采用的读写锁保证的强一致性。
读写锁是一种分布式锁机制,里面包括两种锁,一个叫共享锁,在读的时候添加共享锁,可以保证读读不互斥,读写互斥。一个叫排他锁,在写的时候添加排他锁,可以保证读写都互斥,避免脏数据的风险。这里面需要注意的是读方法和写方法上需要使用同一把锁才行。

面试官:那这个排他锁是如何保证读写、读读互斥的呢?

候选人:其实排他锁底层使用也是setnx,保证了同时只能有一个线程操作锁住的方法

面试官:你听说过延时双删吗?为什么不用它呢?

候选人:延迟双删,如果是写操作,我们先把缓存中的数据删除,然后更新数据库,最后再延时删除缓存中的数据,其中这个延时多久不太好确定,在延时的过程中可能会出现脏数据,并不能保证强一致性,所以没有采用它。

——————————————非强一致性策略——————————————————

面试官:redis做为缓存,mysql的数据如何与redis进行同步呢?(双写一致性)

候选人:嗯!就说我最近做的这个项目,里面有xxxx(根据自己的简历上写)的功能,数据同步可以有一定的延时(符合大部分业务)

我们当时采用的阿里的canal组件实现数据同步:不需要更改业务代码,部署一个canal服务。canal服务把自己伪装成mysql的一个从节点,当mysql数据更新以后,canal会读取binlog数据,然后在通过canal的客户端获取到数据,更新缓存即可。

相关文章:

redis:四、双写一致性的原理和解决方案(延时双删、分布式锁、异步通知MQ/canal)、面试回答模板

双写一致性 场景导入 如果现在有个数据要更新,是先删除缓存,还是先操作数据库呢?当多个线程同时进行访问数据的操作,又是什么情况呢? 以先删除缓存,再操作数据库为例 多个线程运行的正常的流程应该如下…...

智能优化算法应用:基于动物迁徙算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于动物迁徙算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于动物迁徙算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.动物迁徙算法4.实验参数设定5.算法结果6.…...

illuminate/database 使用 五

之前文章: illuminate/database 使用 一-CSDN博客 illuminate/database 使用 二-CSDN博客 illuminate/database 使用 三-CSDN博客 illuminate/database 使用 四-CSDN博客 一、原生查询 1.1 原理 根据之前内容调用执行的静态类为Illuminate\Database\Capsule\M…...

武汉灰京文化:益智游戏的教育与娱乐完美结合

随着游戏技术的不断发展,益智类游戏正经历着一场革命性的变革,逐渐融合了教育和娱乐的元素。创新的设计和互动方式使得许多益智游戏成为了知识传递和技能训练的有效工具,同时保持了娱乐体验的趣味性。这种教育与娱乐的完美结合不仅使益智游戏…...

arcgis api for js 中的query实现数据查询

相当于服务地址中的query查询 获取图层范围内的数据4.24 import Query from arcgis/core/rest/support/Query; import * as QueryTask from "arcgis/core/rest/query";//获取图层范围内的数据4.24 _returnFeatureFromWhere(url, where, geo) {const self thisretu…...

AcWing 1250. 格子游戏(并查集)

题目链接 活动 - AcWing本课程系统讲解常用算法与数据结构的应用方式与技巧。https://www.acwing.com/problem/content/1252/ 题解 当两个点已经是在同一个连通块中,再连一条边,就围成一个封闭的圈。一般用x * n y的形式将(x, y&#xff0…...

CSS对文本的简单修饰

CSS格式&#xff1a; 格式一&#xff1a;在head中的style标签范围内。 < style> 在style内的只写名字不写 &#xff1a; < > 选择器 { 属性的名称 &#xff1a; 样式&#xff1b; 属性的名称&#xff1a;样式&#xff1b; } < style> style中的注释用/* *…...

C++17中if和switch语句的新特性

1.从C17开始&#xff0c;if语句允许在条件表达式里添加一条初始化语句。当仅在if语句范围内需要变量时&#xff0c;使用这种形式的if语句。在if语句的条件表达式里定义的变量将在整个if语句中有效&#xff0c;包括else部分。 std::mutex mx; bool shared_flag true; // guard…...

极坐标下的牛拉法潮流计算57节点MATLAB程序

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 潮流计算&#xff1a; 潮流计算是根据给定的电网结构、参数和发电机、负荷等元件的运行条件&#xff0c;确定电力系统各部分稳态运行状态参数的计算。通常给定的运行条件有系统中各电源和负荷点的功率、枢纽…...

软件设计师——计算机网络(三)

&#x1f4d1;前言 本文主要是【计算机网络】——软件设计师——计算机网络的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1…...

【ArkTS】循环控制与List的使用

ArkTS如何进行循环渲染 现有数据如下 class Item{name:stringimage:Resourceprice:numberdicount:numberconstructor(name:string,image:Resource,price:number,dicount?:number) {this.name namethis.image imagethis.price pricethis.dicount dicount} }private items…...

条款3:尽量使用const

文章目录 const指针和函数声明const修饰指针const修饰函数const修饰容器const应用在函数中 const限定成员函数避免const重载的代码重复总结 const指针和函数声明 const修饰指针 char greeting[] "Hello"; char* p greeting; // non-const 指针,// non-const 数据…...

Chromadb词向量数据库总结

简介 Chroma 词向量数据库是一个用于自然语言处理&#xff08;NLP&#xff09;和机器学习的工具&#xff0c;它主要用于词嵌入&#xff08;word embeddings&#xff09;。词向量是将单词转换为向量表示的技术&#xff0c;可以捕获单词之间的语义和语法关系&#xff0c;使得计算…...

Gin之GORM 操作数据库(MySQL)

GORM 简单介绍 GORM 是 Golang 的一个 orm 框架。简单说&#xff0c;ORM 就是通过实例对象的语法&#xff0c;完成关系型数据库的操作的技术&#xff0c;是"对象-关系映射"&#xff08;Object/Relational Mapping&#xff09; 的缩写。使用 ORM框架可以让我们更方便…...

二十七、读写文件

二十七、读写文件 27.1 文件类QFile #include <QCoreApplication>#include<QFile> #include<QDebug>int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);QFile file("D:/main.txt");if(!file.open(QIODevice::WriteOnly | QIODe…...

flutter 代码混淆

Flutter 应用混淆&#xff1a; Flutter 应用的混淆非常简单&#xff0c;只需要在构建 release 版应用时结合使用 --obfuscate 和 --split-debug-info 这两个参数即可。 –obfuscate --split-debug-info 用来指定输出调试文件的位置&#xff0c;该命令会生成一个符号映射表。目前…...

05 Vue中常用的指令

概述 All Vue-based directives start with a v-* prefix as a Vue-specific attribute. 所有基于 Vue 的指令都以 v-* 前缀作为 Vue 特有的属性。 v-text The v-text directive has the same reactivity as with interpolation. Interpolation with {{ }} is more perform…...

Mr. Cappuccino的第67杯咖啡——MacOS通过PD安装Win11

MacOS通过PD安装Win11 下载ParallelsDesktop安装ParallelsDesktop激活ParallelsDesktop下载Windows11安装Windows11激活Windows11 下载ParallelsDesktop ParallelsDesktop下载地址 安装ParallelsDesktop 关闭上面的窗口&#xff0c;继续操作 激活ParallelsDesktop 关闭上面的…...

【云原生kubernets】Service 的功能与应用

一、Service介绍 在kubernetes中&#xff0c;pod是应用程序的载体&#xff0c;我们可以通过pod的ip来访问应用程序&#xff0c;但是pod的ip地址不是固定的&#xff0c;这也就意味着不方便直接采用pod的ip对服务进行访问。为了解决这个问题&#xff0c;kubernetes提供了Service资…...

docker安装Prometheus

docker安装Prometheus Docker搭建Prometheus监控系统 环境准备(这里的环境和版本是经过测试没有问题,并不是必须这个版本) 主机名IP配置系统说明localhost随意2核4gCentOS7或者Ubuntu20.0.4docker版本23.0.1或者24.0.5,docker-compose版本1.29 安装Docker Ubuntu20.0.4版本…...

了解 Flutter 3.16 功能更新

作者 / Kevin Chisholm 我们在季度 Flutter 稳定版发布会上带来了 Flutter 3.16&#xff0c;此版本包含诸多更新: Material 3 成为新的默认主题、为 Android 带来 Impeller 的预览版、允许添加适用于 DevTools 的扩展程序等等&#xff0c;以及同步推出 Flutter 休闲游戏工具包重…...

python之画动态图 gif效果图

import pandas as pd import matplotlib import matplotlib.pyplot as plt import os# set up matplotlib is_ipython inline in matplotlib.get_backend() if is_ipython:from IPython import displayplt.ion()def find_csv_files(directory):csv_files [] # 用于存储找到的…...

【JavaWeb】用注解代替配置文件

WebServlet("/query") public class QueryServlet extends HttpServlet {...}在Servlet类上写WebServlet("query"),就相当于在配置文件里写了↓ <servlet><servlet-name>query</servlet-name><servlet-class>QueryServlet</se…...

SpringBoot 3.0 升级之 Swagger 升级

文章目录 SpringFox3.0.0openapi3Swagger 注解迁移ApiApiOperationApiImplicitParamApiModelApiModelProperty 最近想尝试一下最新的 SpringBoot 项目&#xff0c;于是将自己的开源项目进行了一些升级。 JDK 版本从 JDK8 升级至 JDK17。SpringBoot 版本从 SpringBoot 2.7.3 升…...

AR游戏开发

增强现实&#xff08;Augmented Reality&#xff0c;AR&#xff09;游戏是一种整合了虚拟和现实元素的游戏体验。玩家通过使用AR设备&#xff08;如智能手机、AR眼镜或平板电脑&#xff09;来与真实世界互动&#xff0c;游戏中的数字内容与真实环境相结合。以下是一些关于AR游戏…...

Easy Excel生成复杂下Excel模板(下拉框)给用户下载

引言 文件的下载是一个非常常见的功能&#xff0c;也有一些非常好的框架可以使用&#xff0c;这里我们就介绍一种比较常见的场景&#xff0c;下载Excel模版&#xff0c;导入功能通常会配有一个模版下载的功能&#xff0c;根据下载的模版&#xff0c;填充数据然后再上传。 需求…...

基于EasyExcel的数据导入导出

前言&#xff1a; 代码复制粘贴即可用&#xff0c;主要包含的功能有Excel模板下载、基于Excel数据导入、Excel数据导出。 根据实际情况修改一些细节即可&#xff0c;最后有结果展示&#xff0c;可以先看下结果&#xff0c;是否是您想要的。 台上一分钟&#xff0c;台下60秒&a…...

电子学会C/C++编程等级考试2021年06月(六级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:逆波兰表达式 逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3。逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的逆波兰表示法为* +…...

智能优化算法应用:基于供需算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于供需算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于供需算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.供需算法4.实验参数设定5.算法结果6.参考文献7.MA…...

vue3 setup语法糖写法基本教程

前言 官网地址&#xff1a;Vue.js - 渐进式 JavaScript 框架 | Vue.js (vuejs.org)下面只讲Vue3与Vue2有差异的地方&#xff0c;一些相同的地方我会忽略或者一笔带过与Vue3一同出来的还有Vite&#xff0c;但是现在不使用它&#xff0c;等以后会有单独的教程使用。目前仍旧使用v…...

直接在原备案号下增加新网站/营销网

有没有发现&#xff0c;最近学Python的程序员越来越多了&#xff0c;不少人开始把Python当做第一语言来学习。但结合我最近这些年Python的学习、开发经验&#xff0c;发现超90%的人在初学Python时都可能会遇到下面这些问题&#xff1a; 应用方向太多了&#xff0c;完全不知道怎…...

餐饮加盟网站怎么做/最新国际新闻头条今日国际大事件

1.对单字符的查找&#xff1a; 1.1单字符&#xff1a; ‘X’ $ grep ‘q’ passwd //查找单个字符 1.2 范围字符 [] [^] 1.3 任意字符 . $ grep [1-9] passwd //查找某个范围的单个字符&#xff08;范围&#xff09; $ grep [a-zA-Z] passwd //查找某个范围的单个字符&#xff…...

wordpress信用卡支付宝/sem投放是什么意思

在 Spring.Net 中对象初始化的方式分为两种&#xff1a; ① 急切实例化&#xff0c;也就是说 Spring.Net 容器初始化的时候将对象先实例化出来。 ② 延迟实例化&#xff0c;也就是说我们在调用 GetObject 方法时才实例化该对象。 Spring.Net 默认使用的 急切实例化 ( lazy-init…...

长沙网站建设哪家靠谱/郑州见效果付费优化公司

String.prototype.charAt()str.charAt(index)返回字符串中指定位置的字符。字符串中的字符从左向右索引&#xff0c;第一个字符的索引值为 0&#xff0c;最后一个字符(假设该字符位于字符串 stringName 中)的索引值为 stringName.length - 1。如果指定的 index 值超出了该范围&…...

促销礼品网站建设/新闻发稿渠道

execute()方法一直是阻塞状态原因:一般是在等待接口的返回。解决办法:接口给个返回值(这个是接口无返回值的情况)或者设置读取接口返回结果的超时时间。...

公司为什么建立网站/整合营销策略有哪些

关于讲理老公&#xff1a;你不讲理。老婆&#xff1a;和你我从来就没讲过理&#xff0c;家就不是讲理的地方。再说你是男的&#xff0c;还比我大8个月呢&#xff0c;你就得让着我。关于钱老公&#xff1a;以后我挣的钱&#xff0c;按比例给你吧&#xff0c;我挣的多时留得也多一…...