redis缓存-更新策略-三大缓存问题

缓存:数据交换的缓冲区,存储的数据的临时地方,读写性能较高。

步骤:

  1. 先从redis里面查询
    • 缓存命中:直接返回结果
    • 缓存未命中
  2. 从数据库里面查询
    • 没有数据:返回null
    • 有数据:存到redis里面,并返回

缓存更新策略:

1、内存淘汰:redis内存不足时,自动淘汰一部分数据;

2、超时剔除:设置TTL过期时间;

3、主动更新:查询数据库时就更新redis。

按业务场景去使用:

低一致性:内存淘汰

高一致性:主动更新,超时剔除作为兜底

主动更新策略

  1. Cache Aside Pattern调用者自己编码,更新数据库时更新缓存
  2. Read/Write Through Pattern缓存和数据库整合为一个服务,调用者使用该服务
  3. Write Behind Caching Pattern调用者仅仅操作缓存,由其他的线程异步将缓存数据持久化到数据库

缓存穿透

缓存穿透的定义
缓存穿透是指客户端请求的数据在缓存和数据库中都不存在,这样每次请求都会穿透缓存直接访问数据库。如果大量这样的请求同时出现,可能会导致数据库压力过大,甚至造成数据库服务崩溃。
例如,攻击者故意使用一些不存在的用户 ID 频繁请求用户信息接口,由于这些用户 ID 对应的信息在缓存和数据库中都没有,就会使这些请求直接打到数据库上。
缓存穿透产生的原因
恶意攻击:攻击者通过构造大量不存在的键来频繁请求服务,试图使数据库过载。
业务逻辑问题:在业务代码中,可能存在没有对数据是否存在进行有效验证就直接查询数据库的情况。比如,在一个电商系统中,商品 ID 如果没有经过合法性检查,可能会有一些无效的 ID 被当作正常请求发送到数据库。

缓存穿透的解决方案

缓存空对象

原理:当从数据库查询数据发现不存在时,在缓存中缓存一个空对象(可以使用一个特定的标记值来表示空对象),并设置一个较短的过期时间。这样,下次同样的请求过来时,会在缓存中命中这个空对象,避免直接访问数据库。

优缺点:
优点:简单有效,能够快速解决大部分缓存穿透问题。
缺点:

  • 如果恶意攻击者使用大量不同的不存在的键进行攻击,缓存中会存储大量的空对象,占用缓存空空间,可以将过期时间设置的短一点。
  • 会造成数据短期的不一致。id不存在,缓存了一个空值,当新的数据来时,并且和当前缓存空对象的id一致。会造成redis缓存是空,但是实际上有这条数据。当该id数据被访问时,走redis取出的就会是空。可以给过期时间设置短一点,或者在插入数据时跟新一下缓存。

布隆过滤器(Bloom Filter)

原理:布隆过滤器是一种概率型数据结构,它可以用来判断一个元素是否在一个集合中。它的原理是通过多个哈希函数对元素进行哈希运算,将结果对应的位在一个位数组中置为 1。当查询一个元素是否存在时,对该元素进行同样的哈希运算,如果所有对应的位都是 1,则该元素可能存在;如果有任何一位是 0,则该元素一定不存在。
示例:使用 Google Guava 库中的布隆过滤器(这只是一个简单示例,实际应用中可能需要根据数据量和误判率等因素调整参数)。

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import java.nio.charset.Charset;
public class BloomFilterExample {public static void main(String[] args) {// 创建一个布隆过滤器,预计插入1000个元素,误判率为0.01BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.forName("UTF - 8")), 1000, 0.01);// 假设这些是数据库中存在的用户IDString[] existingUserIds = {"1", "2", "3"};for (String userId : existingUserIds) {bloomFilter.put(userId);}// 检查用户ID是否可能存在String nonExistentUserId = "4";if (!bloomFilter.mightExist(nonExistentUserId)) {System.out.println("这个用户ID大概率不存在,无需查询数据库");}}
}

优缺点:

优点:可以高效地过滤掉大量不存在的元素,节省缓存空间和数据库查询次数。

缺点:实现复杂,存在一定的误判率,即有可能将实际上不存在的元素判断为可能存在,但可以通过调整参数来降低误判率。而且布隆过滤器本身也需要占用一定的内存空间。

主动避免缓存穿透

上面的都是被动去接受缓存穿透,但是可以主动去避免。

  1. 增强id的复杂性,避免被猜出id;
  2. 对传来的id做基本的格式校验,将不符合要求的id给pass掉;
  3. 做好热点参数的限流(微服务)
  4. 加强用户权限的校验,用户没有权限不能访问一些接口。

缓存雪崩

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

解决方案:

  • 给不同的Key的TTL添加随机值
  • 利用Redis集群提高服务的可用性
  • 给缓存业务添加降级限流策略(微服务)
  • 给业务添加多级缓存(微服务)

缓存击穿

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

缓存重建业务较复杂 :查询数据库建立缓存耗时较长(几十、几百毫秒),在这个时间内可能有多个其他的线程也来访问,去查数据库,照成数据库压力过大。

解决方案:

互斥锁

多个线程来访问,当一个线程访问未命中时,获取锁,然后查数据库,建立缓存,释放锁;在这个时间内,其他的线程再来时,获取不到锁,一直等待带线程释放锁。

优点:保证一致性;

缺点

其他的许多线程会等待该线程执行完成,性能下降;

可能引发死锁。

逻辑过期

适用于缓存热点key,提前有缓存预热。

把过期时间设置在 redis的value中,注意:这个过期时间并不会直接作用于redis,而是我们后续通过逻辑去处理。

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

这种方案巧妙在于,异步的构建缓存,缺点在于在构建完缓存之前,返回的都是脏数据

优点:其他的线程无需等待;

缺点:不能保证数据的一致性;

缓存预热 :活动开始时,对于一些热点key,提前加到redis中,设置逻辑过期时间,所以说缓存一般是一定会命中的,未命中说明不是热点key,返回null;活动结束,再删除。

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

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

相关文章

[TriCore] 01.QEMU 虚拟化 TriCore 架构中的寄存器 指令

目录 1.寄存器宏 - FIELD() 2.寄存器操作 - FIELD_SETTER() & FIELD_GETTER() 3.指令辅助方法 - HELPER() 3.1.辅助宏 3.2.指令示例 3.3.函数调用 4.PSW 寄存器读写 - psw_read() & psw_write() 1.寄存器宏 - FIELD() FIELD() 宏定义寄存器 MASK // include/hw…

《软件工程》第 4 章 - 需求获取

在软件工程中&#xff0c;需求获取是挖掘用户真实需求的关键步骤&#xff0c;它为后续的设计、开发和测试提供坚实基础。本章将围绕需求获取的流程、方法及工具展开&#xff0c;结合实际案例与 Java 代码&#xff0c;深入讲解这一重要环节。 4.1 软件需求的初始表示 4.1.1 用例…

react diff 算法

diff 算法作为 Virtual DOM 的加速器&#xff0c;其算法的改进优化是 React 整个界面渲染的基础和性能的保障&#xff0c;同时也是 React 源码中最神秘的&#xff0c;最不可思议的部分 diff 算法会帮助我们就算出 VirtualDOM 中真正变化的部分&#xff0c;并只针对该部分进行原…

Gin项目脚手架与标配组件

文章目录 前言设计思想和原则✨ 技术栈视频实况教程sponge 内置了丰富的组件(按需使用)几个标配常用组件主要技术点另一个参考链接 前言 软件和汽车一样&#xff0c;由多个重要零部件组装而成。 本文堆积了一些常用部件&#xff0c;还没来得及好好整理。先放着。 神兵利器虽多…

【Webtrees 手册】第 10章 - 用户体验

Webtrees 手册/用户体验 < Webtrees 手册 跳转到导航跳转到搜索 信息 手册部分仍在建设中 请耐心等待或随意贡献自己的力量:-)。 第 10 章 - 用户体验 <- 章节概述 目录 1多位系谱学家的合作 1.1家庭研究模型1.2“孤胆战士”模型1.3示范“本地家庭书”1.4模特“俱乐部”…

Linux 进程概念(下)

目录 前言 4.进程状态 一.普遍的操作系统层面上宏观概念&#xff1a; 二.具体的Linux操作系统的状态&#xff1a; 5.进程优先级&#xff08;了解&#xff09; 6.其他概念 进程切换 前言 本篇是接着上一篇的内容继续往下了解进程相关的一些概念&#xff01; 4.进程状态 运…

使用java实现word转pdf,html以及rtf转word,pdf,html

word,rtf的转换有以下方案&#xff0c;想要免费最靠谱的是LibreOffice方案, LibreOffice 是一款 免费、开源、跨平台 的办公软件套件&#xff0c;旨在为用户提供高效、全面的办公工具&#xff0c;适用于个人、企业和教育机构。它支持多种操作系统&#xff08;Windows、macOS、…

IP证书的作用与申请全解析:从安全验证到部署实践

在网络安全领域&#xff0c;IP证书&#xff08;IP SSL证书&#xff09;作为传统域名SSL证书的补充方案&#xff0c;专为公网IP地址提供HTTPS加密与身份验证服务。本文将从技术原理、应用场景、申请流程及部署要点四个维度&#xff0c;系统解析IP证书的核心价值与操作指南。 一…

GitLab 18.0 正式发布,15.0 将不再受技术支持,须升级【三】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 官网极狐…

超简单Translation翻译模型部署

Helsinki-NLP/opus-mt-{en}-{zh}系列翻译模型可以实现200多种语言翻译&#xff0c;Helsinki-NLP/opus-mt-en-zh是其中英互译模型。由于项目需要&#xff0c;在本地进行搭建&#xff0c;并记录下搭建过程&#xff0c;方便后人。 1. 基本硬件环境 CPU&#xff1a;N年前的 Intel…

Go语言JSON 序列化与反序列化 -《Go语言实战指南》

JSON&#xff08;JavaScript Object Notation&#xff09;是一种常见的数据交换格式。Go 标准库提供了 encoding/json 包&#xff0c;用于方便地将结构体与 JSON 之间互转。 一、序列化&#xff08;Marshal&#xff09; 将 Go 中的数据结构&#xff08;如结构体、map、slice 等…

免费PDF工具-PDF24V9.16.0【win7专用版】

【百度】https://pan.baidu.com/s/1H7kvHudG5JTfxHg-eu2grA?pwd8euh 提取码: 8euh 【夸克】https://pan.quark.cn/s/92080b2e1f4c 【123】https://www.123912.com/s/0yvtTd-XAHjv https://creator.pdf24.org/listVersions.php

网络 :序列和反序列化

网络 &#xff1a;序列和反序列化 &#xff08;一&#xff09;序列和反序列 概念&#xff08;二&#xff09;实例1. 封装socket 接口2. 制定协议&#xff08;用于实现序列和反序列化&#xff09;3. 计算(实现计算器功能)4. 服务器(将上面所有的类功能调用起来)5. 服务端6.客户端…

LiveQing 视频点播流媒体 RTMP 推流服务功能:搭建 RTMP 视频流媒体服务详细指南

LiveQing视频点播流媒体RTMP推流服务功能&#xff1a;搭建RTMP视频流媒体服务详细指南 一、流媒体服务搭建二、推流工具准备三、创建鉴权直播间四、获取推流地址五、配置OBS推流六、推流及播放七、获取播放地址7.1 页面查看视频源地址7.2 接口查询 八、相关问题解决8.1 大疆无人…

UE5 Niagara 如何让四元数进行旋转

Axis Angle中&#xff0c;X,Y,Z分别为旋转的轴向&#xff0c;W为旋转的角度&#xff0c;在这里旋转角度不需要除以2&#xff0c;因为里面已经除了&#xff0c;再将计算好的四元数与要进行旋转的四元数进行相乘&#xff0c;结果就是按照原来的角度绕着某一轴向旋转了某一角度

【微服务】SpringBoot 对接飞书审批流程使用详解

目录 一、前言 二、前置准备 2.1 开通企业飞书账户 2.2 确保账户具备多维表操作权限 2.3 获取飞书开放平台文档 2.4 创建应用 2.5 发布应用 2.6 应用添加操作权限 2.7 获取SDK 三、审批流程对接过程 3.1 配置流程审批定义(流程审批模型) 3.2 自定义应用添加审批AP…

主键与唯一键详解:概念、区别与面试要点

主键与唯一键详解:概念、区别与面试要点 一、核心概念解析 1.1 主键(Primary Key) 主键是数据库表中用于唯一标识每一行记录的列或列组合,具有以下核心特性: 唯一性:主键值在整个表中必须唯一,不允许重复非空性:主键列不允许包含NULL值不可变性:主键值一旦确立,原则…

前端面试准备-1

1.NodeJS的优缺点 优点&#xff1a;   高并发&#xff08;最重要的优点&#xff09;   适合I/O密集型应用 缺点&#xff1a;   不适合CPU密集型应用&#xff1b;CPU密集型应用给Node带来的挑战主要是&#xff1a;由于JavaScript单线程的原因&#xff0c;如果有长时间运行的…

GO并发过高导致程序崩溃如何解决

#作者&#xff1a;曹付江 文章目录 1.并发过高导致程序崩溃2. 如何解决2.1 利用 channel 的缓存区2.2 利用第三方库 3 调整系统资源的上限3.1 ulimit3.2 虚拟内存(virtual memory) 1.并发过高导致程序崩溃 看一个非常简单的例子&#xff1a; func main() {var wg sync.WaitG…

Linux -- gdb/cgdb的认识和使用

预备知识 程序的发布⽅式有两种&#xff0c; debug 模式和 release 模式&#xff0c; Linux gcc/g 出来的⼆进制程 序&#xff0c;默认是 release 模式。 要使⽤gdb调试&#xff0c;必须在源代码⽣成⼆进制程序的时候, 加上 -g 选项&#xff0c;如果没有添加&#x…