【高频】如何保证缓存和数据库一致

  1. 如何确保缓存和数据库的数据一致性?
  2. 怎样解决缓存与数据库之间的数据同步问题?
  3. 如何处理缓存数据和数据库数据不一致的情况?

回答:

一、什么是数据一致性

缓存与数据库的数据一致性指的是,缓存中存储的数据与数据库中存储的数据需保持一致。
即缓存中存有数据,缓存的数据值 = 数据库中的值;缓存中没有该数据,数据库中的值 = 最新值。数据一致性主要包含以下两种情况:

  • 缓存中有数据,那么缓存中的值需要和数据库中值相同。
  • 缓存中本身没有数据,那么,数据库中的值必须是最新值。

如果存在以下情况,则说明存在不一致性情况:

  • 缓存中有数据,但是缓存中的数据与数据库中的数据不一致。
  • 缓存或者数据库中存在旧的数据,导致单个线程读到的数据是旧的。

二、数据不一致的原因

缓存(Redis)和 数据库(MySQL)是两套系统,所以任何一方的数据改写,都需要另一方的协同来保证。但这种协同可能存在一定的失败率,如下:

  • 数据库更新出错:在更新数据库时发生错误,导致缓存中的数据与数据库中的数据不一致。
  • 缓存刷新机制错误:一些缓存系统可能存在刷新机制的问题,导致缓存中的数据没有及时更新,从而与数据库数据出现不一致的情况。
  • 并发请求:当有多个请求同时进行操作时,由于缓存、数据库操作的顺序和时机不同,可能造成不一致的情况。
  • 数据一致性策略不当:在实现缓存和数据库的数据一致性策略时,如果选择不当的数据一致性策略,可能会导致数据不一致的情况。

为了保持缓存和数据库的数据一致性,需要采取适当的一致性策略(如引入 2PC 或 Paxos 等分布式一致性协议,或者分布式锁),并及时处理数据库更新和缓存刷新中的错误。同时,在实现并发请求时,需要合理控制操作的顺序和时机,以避免不一致的情况发生。

三、缓存执行的策略

  • Cache-Aside(缓存旁路):这是最广泛使用的缓存策略之一。在读取数据时,先从缓存中读取数据,如果缓存中没有数据,则从数据库中读取数据,并将读取到的数据存储到缓存中。在写入数据时,先写入数据库,然后更新缓存中的数据。这个策略可以极大地提高读取性能,但是可能会降低写入性能。
  • Read-Through(读穿透):这个策略类似于Cache-Aside,但是它会自动从缓存中读取数据,而不需要先从数据库中读取数据。如果缓存中没有数据,则自动从数据库中读取数据,并将读取到的数据存储到缓存中。这个策略可以提高读取性能,但是可能会增加数据库的负载。
  • Write-Through(写贯穿):这个策略类似于Cache-Aside,但是在写入数据时,它会直接写入缓存和数据库,而不是先写入数据库再更新缓存。这个策略可以提高写入性能,但是可能会降低缓存的利用率。
  • Write-Behind(写后置):这个策略类似于Write-Through,但是在写入数据时,它会异步地更新缓存和数据库,而不是立即更新。这个策略可以提高写入性能,但是可能会增加数据库的负载和缓存的不一致性。
  • Update-In-Place(原地更新):这种策略在缓存中直接更新数据,而不是先删除旧数据再添加新数据。这样可以减少缓存的冲突,但是可能会增加缓存的大小和内存消耗。
  • Write-Back(回写):这种策略在写入数据时,先更新缓存,然后再异步地更新数据库。这样可以提高写入性能,但是可能会增加缓存的不一致性和数据库的负载。
  • Partitioning(分区):这种策略将缓存分成多个分区,不同的数据分区采用不同的缓存策略,以适应不同的访问模式和负载情况。

四、一致性解决方案

1.延迟双删策略主要是是应对先删除缓存,再更新数据库的场景。
我们知道在这种场景中,很容易因为删除数据库太慢导致重新获取的缓存依旧读是数据库旧值,读完旧值之后,数据库才更新完毕。这时候缓存的数据就跟数据库不一致了。参考 3.3 节。
所以这边多加了一个步骤,就是在数据库更新完成之后,再删除一次缓存。所以步骤如下:

  • 删除缓存
  • 缓存删除完成之后,更新数据库
  • 数据库更新完成之后,休眠 n ms,二次删除缓存

这时候唯一存在的一个问题就是,在(更新据库 + 休眠 n ms) 这个时间窗口中,依旧能读取到旧值,而这个短暂时间控制的好的话,是可以接受的。

2.无论是先更新数据库,再删除缓存;还是先删除缓存,在更新数据库。
保持事务性都是一种方案,如果删除缓存失败,则数据库更新会被回滚;如果更新数据库失败,则缓存也不会被删除。这个需要一致性策略接入。不过无论怎么做,这个都会在一定程度上影响执行完成的性能

3.如果双删还是失败呢,那可咋整,还是会产生缓存和数据库数据不一致的现象。
一般的做法是做一层兜底,比如记录日志,人工来处理;或者通过MQ来发布消息,然后开发一个独立的服务来订阅,专门用于数据清理,这就将操作异步化了

4.数据库有类似Binlog之类的东西,记录每次数据的更新。所以我们有另外一种方案,就是把同步缓存的操作交给独立的能力中,从应用层解耦。
图中我们可以看到步骤如下:

  • 更新数据库数据
  • 数据库更新完成之后会把变更记录在 binlog 中
  • 使用 canal 订阅 binlog 日志获取待删除的key(或者更完整的数据对象)
  • 消费者(缓存删除服务)获取到 canal 数据,获得待删除的key,并删除缓存

摘录自以下博文:

https://www.cnblogs.com/wzh2010/p/17205453.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/19340.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【前端】Vuex笔记(超详细!!)

最近花了两周时间,完完全全的跟着Vuex官方的视频学完了Vuex并且详详细细的做了笔记,其中总结部分是我对于整个视频课程的总结,视频部分是跟着视频做的笔记,如果总结部分有不懂的话,直接去视频部分查找对应的笔记即可&a…

ios:文本框默认的copy、past改成中文复制粘贴

问题 ios 开发&#xff0c;对于输入框的一些默认文案展示&#xff0c;如复制粘贴是英文的&#xff0c;那么如何改为中文的呢 解决 按照路径找到这个文件 ios/项目/Info.plist&#xff0c;增加 <key>CFBundleAllowMixedLocalizations</key> <true/> <…

Keras深度学习框架实战(1):图像分类识别

1、绪论 1.1 图像分类的定义 图像分类是计算机视觉领域中的一项基本任务&#xff0c;其定义是将输入图像分配给预定义类别中的一个或多个。具体来说&#xff0c;图像分类系统接受一个图像作为输入&#xff0c;并输出一个或多个类别标签&#xff0c;这些标签描述了图像中的内容…

第十三届蓝桥杯物联网试题(国赛)

还是那句话不能掉以轻心&#xff0c;全力以赴吧&#xff0c;遇事不要慌&#xff0c;该做的都做了&#xff0c;冷静沉稳的处理&#xff0c;看看配置&#xff0c;看看代码&#xff0c;还是不行就重启&#xff0c;都没问题换个板子 下面对比较复杂的部分的处理过程进行展现&#x…

Java-Collection家族(List接口)

集合-Collection家族-List接口 List接口 1 特点 ​ 有序且可重复&#xff08;因为List接口中添加了许多针对下标操作的方法&#xff09; 2 四种实现类的数据类型与特点 ​ a. ArrayList ​ 数据结构&#xff1a;一维数组 ​ 特点&#xff1a;存储数据 ​ b. LinkedList ​ 数…

科研作图学习(持续更新中...)

画神经网络图 https://alexlenail.me/NN-SVG/index.html 图标网站 https://www.freepik.com/ https://www.flaticon.com/icons 可用软件 Edraw PPT Visio 持续更新中…

git报错prohibited by Gerrit: not permitted: update

git push报错&#xff1a; Push to refs/for/[branch] to create a review, or get Push rights to update the branch. Contact an administrator to fix the permissions (prohibited by Gerrit: not permitted: update)原因&#xff1a; 使用Gerrit代码审核时&#xff0c;本…

ubuntu网络图标消失解决

ubuntu 18.04网络图标消失不见解决方法 解决方法&#xff1a; 依次输入以下指令&#xff08;前提已设置好桥接模式或NAT模式&#xff09;&#xff1a; 1.sudo service network-manager stop 2.sudo rm /var/lib/NetworkManager/NetworkManager.state 3.sudo service networ…

CentOS 7基础操作02_优化Linux操作系统中的服务

1、实验环境 公司在文件服务器中新安装了CentOS系统.由于默认启动的服务程序较多&#xff0c;系统运行缓慢。现需要对系绞服务进行适当优化&#xff0c;减少一些不必要的自启动服务.并设置系统在开机后直接进入字符模式。 2、需求描述 根据实际使用需求对CentOS 7操作系统中的…

postgressql——PGPROC XLOG(6)

PGPROC相关结构 在共享内存中,核心数据结构围绕PROC_HDR指向的两个list:PROC和XACT PRCO内存连续,维护链表结构方便申请释放,对应每个后台服务进程,PID为OS标识、PGPROCNO为内部标识 XACT内存连续,维护快照需要的xmin和xid,XACT从PROC拆出来是为了更高的cache line命中…

IBM开源Granite Code模型,多尺寸可选,支持多种代码任务,性能媲美 CodeLlama

前言 近年来&#xff0c;大型语言模型&#xff08;LLM&#xff09;在代码领域展现出惊人的潜力&#xff0c;为软件开发流程带来了革命性的改变。代码 LLM 不仅能够生成高质量代码&#xff0c;还能帮助程序员修复错误、解释代码、编写文档等等&#xff0c;极大地提高了软件开发…

WebRTC 在 iOS 端实现一对一通信

WebRTC 在 iOS 端实现一对一通信 WebRTC 在 iOS 端实现一对一通信申请权限引入 WebRTC 库构造 RTCPeerConnectionFactory创建音视频源视频采集本地视频预览建立信令系统创建 RCTPeerConnection远端视频渲染参考 WebRTC 在 iOS 端实现一对一通信 在 iOS 端&#xff0c;我们将按…

Python高级编程:并发编程与异步编程

Python高级编程:并发编程与异步编程 在前几篇文章中,我们介绍了Python的基础语法、面向对象编程、标准库以及第三方库的使用。在这篇文章中,我们将深入探讨Python中的并发编程和异步编程。这些技术对于提高程序性能和响应速度至关重要,特别是在处理I/O密集型任务时。通过本…

【kubernetes】探索k8s集群的存储卷、pvc和pv

目录 一、emptyDir存储卷 1.1 特点 1.2 用途 1.3部署 二、hostPath存储卷 2.1部署 2.1.1在 node01 节点上创建挂载目录 2.1.2在 node02 节点上创建挂载目录 2.1.3创建 Pod 资源 2.1.4访问测试 2.2 特点 2.3 用途 三、nfs共享存储卷 3.1特点 3.2用途 3.3部署 …

token 无感刷新

什么是 token 无感刷新&#xff1f;为什么需要 token 无感刷新&#xff1f;让我们想象一下有这么个场景&#xff1a;你登录一个系统成功后&#xff0c;玩了 10 分钟&#xff0c;发现登录失效了&#xff0c;又要你重新登录&#xff0c;然后又过 10 分钟&#xff0c;又失效了&…

Python Flask框架(五)数据库

数据库是大多数动态Web程序的基础设施&#xff0c;本章主要介绍如何给Flask程序添加数据库支持&#xff0c;具体来说就是在Python中使用DBMS来对数据库进行管理和操作。 使用ORM不光可以解决SQL注入的问题&#xff0c;而且它为不同的DBMS提供统一的Python接口库&#xff0c;使…

芝浦工业大学利用 NetApp 提供的多层 AI 驱动型安全解决方案抵御网络攻击

成效 10,000 名学生和教职工受到现代存储基础架构的保护NetApp AI 技术可自动检测异常并即时创建数据备份借助 NetApp 重复数据删除和数据压缩将数据缩减了 60% NETAPP 打造现代化的数据保护 众所周知&#xff0c;教育机构很难防范网络攻击。学生、员工和教职工都需要使用自己…

全面解析API网关:动态路由、协议转换及安全防护策略

1.API网关简介与架构演进 1.1. 什么是API网关 API 网关是一种服务器&#xff0c;是多个客户端应用程序至后端服务数据流的中间层。它作为单一的接入点&#xff0c;处理所有应用程序之间的请求通信。API 网关的主要功能包括请求路由、API 组合、策略执行和转换请求和响应。 1…

Web程序设计-实验05 DOM与BOM编程

题目 【实验主题】 影视网站后台影视记录管理页设计 【实验任务】 1、浏览并分析多个网站后台的列表页面、编辑页面&#xff08;详见参考资源&#xff0c;建议自行搜索更多后台页面&#xff09;的主要元素构成和版面设计&#xff0c;借鉴并构思预期效果。 2、新建 index.h…

正则匹配优化:匹配排除多个字符串的其他字符串

(^entity|^with|...)\w优化 (?!entity|with|has|index|associations|input)\w(?!): 匹配排除项 效果 继续优化 匹配会过滤掉带有关键字的字段&#xff0c;在过滤的时候是可以加上尾部结束匹配符的 效果&#xff1a;