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

缓存和数据库一致性问题分析

目录

1、数据不一致的原因

1.1 并发操作

1.2 非原子操作

1.3 数据库主从同步延迟

2、数据不一致的解决方案

2.1 并发操作

2.2 非原子操作

2.3 主从同步延迟

2.4 最终方案

3、不同场景下的特殊考虑

3.1 读多写少的场景

3.2 读少写多的场景


1、数据不一致的原因

导致缓存和数据库数据不一致的原因有三个

  • 并发操作
  • 非原子操作
  • 数据库主从同步延迟

1.1 并发操作

假设数据库的原数据为x=0,考虑两种并发情况

  • 两个线程同时写入
  • 一个线程读,一个线程写

有以下4种方案

  • 先更新缓存,后更新数据库
  • 先更新数据库,后更新缓存
  • 先删除缓存,再更新数据库
  • 先更新数据库,再删除缓存

(1)先更新缓存,后更新数据库

两个线程同时写入

  • A更新缓存,x=1
  • B更新缓存,x=2
  • B更新数据库,x=2
  • A更新数据库,x=1

最终缓存为2,数据库为1

一个线程读,一个线程写

  • A读取缓存发现没有命中,于是读取数据库,得到x=0
  • B更新缓存,x=1
  • B更新数据库,x=1
  • A更新缓存,x=0

最终缓存为0,数据库为1

这种情况发生的概率极小,需要同时满足几个条件

  • 第一,缓存不存在
  • 第二,A的更新缓存命令 后于 B的更新缓存命令(基本不可能发生)
  • 第三,A读取数据库+更新缓存的时间 > B更新缓存+B更新数据库的时间(基本不可能发生,因为写数据库的耗时大概率是比读数据库慢)

(2)先更新数据库,后更新缓存

两个线程同时写入

  • A更新数据库,x=2
  • B更新数据库,x=1
  • B更新缓存,x=1
  • A更新缓存,x=2

最终缓存为2,数据库为1

一个线程读,一个线程写

  • A读取缓存发现没有命中,于是读取数据库,得到x=0
  • B更新数据库,x=1
  • B更新缓存,x=1
  • A更新缓存,x=0

最终缓存为0,数据库为1

这种情况发生的概率也是极小,跟方案2的发生条件一样。

(3)先删除缓存,再更新数据库

两个线程同时写入

由于是删除缓存,多线程同时更新的话,缓存都是会被删除,没有讨论意义

一个线程读,一个线程写

  • A读取缓存发现没有命中,于是读取数据库,得到x=0
  • B删除缓存
  • A更新缓存,x=0
  • B更新数据库,x=1

最终,缓存是0,数据库是1

(4)先更新数据库,再删除缓存

两个线程同时写入

由于是删除缓存,多线程同时更新的话,缓存都是会被删除,没有讨论意义

一个线程读,一个线程写

  • A读取缓存发现没有命中,于是读取数据库,得到x=0
  • B更新数据库,x=1
  • B删除缓存
  • A更新缓存,x=0

最终,缓存是0,数据库是1

这种情况发生的概率也是极小,需要同时满足几个条件

  • 第一,缓存不存在
  • 第二,B更新数据库+删除缓存的时间 < A读取数据库+更新缓存的时间 (基本不可能发生,因为写数据库的耗时大概率是比读数据库慢)

1.2 非原子操作

非原子操作很好理解,就是因为操作缓存和操作数据库是两步操作,所以当第二步操作失败时,就会导致数据不一致问题。

1.3 数据库主从同步延迟

以上都只考虑了单机数据库的情况,对于主从数据库还有另一个问题,就是主从同步延迟

考虑以下情况

一个往主库写入,一个从从库读取

  • A更新主库,x=1
  • A删除缓存
  • B查询缓存没有命中,查询从库,得到x=0
  • 从库同步主库,更新为x=1
  • B更新缓存,x=0

最终,缓存是0,数据库是1

2、数据不一致的解决方案

2.1 并发操作

根据1.1的几种方案,『先更新数据库,再删除缓存』是最好的。

2.2 非原子操作

最简单的解决办法就是重试,但是重试也要考虑一些问题:

  • 立即重试的话大概率会失败;
  • 重试次数设置多少比较合适;
  • 同步重试会一直占用资源;
  • 重试的过程中服务重启,会导致重试的操作消失,数据会一直不一致

所以就能想到异步重试方法,也就是把重试的这个操作写入到消息队列里,由另一个线程专门来处理重试的操作,而且消息队列本身可以保证消息不丢失(不丢失有两个方面,一是消息持久化,二是只有正确被消费掉了才会删除)

除了消息队列这中异步重试方案外,业界还有一种监听数据库bin log的方式,监听到变化后再去操作缓存,但是这种会额外引入其他的中间件而且实现复杂,综合而言没有消息队列的方案好用。

2.3 主从同步延迟

主从同步延迟的解决方案也很明显,就是延迟删除缓存,但是延迟多久再执行删除呢?这个就要靠经验了,一般来说1~5秒不等,看具体业务

所以在之前方案的基础上,引入延迟删除可以解决主从同步延迟的问题。

2.4 最终方案

1)更新数据库

2)删除缓存

3)如果删除失败则额外写入一条重试删除命令到消息队列

4)最后写入一个延迟删除命令到消息队列

3、不同场景下的特殊考虑

3.1 读多写少的场景

这种场景下,redis的作用是为了减轻数据库读取压力、加速读取,往往能接受一定的数据延迟,即保证最终一致性即可。

  • 读多,所以删除缓存操作会导致缓存穿透问题(key不存在,大量请求命中数据库)
  • 写少,所以基本不存在并发写入的问题,但是会存在并发读取和写入的问题

所以,读多写少的场景下,方案3和4是容易出现大问题的。

方案1和方案2是相对能接受的,但是也会有一定概率存在并发写入导致数据不一致的问题。

此时我们可以通过给缓存设置过期时间,使得数据保证最终一致性。

3.2 读少写多的场景

这种场景下,redis的作用是为了减轻数据库写入压力,对数据的一致性要求较高。

  • 读少,所以并发读取和写入的情况比较少
  • 写多,所以并发写入的情况比较多

由于并发写入情况比较多,此时方案3和4比较好,根据上文的分析,方案4比方案3更好。

相关文章:

缓存和数据库一致性问题分析

目录 1、数据不一致的原因 1.1 并发操作 1.2 非原子操作 1.3 数据库主从同步延迟 2、数据不一致的解决方案 2.1 并发操作 2.2 非原子操作 2.3 主从同步延迟 2.4 最终方案 3、不同场景下的特殊考虑 3.1 读多写少的场景 3.2 读少写多的场景 1、数据不一致的原因 导致…...

用Rust生成Ant-Design Table Columns | 京东云技术团队

经常开发表格&#xff0c;是不是已经被手写Ant-Design Table的Columns整烦了&#xff1f; 尤其是ToB项目&#xff0c;表格经常动不动就几十列。每次照着后端给的接口文档一个个配置&#xff0c;太头疼了&#xff0c;主要是有时还会粘错就尴尬了。 那有没有办法能自动生成colu…...

java.lang.ClassNotFoundException: sun.misc.BASE64Decoder

有一个新的应用服务&#xff0c;idea启动应用应用服务时&#xff0c;突然报错java.lang.ClassNotFoundException: sun.misc.BASE64Decoder &#xff0c;然后在网上搜索&#xff0c;说是建议使用apache包&#xff0c;该类新的JRE已经废弃&#xff0c;并从rt.jar包中移除。但是该…...

Unity进阶--对象池数据场景管理器笔记

文章目录 泛型单例类泛型单例类&#xff08;不带组件版&#xff09;对象池管理器数据管理器场景管理器 泛型单例类 using System.Collections; using System.Collections.Generic;public abstract class ManagersSingle<T> where T : new() {private static T instance;…...

【Seata】微服务集成seata

文章目录 1、Seata介绍2、Seata架构3、部署TC服务4、微服务集成seata 1、Seata介绍 Seata是 2019 年 1 月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案。 官网http://seata.io/ 2、Seata架构 Seata事务管理有三个角色&#xff1a; TC (Transaction Coordinator) - 事务…...

解决react,<img>src使用require方法引入图片不显示问题

{settingList.map(i > (<img src{require(./images/${i.deviceTypeName}.png).default} />))} 解决方法&#xff1a; 再导入的图片后加.default即可 <img src{require(../../images/bg.png).default} alt"" /> 推荐阅读&#xff1a;https://www.cnb…...

从小白到大神之路之学习运维第67天-------Tomcat应用服务 WEB服务

第三阶段基础 时 间&#xff1a;2023年7月25日 参加人&#xff1a;全班人员 内 容&#xff1a; Tomcat应用服务 WEB服务 目录 一、中间件产品介绍 二、Tomcat软件简介 三、Tomcat应用场景 四、安装配置Tomcat 五、配置目录及文件说明 &#xff08;一&#xff09;to…...

图解SQL基础知识,小白也能看懂的SQL文章

本文介绍关系数据库的设计思想&#xff1a; 在 SQL 中&#xff0c;一切皆关系。 在计算机龄域有许多伟大的设计理念和思想&#xff0c;例如&#xff1a; 在 Unix 中&#xff0c;一切皆文件。 在面向对象的编程语言中&#xff0c;一切皆对象。 关系数据库同样也有自己的设计…...

自动驾驶感知系统-毫米波雷达

毫米波雷达就是电磁波&#xff0c;雷达通过发射无线电信号并接收反射信号来测定车辆与物体间的距离&#xff0c;其频率通常介于10~300GHz之间。与厘米波导引头相比&#xff0c;毫米波导引头体积小&#xff0c;质量轻&#xff0c;空间分辨率高&#xff1b;与红外、激光、电视等光…...

Esp32_Arduino接入腾讯云笔记

ESP32是一款由乐鑫科技&#xff08;Espressif Systems&#xff09;推出的双核、低功耗、集成Wi-Fi和蓝牙的单芯片微控制器。它采用了Tensilica Xtensa LX6高性能处理器&#xff0c;具有大量的GPIO引脚、模数转换器、SPI、I2S、UART、PWM、I2C和SD卡接口等功能&#xff0c;可以满…...

python简单入门

python简单入门 文章目录 python简单入门0. 地址链接1. 官网2.2. 下载地址3. 官方文档 1. 第一章1.1 python解释器1.2 基础语法1.2.1 常见数据类型1.2.2 强制类型转换1.2.3 注释1.2.4 运算符1.2.5 字符串1.2.5.1 字符串的定义1.2.5.2 字符串拼接1.2.5.3 格式化字符串1.2.5.3 精…...

如何快速从csv文件搭建一个简单的神经网络模型(回归)

快速搭建一个简单的神经网络预测模型 采用的数据是kaggle的房价预测数据 涉及的数据文件&#xff0c;提取码为&#xff1a;zxcv #导入相关包 import pandas as pd import numpy as np import torch import torch.nn as nn首先读取数据 trainpd.read_csv("path",enc…...

Pytorch深度学习-----DataLoader的用法

系列文章目录 PyTorch深度学习——Anaconda和PyTorch安装 Pytorch深度学习-----数据模块Dataset类 Pytorch深度学习------TensorBoard的使用 Pytorch深度学习------Torchvision中Transforms的使用&#xff08;ToTensor&#xff0c;Normalize&#xff0c;Resize &#xff0c;Co…...

macOS Ventura 13.5 (22G74) Boot ISO 原版可引导镜像下载

macOS Ventura 13.5 (22G74) Boot ISO 原版可引导镜像下载 本站下载的 macOS 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安装。另外也支持在 Windows 和 Lin…...

【机器学习】 奇异值分解 (SVD) 和主成分分析 (PCA)

一、说明 在机器学习 &#xff08;ML&#xff09; 中&#xff0c;一些最重要的线性代数概念是奇异值分解 &#xff08;SVD&#xff09; 和主成分分析 &#xff08;PCA&#xff09;。收集到所有原始数据后&#xff0c;我们如何发现结构&#xff1f;例如&#xff0c;通过过去 6 天…...

如何用logging记录python实验结果?

做python实验有时候需要打印很多信息在控制台(console&#xff09;&#xff0c;但是控制台的信息不方便回顾和保存&#xff0c;故而可以采用logging将信息存储起来。 先新建一个文件message.log代码如下&#xff1a; import logging logging.basicConfig(filename"messa…...

C语言假期作业 DAY 03

目录 题目 一、选择题 1、已知函数的原型是&#xff1a; int fun(char b[10], int *a); &#xff0c;设定义&#xff1a; char c[10];int d; &#xff0c;正确的调用语句是&#xff08; &#xff09; 2、请问下列表达式哪些会被编译器禁止【多选】&#xff08; &#xff09; 3、…...

使用serverless实现从oss下载文件并压缩

公司之前开发一个网盘系统, 可以上传文件, 打包压缩下载文件, 但是在处理大文件的时候, 服务器遇到了性能问题, 主要是这个项目是单机部署.......(离谱), 然后带宽只有100M, 现在用户比之前多很多, 然后所有人的压缩下载请求都给到这一台服务器了, 比如多个人下载的时候带宽问…...

从上到下打印二叉树

题目描述 从上到下打印出二叉树的每个节点&#xff0c;同一层的节点按照从左到右的顺序打印。 例如: 给定二叉树: [3,9,20,null,null,15,7], 返回&#xff1a; [3,9,20,15,7] 算法思想 建立一个vector数组ret用来当做返回的结果数组&#xff0c;建立一个队列用来接收二叉树…...

【推荐】排序模型的调优

【推荐】排序模型的调优 排序模型的选择 排序模型常见的训练方式 样本类别不均衡处理尝试 欠拟合 过拟合 其他问题 排序模型的选择 LR&#xff0c;GBDT&#xff0c;LRGBDT&#xff0c;FM/FFM&#xff0c; 深度模型&#xff08;wide & deep&#xff0c;DeepFM&#x…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈&#xff0c;并不断增加特征维度持续测试」的做法&#xff0c;体现了一种逐步建模与迭代验证的实验思路&#xff0c;在金融欺诈检测中非常有价值&#xff0c;本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...

在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南

在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...

动态规划-1035.不相交的线-力扣(LeetCode)

一、题目解析 光看题目要求和例图&#xff0c;感觉这题好麻烦&#xff0c;直线不能相交啊&#xff0c;每个数字只属于一条连线啊等等&#xff0c;但我们结合题目所给的信息和例图的内容&#xff0c;这不就是最长公共子序列吗&#xff1f;&#xff0c;我们把最长公共子序列连线起…...