聊聊缓存机制:双写兜兜转转,又回到了串行化

来源 | moon聊技术

责编 | 寇雪芹

头图 | 下载于ICphoto

什么是双写?这个很好理解,双写就是说,一份数据在数据库存一份,在缓存中也存一份,给缓存一个过期时间,当读不到缓存时从数据库读出来然后写入缓存。

为什么需要双写呢?

当请求量越来越大的时候,系统会慢慢出现瓶颈,由于数据库的链接是有限的,无法支撑较高的QPS,所以我们要想一个办法分担数据库的压力,于是就有了双写,将数据写入缓存,客户端读取数据直接从缓存中读取,这样就可以提高系统的性能。

但是如果要使用双写,那么不管是先更新缓存还是先更新mysql,总会有时间间隔,那么就要保证你的业务在一定程度上允许短暂的数据不一致的情况出现,否则,还是不建议使用的。

那么就有人问了?双写一定不能保证强一致性吗?

答案是可以,只要把所有与其相关的读写请求用队列串行化,这样就可以保证双写的强一致性了,但是这样会极大的降低系统的QPS,非常不推荐这种做法。

既然要双写,那么肯定会出现数据库和缓存数据不一致的情况,要怎样去避免呢?

双写不一致问题要怎么解决?

一.先更新数据库,再更新缓存

这种情况会有什么问题呢?我们看下图:


首先a先更新数据库,按照正常流程来走,紧接着要a线程删除缓存,可是突然后面来了个b线程,并且a线程因为各种业务原因卡住了,导致b线程先完成了,之后a线程才更新缓存。这时突然有其他线程进来读数据,就会读到a的数据,但是按照业务流程来走,应该读到b的数据,此时,就出现了数据错乱的问题。

  • 1.线程a更新数据库

  • 2.线程b更新数据库

  • 3.线程b更新缓存

  • 4.线程a更新缓存

  • 5.其他线程读数据(读错了)

到这里我们会发现,直接更新缓存是有很大的问题的,而且很多时候,在复杂点的缓存场景,缓存不单单是数据库中直接取出来的值,有可能是联合其他的很多数据结合计算出来的一个值。

而且可能会有一种场景,我们经常在更新数据库后直接更新缓存,但是在此之间并没有缓存被访问的需求,这样我们就做了很多无用功,付出了很多代价。

大家应该对单例模式有所了解,其中有一种懒加载的思想,就是说,在你需要的时候再去加载,用在双写的情况下非常合适,也就有了下面这种先更新数据库,再删除缓存的模式。

二.先更新数据库,再删除缓存

这种情况又会有什么问题呢?

当然,这还是一种有问题的方案,我们来跟着图盘一盘。

  • 1:线程a更新数据库

  • 2:程序挂了,没来的及删除缓存

  • 3.其他线程来读数据(全都是错的)

这种方案的问题一目了然,只要程序挂了,就会出现数据读错的情况,真实的业务你是应该读到a线程的值,却一直在读之前的值。

那这种方案有没有优化呢?


当然也有了,其实我们可以每次写入都记录日志,然后修改结束后也记录日志,通过日志状态来判断是否写入成功,

  • 如果没有写入成功后续并且没有新的写入请求,就补写,

  • 否则不做处理。

但是这种情况也会出现不一致的问题,就是如果写数据库程序断了,到下次恢复数据之前这段时间,还会出现数据不一致的情况。

并且如果是频繁写入的情况,很有可能日志机制没有发挥作用,就有新数据写入覆盖,并且日志系统还要占用额外的资源。

我懂了!应该先删除缓存再更新数据库,这样就可以了!

三.先删除缓存 再更新数据库

来来来,继续贴图,是不是很熟悉?

这种方案会有问题吗??当然有,继续盘道:

  • 1:线程a删除缓存

  • 2:线程b删除缓存

  • 3:线程a卡了

  • 4:线程b更新数据库

  • 5:线程a更新数据

  • 6:其他线程读数据,读到了a的(又错了)

完了,这种情况居然也有问题,线程a到底行不行,每次都是你出事。这种情况中间会有一段数据乱掉,但是随着下次的更新数据还是会恢复正确。难道终极方案是先删除缓存,再更新数据库,再更新缓存??

四.先删除缓存,再更新数据库,再删除缓存

继续贴图

  • 1.线程a删除缓存

  • 2.其他线程读取数据,读到的是a之前的数据

  • 3.线程a更新数据库

  • 4.线程a删除缓存

  • 5.其他线程设置缓存数据,是a之前的数据(此时应该是a的)

大家是不是又发现了,这种设计方案还是会有问题的,直到下次数据更新才有可能将数据恢复正确。来吧,最后一种大家经常讨论的延时双删方案,我们一起盘一盘。

五.延时双删

go on

  • 1.先删除缓存

  • 2.再写数据库

  • 3.休眠一段时间(根据具体的业务时间来定)

  • 4.再次删除缓存

这里加了一个延时的操作,目的是确保 修改数据库 -> 清空缓存前,其他事务的更改缓存操作已经执行完。所有的写操作以数据库为准,只要到达缓存过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存。

但这其中难免还是会大量的查询到旧缓存数据的,因为延时时间是根据业务自己定义的,时间太长和太短在高并发情况下都会有查询到脏数据的情况产生。这样最差的情况就是在超时时间内数据存在不一致。

结语


到这里大家应该会发现,除了串行化这种方式以外,其他无论哪种方式大大小小都会有数据不一致的现象发生,有时为了维护数据一致性问题还要做很多额外很重的操作,比如加一些日志来做状态处理双写问题,具体的方案选择还是要根据业务的敏感度来定的。

60+专家,13个技术领域,CSDN 《IT 人才成长路线图》重磅来袭!

直接扫码或微信搜索「CSDN」公众号,后台回复关键词「路线图」,即可获取完整路线图!

更多精彩推荐
☞5G、射频、奥特曼,这仨有联系吗?☞再见 Nacos,我要玩 Service Mesh 了!☞用根因定位法,让运维效率再高一点!
点分享点收藏点点赞点在看

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

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

相关文章

如何基于大数据及AI平台实现业务系统实时化?

简介: 后疫情时代的新社会模式及经济形态必将催生出新的商业模式,在线业务及相关应用场景的流量呈现井喷式发展,常规的离线系统及离线机器学习平台已无法满足业务发展要求。 作者:高旸(吾与),阿…

基于 Flink 的典型 ETL 场景实现

简介: 本文将从数仓诞生的背景、数仓架构、离线与实时数仓的对比着手,综述数仓发展演进,然后分享基于 Flink 实现典型 ETL 场景的几个方案。 作者:买蓉 美团点评高级技术专家整理:赵阳(Flink 社区志愿者&…

商用密码技术与应用创新的方向是什么?安全牛发布《商密报告》全面揭晓

编辑 | 宋慧 出品 | CSDN云计算 头图 | 付费下载于东方IC 2021年4月22日,由安全牛举办的2021商用密码技术创新研讨会暨《2021商用密码创新应用指南》(以下简称《商密报告》)发布会在北京举行。 北京谷安天下科技有限公司副总裁贺晓辉在研讨…

Flink 源码 | 自定义 Format 消费 Maxwell CDC 数据

Flink 1.11 最重要的 Feature —— Hive Streaming 之前已经和大家分享过了,今天就和大家来聊一聊另一个特别重要的功能 —— CDC。 CDC概述 何为CDC?Change Data Capture,将数据库中的’增’、’改’、’删’操作记录下来。在很早之前是通…

阿里巴巴大数据实践:大数据建设方法论OneData

来源:数智化转型俱乐部 面对爆炸式增长的数据,如何建设高效的数据模型和体系,对这些数据进行有序和有结构地分类组织和存储,避免重复建设和数据不一致性,保证数据的规范性,一直是大数据系统建设不断追求的…

干货!一文搞懂无状态服务

来源 | 机智的程序员小熊责编 | 寇雪芹头图 | 下载于视觉中国事故的发生是量的积累的结果,任何事情都没有表面看起来那么简单,在软件运行的过程中,随着用户量的增加,不考虑高可用,迟早有一天会发生故障,不得…

后疫情时代,这家在线教育机构如何乘“云”而上

简介: 阿里云依托于云计算的基础设施特性,能够帮助教育机构避免业务侧重复投入、提高资源利用率、降低开发和运维成本,使洋葱学院激发出更大的活力,在后疫情时代得到更多用户的青睐 新冠疫情让现代人类和国际社会经历了大规模的隔…

2021全球权威AI性能竞赛MLPerf最新榜单: 浪潮获18项冠军几近半壁江山

4月22日,全球权威AI基准评测MLPerf公布2021年最新榜单,在全部有效41个项目中,浪潮获得18项性能第一,斩获几近半数冠军。 MLPerf™由图灵奖得主大卫•帕特森 (David Patterson)联合谷歌、斯坦福、哈佛大学…

NFS文件锁一致性设计原理解析

简介: 在存储系统中, NFS(Network File System,即网络文件系统)是一个重要的概念,已成为兼容POSIX语义的分布式文件系统的基础。它允许在多个主机之间共享公共文件系统,并提供数据共享的优势&am…

作为工程师,你真的了解无服务器?

译者 | 王欢来源 | 分布式实验室头图 | 下载于ICphoto最近,我在YouTube上看了一个非常出色的开发人员的视频。它的标题是“无服务器毫无意义”。虽然我非常喜欢该视频,但也不敢确定作者关于无服务器的观点是否完全正确,因此我想在本文中进行讨…

recaf反编译 java jar包

文章目录1. 获取方式2. 软件运行3. 导入jar4. 模式切换5. 字符串混淆解析1. 获取方式 添加QQ群获取197453088 2. 软件运行 java -jar recaf-2.21.13.jar3. 导入jar 4. 模式切换 5. 字符串混淆解析 如何解密Allatori 混淆的字符串 Java ALLATORIxDEMO

分布式锁在存储系统中的技术实践

简介: 阿里云存储提供了完整的分布式锁解决方案,经过了阿里云众多云产品宝贵的业务场景中长期锤炼,稳定高可靠,且提供了多种语言的SDK选择,甚至是RESTful集成方案。 1 背景 针对共享资源的互斥访问历来是很多业务系统…

Spring Cloud 应用在 Kubernetes 上的最佳实践 — 高可用(混沌工程)

简介: 从上篇开始,我们进入到了高可用的章节,上篇提到的熔断能力,是历年保障大促当天晚上整个系统不被洪峰流量打垮的法宝,本篇介绍的措施与熔断有不一样的地方? 前言 从上篇开始,我们进入到了…

闲鱼对Flutter-Native混合工程解耦的探索

简介: 分手快乐,祝你快乐~ 作者:祈晴 1. 闲鱼Flutter现状 闲鱼是第一个使用Flutter混合开发的大型应用,但闲鱼客户端开发最深入体会的痛点就是编译时长影响开发体验。在FlutterNative这种开发模式下,Nat…

学 Python 最大的 1 个误区,看看你中招了吗?

提起 Python,大家总觉得很简单。但是,能把 Python 用好的人,好像并没多少。随着 Python 火了之后,像“ 3 天带你学会 Python ”、“快速入门到全栈”这样的教程层出不穷。很多讲了一点基础语法后,还没讲 http 协议和异…

Unable to make public jdk.internal.loader.Resource jdk.internal.loader.URLClassPath.getResource(jav

文章目录1. 现象2. 异常截图2. 解决方案3. 执行命令4. 启动日志5. 浏览器效果图1. 现象 执行命令 xjar.exe java -jar unified-access-center-passwd.jar运行 sprinbgboot 打包的jar包报错 具体信息如下: C:\Users\gblfy\Desktop\xJarDir>xjar.exe java -jar…

win10安装go开发环境

文章目录1. 下载软件2. 安装3. 验证1. 下载软件 golang官网:https://golang.google.cn/dl/ 2. 安装 双击go1.19.1.windows-amd64.msi一路下一步 3. 验证 go version

3 张图带你走近蚂蚁mPaaS音视频通话组件

简介: 远程问诊、线上开户、车载语音通话……蚂蚁 mPaaS 正在“拥抱新技术,探索新未来”。 音视频技术的进步,让线上办公不再是一时权宜之计,也使得线上业务的“无接触”开展成为可能。近日,蚂蚁集团推出的移动开发平台…

立即生效!帕特·基辛格卸任 VMware 所有职务

整理 | 苏宓出品 | CSDN(ID:CSDNnews)心无二用,在帕特基辛格(Pat Gelsinger)成为英特尔新任 CEO 两个月后,他宣布辞去此前的 VMware 首席执行官的职务,全身心地帮助英特尔重建往日的…

云原生应用实现规范 - 初识 Operator

简介: 本文我们将首先了解到 Operator 是什么,之后逐步了解到 Operator 的生态建设,Operator 的关键组件及其基本的工作原理,下面让我们来一探究竟吧。 作者 | 匡大虎、阚俊宝 基于 Kubernetes 平台,我们可以轻松的…