【Redis笔记】缓存——缓存分类、更新策略、缓存穿透、缓存雪崩、缓存击穿

缓存

缓存(Cache),就是数据交换的缓冲区,俗称的缓存就是缓冲区内的数据,一般从数据库中获取,存储于高速存储媒介上。
缓存的本质就是用空间换时间,牺牲数据的实时性,以服务器内存中的数据暂时代替从数据库读取最新的数据,减少数据库IO,减轻服务器压力,减少网络延迟,加快页面打开速度。

缓存的优点及作用

降低后端负载,提高读写效率,降低响应时间。

缓存分类

浏览器缓存

主要是存在于浏览器端的缓存

应用层缓存

使用在代码层面的Map、List、Set等进行存储,实现对数据、页面、图片等资源的缓存

数据库缓存

早期的数据库,如Oracle、MySQL、SQL server等,数据都是存放在磁盘。虽然数据库层也有对应的缓存(例如,MySQL增改查数据都会先加载到数据库中的一片空间 buffer pool),但这种缓存一般针对的是查询内容,而且粒度太小,一般只有表中数据没有变更的时候,数据库对应的缓存才发挥作用。但这并不能减少业务系统对数据库产生的增、删、查、改的庞大IO压力。
redis、mamcached、mongodb是比较常见的缓存数据库,把经常需要从数据库查询的数据、或经常更新的数据放入到缓存中,这样下次查询时,直接从缓存直接返回,减轻数据库压力。但这些缓存数据库大多在系统关机后,数据就会丢失,所以大量的数据仍需存在早期的数据库中。

CPU缓存

当代计算机最大的问题是 cpu性能提升了,但内存读写速度没有跟上,所以为了适应当下的情况,增加了cpu的L1,L2,L3级的缓存,介于CPU和内存之间。

服务器缓存

包括代理服务器缓存和CDN缓存

代理服务器缓存:代理服务器是浏览器和源服务器之间的中间服务器,浏览器先向这个中间服务器发起Web请求,经过处理后(比如权限验证,缓存匹配等),再将请求转发到源服务器。
代理服务器缓存的运作原理跟浏览器的运作原理差不多,只是规模更大。可以把它理解为一个共享缓存,不只为一个用户服务,一般为大量用户提供服务,因此在减少响应时间和带宽使用方面很有效,同一个副本会被重用多次。
CDN缓存:也叫网关缓存、反向代理缓存。CDN缓存一般是由网站管理员自己部署,为了让他们的网站更容易扩展并获得更好的性能。
浏览器先向CDN网关发起Web请求,网关服务器后面对应着一台或多台负载均衡源服务器,会根据它们的负载请求,动态将请求转发到合适的源服务器上。
虽然这种架构负载均衡源服务器之间的缓存没法共享,但却拥有更好的处扩展性。从浏览器角度来看,整个CDN就是一个源服务器。

缓存思路

基于Redis的缓存

标准的操作方式就是查询数据库之前先查询缓存,如果缓存数据存在,则直接从缓存中返回,如果缓存数据不存在,再查询数据库,然后将数据存入redis。

更新策略

缓存更新是redis为了节约内存而设计出来的一个东西,主要是因为内存数据宝贵,当我们向redis插入太多数据,此时就可能会导致缓存中的数据过多,所以需要淘汰掉部分过期的数据。
另外缓存的数据源来自于数据库,而数据库的数据是会发生变化的,因此,如果当数据库中数据发生变化,而缓存却没有同步,此时就会有一致性问题存在

策略选择

低一致性要求——内存淘汰或过期淘汰
高一致性要求——主动更新为主、过期淘汰兜底

内存淘汰

redis自动进行,当redis内存达到咱们设定的max-memery的时候,会自动触发淘汰机制,淘汰掉一些不重要的数据(可以自己设置策略方式)

超时剔除

当我们给redis设置了过期时间ttl之后,redis会将超时的数据进行删除,方便咱们继续使用缓存

主动更新

我们可以手动调用方法把缓存删掉,通常用于解决缓存和数据库不一致问题

  1. Cache Aside Pattern 人工编码方式:缓存调用者在更新完数据库后再去更新缓存,也称之为双写方案。

  2. Read/Write Through Pattern : 由系统本身完成,数据库与缓存的问题交由系统本身去处理。

  3. Write Behind Caching Pattern :调用者只操作缓存,其他线程去异步处理数据库,实现最终一致。

Cache Aside

缓存调用者在更新数据库的同时,完成对缓存的更新

一致性良好、实现难度一般

删除/更新缓存

更新缓存:每次更新数据库都更新缓存,会产生无效更新,并且存在较大的线程安全问题。

如果是先更新数据库,再更新缓存。理论上这种方式比先更新数据库再删缓存有着更高的读性能,因为它事先准备好数据。但由于要更新数据库和缓存两块数据,所以它的写性能就比较低,而且关键在于它也会出现脏数据,如下图,两个并发更新操作,分别出现一前一后写数据库、一后一前写缓存,则最终缓存的数据是二者中前一次写入的数据,不是最新的。
如果是先更新缓存,再更新数据库。这种方案见Write Back策略。

删除缓存:更新数据库时让缓存失效,查询时再更新缓存。本质是延迟更新,没有无效更新,线程安全问题相对较低。

先操作数据库/先删除缓存

先操作数据库,再删除缓存:在满足事务原子性的情况下,安全问题概率较低.

写操作先更新数据库,更新成功后使缓存失效。读操作先读缓存,缓存中读到了则直接返回,缓存中读不到再读数据库,之后再将数据库数据加载到缓存中。不过这同样存在问题:查询操作未命中缓存,接着读数据库老数据之后、写缓存之前,此时另一个用户发起了更新操作更新了数据库并清了缓存,接着查询操作将数据库中老数据更新到缓存。这就导致缓存中数据变成脏数据,并且会一直脏下去直到缓存过期或发起新的更新操作。不过这个情况出现的情况比较低,其需要具备以下情况:

  1. 读操作读缓存失效
  2. 有个并发的写操作
  3. 写操作比读操作更快
  4. 读操作早于写操作进入数据库,晚于写操作更新缓存

实际上数据库的写操作会比读操作慢得多,而且还要锁表,而读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存,所有的这些条件都具备的概率基本并不大。并且即使出现这个问题还有一个缓存过期时间来自动兜底。

先删除缓存,再操作数据库:安全问题概率较低。

假设有两个并发操作,一个操作更新、另一个操作查询,更新操作删除缓存后还没来得及更新数据库,此时另一个用户发起了查询操作,它因没有命中缓存进而从数据库读,此时第一个操作还没到更新数据库的阶段,读取到的是老数据,接着写到缓存中,导致缓存中数据变成脏数据,并且会一直脏下去直到缓存过期或发起新的更新操作。

如何保证数据库与缓存操作原子性?

单体系统:利用事务机制 (比如方法体上添加注解 @Transactional)

分布式系统:利用分布式事务机制

Read/With Through

缓存与数据库集成为一个服务,服务保证两者的一致性,对外暴露API接口,调用者调用API,无需知道操作的是缓存还是数据库,不关心一致性

一致性良好、实现复杂、性能一般

Write Back

缓存调用者的CRUD都针对缓存完成,由独立的异步线程将缓存数据写入数据库,实现最终一致。

一致性差、性能良好、实现复杂

缓存穿透

缓存穿透 :缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。

常见的解决方案有两种:

  • 缓存空对象
    • 优点:实现简单,维护方便
    • 缺点:
      • 额外的内存消耗
      • 可能造成短期的不一致
  • 布隆过滤
    • 优点:内存占用较少,没有多余key
    • 缺点:
      • 实现复杂
      • 存在误判可能

缓存空对象

当我们客户端访问不存在的数据时,先请求redis,但是此时redis中没有数据,此时会访问到数据库,但是数据库中也没有数据,这个数据穿透了缓存,直击数据库,我们都知道数据库能够承载的并发不如redis这么高,如果大量的请求同时过来访问这种不存在的数据,这些请求就都会访问到数据库,简单的解决方案就是哪怕这个数据在数据库中也不存在,我们也把这个数据存入到redis中去,这样,下次用户过来访问这个不存在的数据,那么在redis中也能找到这个数据就不会进入到缓存了

布隆过滤

布隆过滤器其实采用的是哈希思想来解决这个问题,通过一个庞大的二进制数组,走哈希思想去判断当前这个要查询的这个数据是否存在,如果布隆过滤器判断存在,则放行,这个请求会去访问redis,哪怕此时redis中的数据过期了,但是数据库中一定存在这个数据,在数据库中查询出来这个数据后,再将其放入到redis中,假设布隆过滤器判断这个数据不存在,则直接返回。

这种方式优点在于节约内存空间,存在误判,误判原因在于:布隆过滤器走的是哈希思想,只要哈希思想,就可能存在哈希冲突。

缓存雪崩

缓存雪崩是指在同一时段大量的缓存失效或者Redis等缓存服务宕机,导致大量请求到达数据库,带来巨大压力。

解决方案:

  1. 给不同的Key的TTL添加随机值,避免了因为采用相同的过期时间导致的缓存雪崩
  2. 利用Redis集群提高服务的可用性,可以使用主从架构的集群提高服务的可用性,万一出现宕机可以使用从节点顶上,避免因为一台Redis缓存服务宕机影响整个业务,提高Redis的容灾性
  3. 给缓存业务添加降级限流策略,当redis发生故障的时候可以直接拒绝服务而不是继续访问数据库
  4. 给业务添加多级缓存,在浏览器、nginx、redis、jvm、数据库等一层层的添加缓存
  5. 使用熔断机制。当流量到达一定的阈值时,就直接返回“系统拥挤”之类的提示,防止过多的请求打在数据库上。至少能保证一部分用户是可以正常使用,其他用户多刷新几次也能得到结果。

缓存击穿

缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击。

常见的解决方案有两种:

  • 互斥锁
  • 逻辑过期

互斥锁

如果发生缓存击穿后,第一个请求查询数据库中该数据的时候,使用一个锁锁住,后续的所有请求在锁未放开之前访问这个数据就让它休眠一会重新查询缓存。缺点就是在第一个线程写缓存期间,其他访问该数据的线程拿不到锁就只能处于等待状态,影响查询的性能,因为此时会让查询的性能从并行变成了串行,我们可以采用tryLock方法 + double check来解决这样的问题。

优点:没有额外的内存消耗;保证了缓存数据库的一致性;实现比较简单
缺点:线程需要等待,性能受影响;可能有死锁风险。

逻辑过期

我们把过期时间设置在 redis的value中,注意:这个过期时间并不会直接作用于redis,而是我们后续通过逻辑去处理。
假设线程1去查询缓存,然后从value中判断出来当前的数据已经过期了,此时线程1去获得互斥锁,那么其他线程会进行阻塞,获得了锁的线程他会开启一个新开的线程2去进行 以前的重构数据的逻辑,直到新开的线程完成这个逻辑后,才释放锁, 而线程1直接进行返回,假设现在线程3过来访问,由于线程线程2持有着锁,所以线程3无法获得锁,线程3也直接返回过期的数据,只有等到新开的线程2把重建数据构建完后,其他线程才能返回更新的数据。

优点:线程无需等待
缺点:不能保证缓存数据库一致性;有额外的内存消耗;实现比较复杂。

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

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

相关文章

民事二审案件庭审应如何准备?

一、你要明确审理范围,固定上诉请求 首先,第二审人民法院围绕当事人的上诉请求进行审理。 其次,在第二审程序中,原审原告增加独立的诉讼请求或者原审被告提出反诉的,第二审人民法院可以根据当事人自愿的原则就新增加的…

技术革新与市场需求:探索亚信安慧AntDB的发展之路

在这个信息爆炸的时代,企业对数据处理的需求日益增长,而传统的数据库系统往往难以应对海量数据的存储和处理。亚信安慧AntDB的出现,为解决这一难题提供了有力的工具。它不仅具备高吞吐、高并发、高性能的特点,还拥有极佳的扩展性和…

HTML+JavaScript-05

DOM 什么是 DOM? DOM 是一项 W3C (World Wide Web Consortium) 标准。 DOM 定义了访问文档的标准: “W3C 文档对象模型(DOM)是中立于平台和语言的接口,它允许程序和脚本动态地访问、更新文档的内容、结构和样式。”…

AI绘画探索人工智能的未来

🌈个人主页: Aileen_0v0 🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​💫个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-8fL64RHWVzwpzR6m {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

SouthLeetCode-打卡24年01月第5周

SouthLeetCode-打卡24年01月第5周 // Date : 2024/01/39 ~ 2024/01/31 031.删除链表的倒数第 N 个结点 (1) 题目描述 031#LeetCode.19.#北岸计划2024/01/29 (2) 题解代码 Version1.0 class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {if(head …

【知识图谱--第一讲概论】

深度学习–连接主义 知识图谱–符号主义 表示 有属性图和RDF图两种 RDF由三元组表示:Subject - Predicate - Object 存储 图数据库 抽取 融合 推理 问答 图算法

Seata下载与配置、启动

目录 Seata下载Seata配置启动Seata Seata下载 首先,我们需要知道我们要使用哪个版本的seata,这就要查看spring-cloud-alibaba版本说明,找到我们对应的seata。 spring-cloud-alibaba版本说明: 地址链接 下面是部分版本说明: s…

【MyBatis】MyBatis是什么?作用?怎么实现?

一、MyBatis是什么 MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain …

【Java】小白友好的JDBC基础学习笔记

目录 JDBC简介 JDBC使用基本步骤 DriverManager Connection Statement PreparedStatement ResultSet JDBC简介 JDBC(Java Database Connectivity)是 Java 提供的一种用于与关系型数据库进行交互的 API(应用程序接口)。它允…

感染了后缀为.pings勒索病毒如何应对?数据能够恢复吗?

导言: 近期,一种名为.pings的勒索病毒悄然出现,给用户的数据安全带来了极大的威胁。该病毒以强力的加密手段对用户文件进行锁定,并勒索赎金。在本文中,91数据恢复将深入介绍.pings勒索病毒的特点,提供被感…

代码随想录二刷——字符串day9

文章目录 前言字符串知识点 一、 28. 找出字符串中第一个匹配项的下标二、459. 重复的子字符串总结 前言 一个本硕双非的小菜鸡,备战24年秋招,计划二刷完卡子哥的刷题计划,加油! 二刷决定精刷了,于是参加了卡子哥的刷…

虚拟机扩容后黑屏卡死解决方法

亲测有效,首先一般是在扩容后黑屏的,现象为开机后看到个横线光标不闪,黑屏,进入不了桌面。原因是硬盘已经满了,所以解决方法就是清理硬盘。所以首先还是要解决登录问题。 开机时按 esc 键进入 GNU GRUB,选择…

详解SpringCloud微服务技术栈:深入ElasticSearch(4)——ES集群

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习 🌌上期文章:详解SpringCloud微服务技术栈:深入ElasticSearch(3)——数据同步(酒店管理项目&a…

新火种AI|GPT Store可能是一个“硅基人才市场”

作者:一号 编辑:美美 也许我们都错了,GPT Store可能是一个“硅基人才市场”,而不是APP Store。 如果要说在AI领域中最火的一个应用,那么在当下,毫无疑问会是ChatGPT。 2023年,全球前50的AI工…

IT行业中最重要的证书

在IT行业,拥有一些含金量较高的证书是职业发展的关键。这些证书不仅可以证明技能水平,还有助于提升在职场上的竞争力。本文将介绍几个IT行业中最重要的证书。 1. Cisco认证 CCNA(Cisco Certified Network Associate)是Cisco公司新…

LeetCode: 189.轮转数组

本篇目标了解,翻转数组的经典解法, 189. 轮转数组 - 力扣(LeetCode) 目录 基本方法概述: 1,翻转做法,推荐时O(n),空(1) 2&#x…

J-Link:STM32使用J-LINK烧录程序,其他MCU也通用

说明:本文记录使用J-LINK烧录STM32程序的过程。 1. J-LINK驱动、软件下载 1、首先拥有硬件J-Link烧录器。 2、安装J-Link驱动程序SEGGER 下载地址如下 https://www.segger.com 直接下载就可以了。 2.如何使用J-LINK向STM32烧写程序 1、安装好以后打开J-LINK Fl…

软件测试基础总结

🍅 视频学习:文末有免费的配套视频可观看 🍅 关注公众号【互联网杂货铺】,回复 1 ,免费获取软件测试全套资料,资料在手,涨薪更快 前言 提示:本文旨在帮助小白对软件测试有个基础的入…

黑方备份学习(1):linux安装 黑方容灾备份与恢复系统软件v6.0 代理

1.环境准备 1.1硬件环境 内存>4G,cpu最低双核 1.2把SElinux状态改为Disabled (1)查看SElinux状态 输入getenforce命令 SELinux共有3个状态: enforcing (执行中)、permissive (不执行但…

SOME/IP 协议介绍(七)传输 CAN 和 FlexRay 帧

SOME/IP 不应仅用于传输 CAN 或 FlexRay 帧。但是,消息 ID 空间需要在两种用例之间进行协调。 传输 CAN/FlexRay 应使用完整的 SOME/IP 标头。 AUTOSAR Socket-Adapter 使用消息 ID 和长度来构建所需的内部 PDU,但不会查看其他字段。因此,必…