高并发下数据一致性问题:数据库+缓存双写模式分析

news2024/11/16 1:29:11

前言

随着互联网业务的发展,其中越来越多场景使用了缓存来提升服务质量。从系统角度而言,缓存的主要目标是减轻数据库压力(特别是读取压力)并提高服务响应速度。引入缓存就不可避免会涉及到缓存与业务数据库数据一致性的问题,而不同的业务场景对数据一致性的要求也有所不同。本文将针对常见的数据库+缓存双写模式进行数据一致性分析。

数据库+缓存双写

数据库+缓存双写模式是一种常见的数据处理模式,它结合了数据库和缓存的优势。所以,说白了,数据库+缓存双写就是值,在数据处理过程下,写操作会同时更新数据库和缓存

当数据需要被写入时,首先会将更新操作应用于数据库,确保数据的持久性和一致性。接下来,更新的数据也会被写入缓存,以提高后续读取请求的响应速度。

这种双写模式确保了数据的可靠性和一致性(其实在高并发情况下,并会有数据不一致的情况,后面将详细分析)。读取数据时,系统首先检查缓存,如果缓存中存在所需数据,则直接从缓存中获取,减轻了对数据库的负载。如果缓存中不存在所需数据,系统会从数据库中获取,并将获取到的数据写入缓存,以便将来的读取请求能够从缓存中获得更快的响应。

通过使用数据库+缓存双写模式,系统能够在保持数据一致性的同时,提高读取请求的效率和响应速度。然而,这种模式也增加了系统复杂性,因为需要确保数据库和缓存之间的数据一致性,并处理双写可能带来的同步和并发问题。

更新缓存还是删除缓存?

答案是:删除缓存
原因如下:

  1. 在实际业务中,缓存的数据可能不是直接来自数据库表,也许来自多张底层数据表的聚合。比如上面提到的商品详情信息,在底层可能会关联商品表、价格表、库存表等,如果更新了一个价格字段,那么就要更新整个数据库,还要关联的去查询和汇总各个周边业务系统的数据,这个操作会非常耗时。
  2. 从另外一个角度,不是所有的缓存数据都是频繁访问的,更新后的缓存可能会长时间不被访问(利用大量计算和时间去做更新,最后却没有被访问,不一定有价值),所以说,从计算资源和整体性能的考虑,更新的时候删除缓存,等到下次查询命中再填充缓存,是一个更好的方案。
  3. 系统设计中有一个思想叫 Lazy Loading,适用于那些加载代价大的操作,删除缓存而不是更新缓存,就是懒加载思想的一个应用。

参考:40 经典问题:先更新数据库,还是先更新缓存?

缓存更新(删除)策略

情况1:先删除缓存,后更新数据库 —— 更大概率出现数据不一致

举个例子:
线程1 刚刚 删除了 k = 1的缓存,并且打算去数据库更新k 1 -> 2(注意:数据库更新是一个慢操作);在这个时候,线程2 发现 缓存中 k 不存在,那么线程2 就去数据库中查k,由于线程1更新操作很慢,因此在线程2查询k的时候 线程1并未完成对 k = 2的更新,此时线程2就读到了旧数据k=1,并且线程1还要去更新缓存k = 1(这个过程很快)。过了一会儿,线程1才完成数据库更新k=2,然而此时缓存中k=1,所以数据不一致发生了。

结合下面的图来看(蓝色的条表示操作需要的时间,虚线代表此时DB和Cache的情况)
在这里插入图片描述

可以发现,在更新DB k = 2的时候,存在很长时间的空窗让其他线程读到旧的数据并且更新旧的数据到缓存,因此这种情况,有很大概率出现数据不一致。

情况2 : 先更新数据库,再删除缓存——减少不一致的发生时间

情况A:读缓在更新完数据库且删缓存之前读到的

线程1查不到缓存,就查数据库k = 2,并且将缓存写入 k = 2,但是此时线程2更新数据库 k = 1,并且删除缓存(还没完成),而假设此时有第三个线程3是在线程2更新数据库完成但删除缓存未完成读到了缓存 k = 2,此时数据就不一致了。但是,由于缓存删除其实很快,这种情况很少。
在这里插入图片描述

情况B:写缓存是在删缓存之后造成的不一致

线程1查缓存不存在,所以去查DB 得到 k =1 ,然后打算写缓存 k = 1(但是还没完成),此时,线程2更新完数据库 k = 2,打算删除缓存,然而此时线程1完成写缓存k = 1,此时数据不一致了。

解决方案 —— 延迟双删策略

针对这种情况,采用延迟双删策略
刚才的情况是因为写缓存是在删缓存之后造成的不一致,所以我们可以在删缓存之后设置一个定时任务或者延时队列MQ,比如在发送删除缓存命令延迟1秒(由业务决定)之后才真正执行,让写缓存先完成。

异步串行化:解决“先删缓存,后更新DB”情况下的数据不一致问题。

参考:高并发场景下的缓存 + 数据库双写不一致问题分析与解决方案设计

刚才的情况是,还没更新数据库的就查数据库读到旧数据吗?不就是因为读在更新前面了吗?那我就让你排队执行呗。

我们考虑在系统内部维护n个内存队列,更新数据的时候,根据数据的唯一标识,将该操作路由之后,发送到其中一个jvm内部的内存队列中(对同一数据的请求发送到同一个队列)。读取数据的时候,如果发现数据不在缓存中,并且此时队列里有更新库存的操作,那么将重新读取数据+更新缓存的操作,根据唯一标识路由之后,也将发送到同一个jvm内部的内存队列中。然后每个队列对应一个工作线程,每个工作线程串行地拿到对应的操作,然后一条一条的执行。

这样的话,一个数据变更的操作,先执行删除缓存,然后再去更新数据库,但是还没完成更新的时候,如果此时一个读请求过来,读到了空的缓存,那么可以先将缓存更新的请求发送到队列中,此时会在队列中积压,排在刚才更新库的操作之后,然后同步等待缓存更新完成,再读库。

参考:干货 | 携程最终一致和强一致性缓存实践

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

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

相关文章

充电桩计量检测TK4860E交流充电桩检定装置

固定检定点:系统预设24A220V和12A220V的检定点,可完成单相32A或单相16A充电桩的工作误差的检定,24A和12A检定点的设计既可满足实际输出达不到额定电流的单相充电桩的检定,又可保证检定效率。 固定电量:系统可预设充电…

源代码安全管理

现在,随着软件开发公司对源代码保护的日益重视,源代码已成为企业核心竞争力的关键因素之一。为了确保企业在同行中展露头角并具备核心竞争力,源码的保护变得至关重要。 目前,源代码加密有两种常用方式:物理性和软件性…

leetcode 139.单词拆分

题目描述 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。 注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。 来源:力扣(LeetCode) 链…

ASEMI代理NXP快恢复功率二极管BYC30W-600P参数

编辑-Z BYC30W-600P参数描述: 型号:BYC30W-600P 重复峰值反向电压VRRM:600V 峰值工状向电压VRWM:600V 反向电压VR:600V 平均正向电流IF:30A 正向电压VF:1.38V 反向恢复时间trr&#xff…

iptables trace使用

iptables规则链流向: modprobe ipt_LOG ip6t_LOG nfnetlink_log加载内核模块 写入iptables规则,-A XXX -j TRACE iptables --version查看iptables版本,nf_tables则使用xtables-monitor --trace监听iptables规则流动。legacy则使用/var/log…

也谈现在网站行业是否还有必要做下去?

我是卢松松,点点上面的头像,欢迎关注我哦! 想就这个话题唠叨几句的起因,是前几天拜读了卢松松发表的一篇题为**《为什么说网站行业不能做了?》**的文章。文章内容是卢松松对网站行业的现状随意的吐槽,没想到有位网友…

第十五个“世界海洋日”:水声功率放大器能为海洋水下声呐研究做些什么?

2023年6月8日,第十五个“世界海洋日”到来,今年的海洋日我们除了要聚焦海洋生态保护和海洋资源的可持续发展及利用,我们同样把视线聚焦在海洋科学研究上,海洋水下声呐技术,就是我们本次的主题。 作为能良好驱动声呐&am…

线性回归算法(含示例代码)

1 知识点讲解 1.1 线性回归 线性回归是一种常见的机器学习算法,用于预测连续型变量。该算法的目标是建立一个线性模型,根据输入的自变量来预测一个连续型的因变量。 在线性回归中,我们假设因变量(也称为响应变量)与…

近80%企业首选——亚马逊云科技为中国企业出海保驾护航

随着全球数字化进程的不断加速,中国出海“大航海时代”已然到来。从#万企组团出国抢订单#到#苏州赴日包机抢单20亿元#,中国企业对海外市场的优势已经一步步建立了起来。 从卖小商品、卖鞋的“世界工厂”,到现在产业升级后的卖汽车、卖服务、…

抖音seo矩阵系统源码|需求文档编译说明(一)

抖音seo矩阵系统文章目录技术囊括 ①产品原型 ②需求文档 ③产品流程图 ④部署方式说明 ⑤完整源码 ⑥源码编译方式说明 ⑦三方框架和SDK使用情况说明和代码位置 ⑧平台操作文档 ⑨程序架构文档 短视频矩阵系统源码开发锦囊囊括前言一、短视频账号矩阵系统开发者必备能力语言&…

招标投标管理微信小程序解决方案

招投标管理微信小程序是一种基于微信公众平台构建的在线招投标管理平台,适用于各类招投标项目管理,通过小程序内的功能实现投标、查看、评估和管理等各项业务。下面我们来了解一下招投标管理微信小程序的具体功能和应用情况。 招投标管理微信小程序的功能…

App 启动速度优化

前言​​​​​​​ APP打开的一瞬间速度快慢;就好比人的第一印象,快速的打开一个应用往往给人很舒服的体验。app经常性卡顿启动速度很慢,这无疑是对用户的流失。 启动方式介绍 APP启动的方式分为3种:冷启动、热启动、温启动。…

28.vite

目录 1 一些概念 1.1 单页面应用程序SPA 1.2 vite 2 初始化vite项目 3 项目中的文件 1 一些概念 1.1 单页面应用程序SPA 单页面应用程序是只有一个页面的前端,切换页面通过前端路由来切换 特点如下 实现了前后端分离,后端仅出接口&#…

Flink TableAPI window and watermarket

序言 本次主要是弄清楚.批流统一 的处理方式,因为它是使用SQL来操作批流计算的.所以它怎么设置算子并行度?如何设置窗口?如何处理流式数据?等等 有很多疑问. 我还是觉得直接使用流计算的API更好.流批一体API最终也是转换成流式计算,最主要的是使用sql来设置算子或者窗口,并…

python合并多个excel,每个excel中有相同的列,按指定列名将数据列合并到一起。以统计学生多个作业提交情况为例。

一、实现目标 有多个excel文件,每个excel文件是一次学生作业的提交情况,最终统计出所有学生所有作业的提交情况。具体格式和内容如下: excel1.xlsx excel2.xlsx excel3.xlsx: 最后统计出所有学生提交的所有作业的情况: 二、实现思路

C# 自动备份文件

目录 文件目录如下 APBackUpFiles app.config OracleHelper LocalFileMethods LogFile packages.config ReadFile 如何发布 在工作的时候,遇到了需要定时对服务器的文件进行备份的需求,原因是 AP(服务器)上的空间不够了&a…

遗传算法解决TSP旅行商问题(numpy、pandas)

努力是为了不平庸~ 学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。 目录 一、引言 原理: 问题: 二、思路步骤 三、代码编写步骤 A、代码各步骤的方法、目的及意义 1. 导入所需的库&…

测试人,你凭什么脱颖而出?

我们在软件测试面试时,可能经常会碰到HR这样问“与其他竞争者相比,你认为自己的优势在哪里?” 看似简单,但仔细深思可能心理陡然冰冰凉,因为自己难以有信心比他人突出(除了腰间盘),看…

DBA 抓包神器 tshark 测评

想窥探神秘的网络世界的奥秘,tshark 助你一臂之力! 作者:赵黎明 爱可生 MySQL DBA 团队成员,熟悉 Oracle、MySQL 等数据库,擅长数据库性能问题诊断、事务与锁问题的分析等,负责处理客户 MySQL 及我司自研 D…

chatgpt赋能python:Python火了原因分析

Python火了原因分析 Python语言是近年来最热门的编程语言之一,有很多原因可以解释它的成功。本文将介绍三个最重要的原因,以及如何利用这些原因来提高您的Python编程技能。 Python具有易学性和流行的库 Python的设计使它非常容易学习,尤其…