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

缓存(2):数据一致性

概述

一致性就是数据保持一致,在分布式系统中,可以理解为多个节点中数据的值是一致的

  • 强一致性:这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么用户体验好,但实现起来往往对系统的性能影响大
  • 弱一致性:这种一致性级别约束了系统在写入成功后,不承诺立即可以读到写入的值也不承诺多久之后数据能够达到一致,但会尽可能地保证到某个时间级别(比如秒级别)后,数据能够达到一致状态
  • 最终一致性:最终一致性是弱一致性的一个特例,系统会保证在一定时间内,能够达到一个数据一致的状态。这里之所以将最终一致性单独提出来,是因为它是弱一致性中非常推崇的一种一致性模型,也是业界在大型分布式系统的数据一致性上比较推崇的模型

缓存可以提升性能、缓解数据库压力,但是使用缓存也会导致数据不一致性的问题。

三种经典的缓存模式

三种经典的缓存模式

  • Cache-Aside Pattern:旁路缓存模式
  • Read-Through/Write through:读写穿透
  • Write behind:异步缓存写入

Cache-Aside Pattern(旁路缓存模式)

Cache-Aside Pattern,即旁路缓存模式,它的提出是为了尽可能地解决缓存与数据库的数据不一致问题

读请求流程如下:

  • 读的时候,先读缓存,缓存命中的话,直接返回数据;
  • 缓存没有命中的话,就去读数据库从数据库取出数据,放入缓存后,同时返回响应
    在这里插入图片描述

写请求流程如下:

  • 更新的时候,先更新数据库,然后再删除缓存
    在这里插入图片描述

问题

为什么这是直接删除缓存?

如果是更新的话,会有下述几个缺点

  • 会出现数据不一致问题,假设:
    • 线程A先发起一个写操作,第一步先更新数据库;
    • 线程B再发起一个写操作,第二步更新了数据库
    • 由于网络等原因,线程B先更新了缓存, 线程A更新缓存
    • 这时候,缓存保存的是A的数据(老数据),数据库保存的是B的数据(新数据),数据不一致了,脏数据出现
    • 这时候,如果是删除缓存取代更新缓存则不会出现这个脏数据问题
  • 如果你写入的缓存值,是经过复杂计算才得到的话。 更新缓存频率高的话,就浪费性能
  • 写多读少的情况下,数据很多时候还没被读取到,又被更新了,这也浪费了性能

但是如果是更新缓存的话,在读多写少的场景,价值大

为什么先操作数据库后操作缓存

假设有A、B两个请求,请求A做更新操作,请求B做查询读取操作。

如果是先操作缓存的话,A、B两个请求的操作流程如下:

  1. 线程A发起一个写操作,第一步del cache
  2. 此时线程B发起一个读操作,cache miss
  3. 线程B继续读DB,读出来一个老数据
  4. 然后线程B把老数据设置入cache
  5. 线程A写入DB最新的数据

如果是先操作缓存的话便会出现:缓存保存的是老数据,数据库保存的是新数据

因此,Cache-Aside缓存模式,选择了先操作数据库而不是先操作缓存。

数据不一致情况

情况的核心是
线程1:DB写操作和删除缓存在事务中,删除缓存后,事务还未提交。
线程2:缓存已经删除,从DB读后,写入缓存。
由于线程1的事务未提交,线程2读取并放入缓存的的还是旧数据,导致数据最终不一致

但,这个case理论上会出现,不过,实际上出现的概率可能非常低,因为这个条件需要发生在读缓存时缓存失效,而且并发着有一个写操作

实际上数据库的写操作会比读操作慢得多,而且还要锁表,而读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存,所有的这些条件都具备的概率基本并不大
所以,要么通过2PC或是Paxos协议保证一致性要么就是拼命的降低并发时脏数据的概率
而Facebook使用了这个降低概率的玩法,因为2PC太慢,而Paxos太复杂

当然,最好还是为缓存设置上过期时间。

解决方案: 删除缓存,做2次删除

  1. 直接删除;
  2. 注册事务回调,事务结束(提交或回滚)后再次删除

Read-Through/Write through(读写穿透)

Read/Write Through模式中,服务端把缓存作为主要数据存储应用程序跟数据库缓存交互,都是通过抽象缓存层完成的

  • 可以理解为,应用认为后端就是一个单一的存储,而存储自己维护自己的Cache

Read-Through实际只是在Cache-Aside之上进行了一层封装,它会让程序代码变得更简洁,同时也减少数据源上的负载。
Read-Through读流程如下

  • 从缓存读取数据,读到直接返回
  • 如果读取不到的话,从数据库加载,写入缓存后,再返回响应

流程如下所示

相关文章:

缓存(2):数据一致性

概述 一致性就是数据保持一致,在分布式系统中,可以理解为多个节点中数据的值是一致的。 强一致性:这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么,用户体验好,但实现起来往往对系统的性能影响大弱一致性:这种一致性级别约束了系统在写入成功…...

什么是原码和补码

补码的本质确实是模运算(Modular Arithmetic),这是理解补码为何能统一加减法的核心数学原理。下面用最通俗的语言和例子解释清楚: —### 1. 先理解什么是“模运算”- 模运算就是“周期性计数”,比如钟表: -…...

ppy/osu构建

下载 .NET (Linux、macOS 和 Windows) | .NET dotnet还行 构建:f5 运行:dotnet run --project osu.Desktop -c Debug...

基于几何布朗运动的股价预测模型构建与分析

基于几何布朗运动的股价预测模型构建与分析 摘要 本文建立基于几何布朗运动的股价预测模型,结合极大似然估计与蒙特卡洛模拟,推导股价条件概率密度函数并构建动态预测区间。实证分析显示模型在标普500指数预测中取得89%的覆盖概率,波动率估…...

使用交互式半自动化标注工具制作语义分割数据集

参考的初始资源: GitHub项目文档 B站视频 1.安装工具 打开Anaconda Prompt 1.创建虚拟环境 conda create -n isat_env python3.8 conda activate isat_env2.安装GPU版本pytorch 4070 Ti CUDN12.5 pip install torch torchvision torchaudio --index-url https:/…...

deepseek梳理java高级开发工程师微服务面试题

Java微服务高级面试题与答案 一、微服务架构设计 1. 服务拆分原则 Q1:微服务拆分时有哪些核心原则?如何解决拆分后的分布式事务问题? 答案: 服务拆分五大原则: 1. 单一职责原则(SRP)- 每个…...

二分查找算法的思路

二分查找思路总结 明确目标与单调性特点: 核心目标:寻找满足某种条件的答案(如最小/最大值)。单调性要求:需要证明你的判断函数具有单调性——即如果某个答案 T 可行,那么大于 T 的答案通常也是可行的&…...

(1)python开发经验

文章目录 1 安装包格式说明2 PySide支持Windows7 更多精彩内容👉内容导航 👈👉Qt开发 👈👉python开发 👈 1 安装包格式说明 PySide下载地址 进入下载地址后有多种安装包,怎么选择: …...

DAY05:深入解析生命周期与钩子函数

引言 在 Vue 开发中,生命周期和钩子函数是理解组件行为的关键。无论是初始化数据、操作 DOM,还是清理资源,生命周期钩子都提供了精确的控制点。本文将从基础理论出发,结合项目实战,详细剖析 Vue 3 的生命周期机制、组…...

python如何提取Chrome中的保存的网站登录用户名密码?

很多浏览器都贴心地提供了保存用户密码功能,用户一旦开启,就不需要每次都输入用户名、密码,非常方便。作为python脚本,能否拿到用户提前保存在浏览器中的用户名密码,用以自动登录呢?必须有,小爬…...

Redis实现分布式获取全局唯一自增ID的案例。

【1】简易自增版本(从 1 开始 1,2,3,...) 项目结构 下面是一个基于 RedisTemplate 实现的分布式全局唯一自增 ID 生成器的案例。适用于 Java Spring Boot 环境,利用 Redis 的原子操作 INCR 指令。 ✅ 原理说明 Redis 提供的 INCR 命令是原子性的&…...

人脸识别备案:筑牢人脸信息 “安全墙”

人脸识别备案制度主要依据《人脸识别技术应用安全管理办法》建立,人脸识别技术广泛应用于安防、金融、门禁、交通等领域,带来便利高效的同时,人脸信息安全问题也引发担忧。为规范技术应用、保护个人信息权益,人脸识别备案制度应运…...

基于RT-Thread的STM32F4开发第三讲——DAC

文章目录 前言一、DAC是什么?二、RT-Thread工程创建三、DAC函数编写1.DAC.c2.DAC.h3.main.c 四、结果测试五、工程分享 前言 本章利用RT-Thread最新的驱动5.1.0开发DAC模块,使用的开发板是正点原子的STM32F4探索者。很多配置和上文重复,本文…...

UE5通过C++实现TcpSocket连接

在 Unreal Engine 5 的 C 项目中,实现一个具备消息监听、心跳检测和断线重连功能的 TCP 客户端,可以参考以下完整示例。 准备工作 1、模块依赖 在 YourModule.Build.cs 文件中,添加对 Sockets 和 Networking 模块的依赖: Publ…...

网络状态可以通过hutool.HttpStatus获取

网络状态可以通过hutool.HttpStatus获取 全部都是静态int类型...

Gemini 2.5 推动视频理解进入新时代

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...

谈谈各种IO模型

目前的IO模型有5种:BIO(阻塞IO)、NIO(非阻塞IO)、IO多路复用、信号驱动IO、异步IO(AIO) 了解这些模型之前,我们需要先知道IO模型中的几个概念:阻塞&非阻塞、同步&am…...

基于STM32、HAL库的ADAU1701JSTZ音频接口芯片驱动程序设计

一、简介: ADAU1701JSTZ 是 Analog Devices 公司推出的一款高性能、低功耗音频编解码器 (CODEC) 芯片。它专为便携式音频设备设计,集成了麦克风前置放大器、ADC、DAC、耳机放大器等功能模块,支持多种音频接口和采样率,非常适合与 STM32 微控制器配合使用。 主要特性: 24…...

Linux系统管理与编程20:Apache

兰生幽谷,不为莫服而不芳; 君子行义,不为莫知而止休。 做好网络和yum配置,用前面dns规划的www的IP进行。 #!/bin/bash #----------------------------------------------------------- # File Name: myWeb.sh # Version: 1.0 # …...

BFS算法篇——打开智慧之门,BFS算法在拓扑排序中的诗意探索(下)

文章目录 引言一、课程表1.1 题目链接:https://leetcode.cn/problems/course-schedule/description/1.2 题目分析:1.3 思路讲解:1.4 代码实现: 二、课程表||2.1 题目链接:https://leetcode.cn/problems/course-schedul…...

【入门】纸盒的最大体积是多少?

描述 在一张尺寸为 n * n 厘米的正方形硬纸板的四个角上,分别裁剪掉一个 m * m 厘米的小正方形,就可以做成一个无盖纸盒,请问这个无盖纸盒的最大体积是多少? 立方体的体积 v 底面积 * 高) 比如: n 5 &am…...

什么是Vim

Vim可是Linux中最强大、最受欢迎的文本编辑器之一,很多程序员、系统管理员都离不开它。要说清楚Vim的各种功能和用法,似乎有点长,但我会尽量用简单通俗的方式,把Vim的核心知识讲清楚,让你能一步一步开始使用它。 一、…...

QT5.14安装以及新建基础项目

进入qt中文网站:Qt | 软件开发全周期的各阶段工具 额,考虑新手可能还是找不到,我就分享一下我下载的的吧 通过网盘分享的文件:qt-opensource-windows-x86-5.14.2.exe 链接:https://pan.baidu.com/s/1yQTRp-b_ISje5B3UWb7Apw?pw…...

Java Spring MVC -01

SpringMVC 是一种基于 的实现 MVC 设计模式的请求驱动类型的轻量级 Web 框架,属于 Spring FrameWork 的后续产品,已经融合在 Spring Web Flow 中。 First:SpringMVC-01-SpringMVC 概述 SpringMVC 是 Spring 框架的一个模块,用于构建 Web 应…...

KV cache 缓存与量化:加速大型语言模型推理的关键技术

引言 在大型语言模型(LLM)的推理过程中,KV 缓存(Key-Value Cache) 是一项至关重要的优化技术。自回归生成(如逐 token 生成文本)的特性决定了模型需要反复利用历史token的注意力计算结果&#…...

视频编解码学习十一之视频原始数据

一、视频未编码前的原始数据是怎样的? 视频在未编码前的原始数据被称为 原始视频数据(Raw Video Data),主要是按照帧(Frame)来组织的图像序列。每一帧本质上就是一张图片,通常采用某种颜色格式…...

[Java实战]Spring Boot 3 整合 Apache Shiro(二十一)

[Java实战]Spring Boot 3 整合 Apache Shiro(二十一) 引言 在复杂的业务系统中,安全控制(认证、授权、加密)是核心需求。相比于 Spring Security 的重量级设计,Apache Shiro 凭借其简洁的 API 和灵活的扩…...

Cursor 编辑器 的 高级使用技巧与创意玩法

以下是针对 Cursor 编辑器 的 高级使用技巧与创意玩法 深度解析,涵盖代码生成优化、工作流定制、隐藏功能等层面,助你将 AI 辅助编程效率提升至新高度: 一、代码生成进阶技巧 1. 精准控制生成粒度 行级控制: 在代码行内用 // > 指定生成方向(替代模糊注释)def merge_…...

mysql性能提升方法大汇总

前言 最近在开发自己的小程序的时候,由于业务功能对系统性能的要求很高,系统性能损耗又主要在mysql上,而业务功能的数据表很多,单表数据量也很大,又涉及到很多场景的数据查询,所以我针对mysql调用做了优化…...

C++标准流详解:cin/cout的绑定机制与cerr/clog的缓冲差异

在C中,标准错误流(cerr)、标准日志流(clog)与标准输入输出流(cin/cout)的行为差异主要体现在缓冲机制和绑定关系上。以下是详细解释,并结合cin和cout的关联性进行对比分析&#xff1…...