使用数据库和缓存的时候,是如何解决数据不一致的问题的?
1.缓存更新策略
1.1. 缓存旁路模式(Cache Aside)
在应用里负责管理缓存,读取时先查缓存,如果命中了则返回缓存,如果未命中就查询数据库,然后返回缓存,返回缓存的同时把数据给写入缓存中。更新的时候则是先更新数据库,然后再删除缓存。
读: 先查缓存,缓存命中则之间返回,未命中则查数据库,数据库返回数据的同时写入缓存中。这样子下一次再查的时候就可以命中缓存了。
写: 先更新数据库,更新之后删除缓存。
优点是比较简单,对数据一致性要求不高的时候大多数场景能用,缺点就是可能会有短时间的数据不一致问题,主要是在写操作中删除缓存的时候。为什么会有数据不一致的时候呢?如果在把A改为B之后,缓存里还是A,但是在删除缓存之前,此时另一个线程已经进来了要读取缓存,那么它读取到的就是A(也就是旧的数据),它命中缓存了所以不会再访问数据库,但是此时数据库是B,明显出现了数据不一致的问题。这种情况一般是在并发情况出现。
1.2.写穿透模式(Write Through)
更新数据库的同时更新缓存,保障数据一致。
读: 直接查缓存。
写: 先更新数据库再更新缓存。
优点是数据一致性比较高,缺点是每次写操作都会更新缓存,缓存的压力可能会比较大。
1.3.写回模式(Write Back)
读: 直接查缓存。
写: 先更新缓存,然后异步更新数据库。
1.4.读写双删(属于缓存旁路模式的扩展)
在应用里负责管理缓存,读取时先查缓存,如果命中了则返回缓存,如果未命中就查询数据库,然后返回缓存,返回缓存的同时把数据给写入缓存中。更新的时候则是先更新数据库,然后再删除缓存,隔段时间再删除一次缓存,也就是一共删了两次缓存。
读: 先查缓存,缓存命中则之间返回,未命中则查数据库,数据库返回数据的同时写入缓存中。这样子下一次再查的时候就可以命中缓存了。
写: 先删除缓存,然后更新数据库,更新之后再次删除缓存。
要知道缓存旁路模式在并发情况下,可能会出现数据不一致问题,如果并发量比较高的话,出现问题的概率就会变大,所以有了读写双删这个扩展的方式。
具体实现:
1.先删除缓存(防止更新数据库后获取缓存的请求获取到旧数据)
2.然后更新数据库
3.然后删除缓存(防止此时的缓存里的数据和数据库里的不一致)
读写双删相对出现数据不一致的概率比较低,但也并不是一定的,如果在A线程删除缓存之后,更新数据库之前,此时有另一个线程B进来进行读操作,因为B的缓存未命中直接访问数据库,然后又会把数据写入缓存,此时缓存里的数据就是更新前的数据,但是A依然会进行更新数据库的操作,然后就导致数据库的数据和缓存不一致,当线程C来访问的时候,因为缓存命中,所以直接读到了旧数据。
1.5.读写双删(Double Delete)
具体实现:
1.先删除缓存(防止更新数据库后获取缓存的请求获取到旧数据)
2.然后更新数据库
3.等待一段时候后
4.然后删除缓存(防止此时的缓存里的数据和数据库里的不一致)
缓存失效策略
2.1.主动失效
在数据库更新的时候,立刻删除缓存或者更新缓存。
读: 直接查缓存。
写: 先写数据库,然后删缓存或者立马更新缓存。
2.2.被动失效
给缓存设置TTL(过期时间),过期后自动失效。
读: 直接查缓存。
写: 写入缓存时,设置TTL
优点是比较简单,缺点就是在缓存过期后、更新缓存前,可能会有短暂的数据不一致。
双写一致性策略
3.1.分布式锁
在更新数据库和缓存的时候,使用分布式锁,确保操作是原子性的(要么都成功要么都失败)。主要流程就是【获取分布式锁>>更新数据库>>更新缓存>>释放分布式锁】,优点是确保强一致性,缺点也很明显,因为加了锁所以没法支持并行操作,多线程到这里变成排队的单线程操作,会导致性能比较低。适用于对性能要求不高并且对数据一致性要求很高的场景。
3.2.消息队列
通过消息队列通知更新缓存,确保最终一致性(和强一致不一样)。主要流程就是【更新数据>>发送消息>>消费者读取消息更新缓存】,优点是异步操作,性能较好,缺点也是因为异步,所以缓存会有延迟,如果在更新缓存之前有其他请求获取缓存,可能就会出现数据不一致的情况。
其他一致性策略
4.1.读写分离
顾名思义,就是把读和写分开处理,读操作是从缓存中读数据,写操作则是更新数据库,并且更新缓存(即时或者异步都可),优点就是读性能会很好,缺点就是写操作时可能会导致数据库和缓存出现数据不一致的问题。
4.2.版本控制
给缓存添加一个版本号,每次更新缓存都增加版本号,确保版本和数据库的版本一致。优点就是能保障数据的一致性,缺点是实现起来比较复杂。
相关文章:
使用数据库和缓存的时候,是如何解决数据不一致的问题的?
1.缓存更新策略 1.1. 缓存旁路模式(Cache Aside) 在应用里负责管理缓存,读取时先查缓存,如果命中了则返回缓存,如果未命中就查询数据库,然后返回缓存,返回缓存的同时把数据给写入缓存中。更新…...
VS Code C++ 开发环境配置
VS Code 是当前非常流行的开发工具. 本文讲述如何配置 VS Code 作为 C开发环境. 本文将按照如下步骤来介绍如何配置 VS Code 作为 C开发环境. 安装编译器安装插件配置工作区 第一个步骤的具体操作会因为系统不同或者方案不同而有不同的选择. 环境要求 首先需要立即 VS Code…...
使用OpenCV和MediaPipe库——实现人体姿态检测
目录 准备工作如何在Windows系统中安装OpenCV和MediaPipe库? 安装Python 安装OpenCV 安装MediaPipe 验证安装 代码逻辑 整体代码 效果展示 准备工作如何在Windows系统中安装OpenCV和MediaPipe库? 安装Python 可以通过命令行运行python --versio…...
JWT的学习
1、HTTP无状态及解决方案 HTTP一种是无状态的协议,每次请求都是一次独立的请求,一次交互之后就是陌生人。 以CSDN为例,先登录一次,然后浏览器退出,这个时候在进入CSDN,按理说服务器是不知道你已经登陆了&…...
elasticsearch是哪家的
Elasticsearch:数据搜索与分析的领航者 在当今这个信息爆炸的时代,快速且准确地处理海量数据成为了众多企业和组织追求的目标。而Elasticsearch正是在这个背景下脱颖而出的一款强大的开源搜索引擎。它是由位于美国加利福尼亚州的Elastic公司所开发和维护…...
《A++ 敏捷开发》- 18 软件需求
需求并不是关于需求 (Requirements are not really about requirements) 大家去公共图书馆寄存物品,以前都是扫二维码开箱,有些图书馆升级了使用指纹识别。 “是否新方法比以前好?”我问年轻的开发人员。 “当然用指纹识别好。新技术&#x…...
计算机网络:计算机网络的组成和功能
计算机网络的组成: 计算机网络的工作方式: 计算机网络的逻辑功能; 总结: 计算机网络的功能: 1.数据通信 2.资源共享 3.分布式处理:计算机网络的分布式处理是指将计算任务分散到网络中的多个节点(计算机或设备&…...
Upload-Labs-Linux 1-20
前端校验绕过:pass 01 两种思路:1.通过抓包,修改后缀 2.前端禁用js绕过前端后缀检验 首先写一个木马,改为图片格式GIF89a<?php eval($_POST[cmd])?>抓包之后改为PHP格式: 使用蚁剑连接木马,第一次尝…...
Compose笔记(八)--权限
这一节主要了解一下Compose中权限的申请,其中主要用到accompanist-permissions这个权限库,它是一个简化的Android Compose 中权限管理的库,如下使用: 栗子: 依赖添加 dependencies {implementation("com.google.accompani…...
单例模式:确保一个类只有一个实例
目录 引言 1. 单例模式的核心思想 2. 单例模式的实现方式 2.1 饿汉式单例 2.2 懒汉式单例 2.3 线程安全的懒汉式单例 2.4 双重检查锁定(Double-Checked Locking) 2.5 静态内部类实现单例 2.6 枚举实现单例 3. 单例模式的使用场景 4. 单例模式…...
推荐一个好用的在线文本对比网站 - diffchecker
推荐网址:https://www.diffchecker.com UI设计也很不错,响应也很快,广告少 生成的对比还可以生成在线链接:(点击右上角“分享”) 可设置过期时间等 我生成的示例:https://www.diffchecker.c…...
学习第八十五行
[capture](parameters) -> return_type {// function body }capture: 捕获列表,指定如何捕获周围作用域中的变量。parameters: 参数列表,与普通函数类似。return_type: 返回类型,可以省略,编译器会自动推断。function body: 函…...
基于Django创建一个WEB后端框架(DjangoRestFramework+MySQL)流程
一、Django项目初始化 1.创建Django项目 Django-admin startproject 项目名 2.安装 djangorestframework pip install djangorestframework 解释: Django REST Framework (DRF) 是基于 Django 框架的一个强大的 Web API 框架,提供了多种工具和库来构建 RESTf…...
【Python 2D绘图】Matplotlib绘图(统计图表)
【Python 2D绘图】Matplotlib绘图(统计图表) 1. 概述1.1 简介1.2 安装1.3 导入1.4 保存1.5 数据来源1.5.1 Numpy ndarray1.5.2 Pandas DataFrame 1.6 中文显示 2. 基础样式2.1 颜色2.1.1 简称2.1.2 全称 2.2 布局2.2.1 Matplotlib 画布划分2.2.2 绘制子图…...
vue3框架的响应式依赖追踪机制
当存在一个响应式变量于视图中发生改变时会更新当前组件的所以视图显示,但是没有视图中不写这个响应式变量就就算修改该变量也不会修改视图,这是为什么?我们能否可以理解宽泛的理解为vue组件的更新就是视图的更新,单当视图中不存在…...
.Net 6 上传文件接口 文件大小报错整体配置
/// <summary>/// 上传文件/// </summary>/// <param name"file"></param>/// <returns></returns>[HttpPost("UploadifyFile")][RequestSizeLimit(2000 * 1024 * 1024)] // 设置最大请求体大小为 100MBpublic async …...
Git基础之工作原理
基础概念 git本地有三个工作区域,工作目录 Working Directory,暂存区Stage/Index和资源区Repository/Git Directory,如果在加上远程的git仓库就是四个工作区域 四个区域与文件交换的命令之间的关系 WorkSpace:工作区,就…...
小程序 wxml 语法 —— 41列表渲染 - 进阶用法
这一节讲解列表渲染的两个进阶用法: 如果需要对默认的变量名和下标进行修改,可以使用 wx:for-item 和 wx:for-item: 使用 wx:for-item 可以指定数组当前元素的变量名使用 wx:for-index 可以指定数组当前下标的变量名 将 wx:for 用在 标签上&…...
ElasticSearch 入门教程
ElasticSearch 入门教程 ElasticSearch 是一个分布式、可扩展的搜索和分析引擎,基于 Apache Lucene 构建,支持全文检索、结构化查询和聚合分析。本教程将带你深入了解 ElasticSearch 的核心概念、安装配置、常见操作,并提供示例代码…...
用Python写一个算24点的小程序
一、运行界面 二、显示答案——递归介绍 工作流程: 1. 基本情况:函数首先检查输入的数字列表 nums 的长度。如果列表中只剩下一个数字,它会判断这个数字是否接近 24(使用 abs(nums[0] - 24) < 1e-10 来处理浮点数精度问题&…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
