【Redis知识点总结】(四)——如何保证缓存与数据库中的数据一致性

Redis知识点总结(四)——如何保证缓存与数据库中的数据一致性

  • 更新缓存
  • 删除缓存
    • 先删除缓存后更新数据库
    • 先更新数据库后删除缓存
  • 使用canal
  • 总结

面试会经常遇到这种问题:你们如何保证缓存与数据库中的数据一致性?或者是:你们如果保证缓存与数据库的双写一致性?

其实这种问题本身就很矛盾,使用缓存的目的,本身就是牺牲一定的强一致性,追求性能的提升,如果真有场景是要保证缓存和数据库一致的,就不适合用缓存。但是既然面试官问到了,我们还是要答一下。

在使用缓存的时候,如果发生更新数据库的操作,我们可以删除缓存,也可以更新缓存。

更新缓存

我认为更新缓存是不可取的,原因有二:

  1. 如果这个缓存是个冷门数据,后续都不会查询到,那么这个更新就是多余的,还会占用内存空间
  2. 缓存和数据库都要更新,还要保证一致性,那么只能用事务,这样性能就会下降,违背了使用缓存的初衷

在这里插入图片描述

但是有一种情况是可以使用更新缓存这种策略的,就是一致性要求不高但是更新的数据是一个热点数据,那我们可以在更新数据库后,马上更新缓存,这样就不会因为有缓存缺失而造成大量的请求打向数据库,也就是缓存击穿的问题。即使更新数据库成功了,但是缓存更新失败也没关系,因为前提是一致性要求不高。

在这里插入图片描述

但是面试官问的是缓存与数据库如果保证一致性,那就不符合一致性要求不高的前提,所以更新缓存这种策略就不用考虑了。

删除缓存

再来看下删除缓存这种策略,我们可以先删缓存在更新数据库,也可以先更新数据库再删除缓存。

先删除缓存后更新数据库

先删缓存后更新数据库这种方案,有两种失败的情况:

  1. 删缓存失败
  2. 删缓存成功,更新数据库失败

如果删除缓存失败,那么就返回更新失败,此时数据库与缓存还是一致的;如果删缓存成功,但是更新数据库失败,那么也返回更新失败,此时只是缓存中没数据,下次查询的时候发现缓存缺失,从数据库中查询加载到缓存中,缓存和数据库还是一致的。这样,看起来好像没什么问题。

在这里插入图片描述

但是这种做法有一个潜在的问题,当缓存的数据的并发访问量比较大的时候,有可能出现如下这种情况:

在这里插入图片描述

线程1发起了一个更新操作,而线程2发起了以查询操作,目标都是同一份数据。线程1首先删除了缓存,但是迟迟没有更新数据库成功,而此时线程2进来了,线程2查询缓存发现缓存缺失,于是查询数据库并加载到缓存,但由于线程1没来得及更新数据库,所以此时缓存中的数据是旧的。随后线程1才更新数据库成功,此时缓存与数据库的数据就不一致了。

解决这种问题的办法,就是使用延迟双删的机制:

在这里插入图片描述

线程1在更新数据库成功后,sleep一段时间,然后再次删除缓存,就能把线程2加载到缓存中的旧值给删掉。但是这个sleep的时间长度不好把握,如果时间短了,可能在线程2加载旧值到缓存前,线程1就醒来了,那么缓存中的旧值还是没删,如果时间长了,又会影响数据更新的性能,数据已经更新成功了,但更新结果迟迟未返回。因此,一般情况下这种延时双删的机制也很少使用,进而先删缓存的这种做法也很少使用。

先更新数据库后删除缓存

再来看看先更新数据库,后删除缓存的做法。

如果更新数据库成功,然后删除缓存成功,那么缓存和数据库是能保证一致性的,但是在更新数据库成功之后,在删除缓存之前,其他线程查询到的还是旧值。

在这里插入图片描述

但是缓存不一致只是在更新数据库成功后,删除缓存成功之前的这一段时间内,如果不是要求强一致性的场景,都是可以接受的。

再看一下更新数据库或删除缓存不成功的情况:先更新数据库,如果更新失败了,那么就返回更新失败,此时缓存与数据库中的数据还是一致的;如果更新数据库成功,但是删除缓存失败,那么缓存与数据库的值是不一致。

在这里插入图片描述

但是我们可以给缓存添加一个过期时间,时间到了也会自动删除,那么我们就容忍一段时间的不一致,这种做法适用于一致性要求不高,只需要保证最终一致性的场景。

在这里插入图片描述

但是如果一致性要求非常高,不能容忍这一段时间的数据不一致,那么我们可以把要删除的key添加到队列中,然后起一个线程异步监听该队列,不断重试删除缓存,直到成功为止。

在这里插入图片描述

这种做法虽然还是没有保证绝对的一致性,但是容忍的不一致性时间更短了,更适合一致性要求较高的场景,但是引入了异步线程和队列,复制度就提升了。

如果再变态一点的,就是要保证绝对的一致,不能容忍一点点的不一致,并且连更新数据库成功后删除缓存成功之前的这一段时间的不一致也不能容忍,那么只能通过事务去保证。

在这里插入图片描述

但是这样一来,性能就会急剧下降,违背了使用缓存的初衷。

使用canal

还有一种保证缓存与数据库一致性的方案就是使用canal。

canal是基于MySQL的binlog日志进行数据同步的一个工具,它伪装成MySQL主从同步中的一个Slave节点,向MySQL主节点发起binlog同步的请求,接收到binlog后,canal就可以把接收到的binlog进行解析与处理,然后把数据同步到下游。

我们配置canal监听MySQL的binlog,然后同步数据到redis,这样就可以实现缓存与数据库的一致性。

在这里插入图片描述

当然,这种方案也不是强一致的,因为从数据库写成功,dump出binlog,到canal成功同步到redis,是存在一点点时差的。

总结

最后总结一下比较靠谱的几种做法。

如果是强一致性的场景,是不适合使用缓存的,那么最好就不要使用缓存了。如果遇到了即要求强一致性,又追求高性能的场景,那就太变态了。

如果是对一致性要求较高,但又不是强一致性,那可以使用canal同步的方案,正常情况下canal读取binlog同步数据到redis这个过程,处理是非常快的。

如果对一致性要求不高,可以采用先更新数据库,后删除缓存的机制,并且在查询数据库加载数据到缓存时,给缓存设置一个过期时间。这样,即使出现不一致,也只需容忍一段时间的不一致,等缓存过期时间到,缓存就会失效,可以到达最终一致性。

在这里插入图片描述

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

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

相关文章

*波动数列c++

题目 输入样例: 4 10 2 3输出样例: 2样例解释 两个满足条件的数列分别是2 4 1 3和7 4 1 -2。 思路 上来先理解题意,本题求的是“长度为n 总和为s的……数列的数目”。 假设第一项为x,增加 a 或者减少 b用di表示,…

【Spring Boot 源码学习】深入应用上下文初始化器实现

《Spring Boot 源码学习系列》 深入应用上下文初始化器实现 一、引言二、往期内容三、主要内容3.1 spring-boot 子模块中内置的实现类3.1.1 ConfigurationWarningsApplicationContextInitializer3.1.2 ContextIdApplicationContextInitializer3.1.3 DelegatingApplicationConte…

【智能算法】斑鬣狗优化算法(SHO)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过。 3.代码实现4.参考文献 1.背景 2017年,Dhiman等人受到斑鬣狗自然狩猎行为启发,提出了斑鬣狗优化算法(Spotted Hyena Optimizer, SHO)。 2.算法原理 2.1算法思想 SHO将斑鬣狗狩猎行为分为围捕-狩猎-进攻三…

Python入门(三)

序列 序列是有顺序的数据集合。序列包含的一个数据被称为元素,序列可以由一个或多个元素组成,也是可以没有任何元素的空序列。 序列的类型 元组(定值表):一旦建立,各个元素不可再更变,所以一…

Wireshark抓包工具的使用

提示:本文为学习记录,若有错误,请联系作者,谦虚受教 文章目录 前言一、下载二、首页三、使用1.读入数据2.分析数据3.筛选IP4.保存数据 四、过滤器表达式五、TCP总结 前言 低头做事,抬头看路。 一、下载 下载路径wire…

【论文笔记合集】LSTNet之循环跳跃连接

本文作者: slience_me LSTNet 循环跳跃连接 文章仅作为个人笔记 论文链接 文章原文 LSTNet [25] introduces convolutional neural networks (CNNs) with recurrent-skip connections to capture the short-term and long-term temporal patterns. LSTNet [25]引入…

【Java刷题篇】串联所有单词的子串

这里写目录标题 📃1.题目📜2.分析题目📜3.算法原理🧠4.思路叙述✍1.进窗口✍2.判断有效个数✍3.维护窗口✍4.出窗口 💥5.完整代码 📃1.题目 力扣链接: 串联所有单词的子串 📜2.分析题目 阅…

口腔管理平台 |基于springboot框架+ Mysql+Java+B/S结构的口腔管理平台 设计与实现(可运行源码+数据库+lw文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 前台功能效果图 管理员功能登录前台功能效果图 会员功能 系统功能设计 数据库E-R图设计 lunwen参考…

智慧公厕建设的主要目标是什么?

随着城市化进程的不断推进,公共厕所作为城市基础设施的重要组成部分,也变得越来越重要。为了提升公共厕所的管理水平、提供更好的服务质量,智慧公厕应运而生。智慧公厕的建设旨在通过信息化手段实现公共厕所的全面感知监测,实现公…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:FormLink)

提供静态卡片交互组件,用于静态卡片内部和提供方应用间的交互,当前支持router、message和call三种类型的事件。 说明: 该组件从API Version 10开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 该组件仅可…

6.【Linux】进程间通信(管道命名管道||简易进程池||简易客户端服务端通信)

介绍 进程间通信的方式 1.Linux原生支持的管道----匿名和命名管道 2.System V-----共享内存、消息队列、信号量 3.Posix------多线程、网路通信 进程间通信目的 数据传输:一个进程需要将它的数据发送给另一个进程 资源共享:多个进程之间共享同样的资源。…

【C++刷题】优选算法——动态规划第一辑

1.状态表示是什么?简答理解是dp表里的值所表示的含义怎么来的?题目要求经验题目要求分析问题的过程中,发现重复子问题 2.状态转移方程dp[i]......细节问题:3.初始化控制填表的时候不越界4.填表顺序控制在填写当前状态的时候&#…

腾讯云免费服务器配置大全和个人企业申请流程,2024年新版教程

腾讯云免费服务器申请入口 https://curl.qcloud.com/FJhqoVDP 免费服务器可选轻量应用服务器和云服务器CVM,轻量配置可选2核2G3M、2核8G7M和4核8G12M,CVM云服务器可选2核2G3M和2核4G3M配置,腾讯云服务器网txyfwq.com分享2024年最新腾讯云免费…

蓝桥杯每日一题——棋盘

问题描述 小蓝拥有 n xn 大小的棋盘,一开始棋盘上全都是白子。小蓝进行了 m 次操作,每次操作会将棋盘上某个范围内的所有棋子的颜色取反(也就是白色棋子变为黑色,黑色棋子变为白色)请输出所有操作做完后棋盘上每个棋子的颜色。输入格式 输入的…

卷积神经网络算法原理(卷积层,卷积运算,填充,步幅,经过卷积运算后的特征图大小,池化层,最大池化,平均池化,经过池化层运算后的特征图大小)

文章目录 卷积神经网络算法原理(卷积层,卷积运算,填充,步幅,经过卷积运算后的特征图大小,池化层,最大池化,平均池化,经过池化层运算后的特征图大小)前言1、图像的本质1.1、灰度图1.2…

Java学习笔记(16)

常见算法 查找算法 查询某个元素是否存在 二分查找(数组元素必须是有序的) package exercise;public class exercise1 {public static void main(String[] args) {int[] arr {7, 23, 797, 23, 79, 81, 103, 127, 131, 147};System.out.println(binar…

实战Python Socket编程:开发多用户聊天应用

实战Python Socket编程:开发多用户聊天应用 Python Socket 编程概述什么是Socket编程?Socket编程的应用场景Socket编程的重要性基本概念 环境准备Python版本必要的库开发环境配置调试工具 基本Socket编程创建Socket绑定Socket到端口监听连接接受连接发送…

24.第12届蓝桥杯省赛真题题解

A.空间&#xff08;100%&#xff09; 计算机存储单位计算 1TB2^10 GB 1GB2^10 MB 1MB2^10 KB 1KB2&10 B 1B8 bit(bit位二进制的最小的存储单位) #include <iostream> #include <cmath>using namespace std; //2^28B 2^2int main(){std::ios::sync_with_stdio…

【C语言入门】浮点型数据在内存中的存储

✨✨欢迎大家来到Celia的博客✨✨ &#x1f389;&#x1f389;创作不易&#xff0c;请点赞关注&#xff0c;多多支持哦&#x1f389;&#x1f389; 所属专栏&#xff1a;C语言 个人主页&#xff1a;Celias blog~ 目录 ​编辑 引言 引例 一、浮点型在内存中的存储方式 1.1 …

在idea中配置tomcat服务器,然后部署一个项日

1.下载tomcat Tomcat下载 点击右边的tomcat8 找到zip点击下载 下载完&#xff0c;解压到你想放置的路径下 2.配置环境变量 打开设置找到高级系统设置点击环境变量 点击新建&#xff0c;变量名输入&#xff1a;CATALINA_HOME&#xff0c;变量值就是Tomcat的安装路径&#x…