当前位置: 首页 > news >正文

Redis缓存的一些概念性问题

目录

缓存模型和思路

缓存更新策略

数据库和缓存不一致

缓存与数据库双写一致

缓存穿透

缓存雪崩

缓存击穿


速度快,好用,内存的读写性能远高于磁盘,缓存可以大大降低用户访问并发量带来的服务器读写压力

缓存模型和思路

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

代码思路:如果缓存有,则直接返回,如果缓存不存在,则查询数据库,然后存入redis。

image-20240620194651457

缓存更新策略

目的:为了节约内存

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

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

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

数据库和缓存不一致

数据库的数据发送变化,缓存没有同步,此时会有数据一致性问题存在

解决方案:

image-20240620195446771

应当是先操作数据库,再删除缓存,原因在于,如果你选择第一种方案,在两个线程并发来访问时,假设线程1先来,他先把缓存删了,此时线程2过来,他查询缓存数据并不存在,此时他写入缓存,当他写入缓存后,线程1再执行更新动作时,实际上写入的就是旧的数据,新的数据被旧数据覆盖了。

1.先删除缓存,再操作数据库时:更新数据库的时间较长,介入其他线程的概率很打

2.先操作数据库,再删除缓存时:写缓存的速度很快,介入其他线程的概率很小

image-20240620195625331

缓存与数据库双写一致

如果缓存未命中,则查询数据库,将数据库结果写入缓存,并设置超时时间;采用删除策略,来解决双写问题,修改数据时,先修改数据库,再删除缓存(例如:根据id修改数据时)

当我们修改了数据之后,然后把缓存中的数据进行删除,查询时发现缓存中没有数据,则会从mysql中加载最新的数据,从而避免数据库和缓存不一致的问题

缓存穿透

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

解决方案:(访问这个不存在的数据,那么在redis中也能找到这个数据就不会进入到数据库了)

  • 缓存空对象 实现简单,维护方便(额外的内存消耗,可能造成短期的不一致)

  • 布隆过滤 内存占用较少,没有多余key (实现复杂,哈希思想,存在哈希冲突,有误判可能)

    主动防止:

    • 增强id的复杂度,避免被猜测id规律

    • 做好数据的基础格式校验

    • 加强用户权限校验

    • 做好热点参数的限流

image-20240620202437830

缓存雪崩

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

解决方案:

  • 给不同的Key的TTL添加随机值

  • 利用Redis集群提高服务的可用性

  • 给缓存业务添加降级限流策略

  • 给业务添加多级缓存

image-20240620205419932

缓存击穿

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

线程A在查询数据库并重新加载到缓存的期间有大量的其它线程来访问这些数据,缓存中没有,去数据库中找,导致数据库访问压力过大

常见的解决方案有两种:

  1. 互斥锁

    大量同时访问这些数据时,只能有线程A去访问数据库,在访问时加上锁,其它线程获取锁失败,处于循环等待中,直到线程A访问数据库完毕,写入了缓存,使得其它线程可以缓存命中了

    image-20240620211205116

    互斥锁实现逻辑

    image-20240620214756857

  2. 逻辑过期

出现这个缓存击穿问题,主要原因是在于我们对key设置了过期时间,逻辑过期是不设置过期时间,而是把过期时间设置在 redis 的value中,后续通过逻辑去处理

在线程A,发现逻辑时间过期,获取有锁成功,会另开一个线程去完成查询数据重建缓存,线程A返回旧数据;当其它线程来时,发现获取锁失败会直接返回旧数据,直到另开的线程锁释放后才能得到新数据

image-20240620212535113

逻辑过期实现逻辑:

image-20240620222032478

对比:

image-20240620212630091

模拟高并发:JMeter 下载安装:Jmeter安装教程【5.5】【Windows】jmeter详细安装配置教程,装不好你打我-CSDN博客

相关文章:

  • Milvus跨集群数据迁移
  • MySQL 保姆级教程(八):创建计算字段
  • 【Ubuntu通用压力测试】Ubuntu16.04 CPU压力测试
  • 传统后端SQL数据层替代解决方案: 内置数据源+JdbcTemplate+H2数据库 详解
  • YOLOv10改进 | Conv篇 |YOLOv10引入SPD-Conv卷积
  • 【前端技巧】css篇
  • React.ReactElement 与 React.ReactNode
  • Effective C++ 改善程序与设计的55个具体做法笔记与心得 3
  • SonarQube集成Jenkins平台搭建
  • 【Python】一文向您详细解析内置装饰器 @lru_cache
  • 【Android面试八股文】Kotlin内置标准函数let的原理是什么?
  • 初识C++ · 继承(1)
  • 乐鑫ESP32相关资料整理
  • 喜马拉雅项目调整
  • 让NSdata对象转变成UIImage对象再裁剪图片的方法
  • .pyc 想到的一些问题
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • 30秒的PHP代码片段(1)数组 - Array
  • Android Volley源码解析
  • angular2 简述
  • bootstrap创建登录注册页面
  • chrome扩展demo1-小时钟
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • node.js
  • Rancher-k8s加速安装文档
  • 编写符合Python风格的对象
  • 对象引论
  • 前嗅ForeSpider中数据浏览界面介绍
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 入口文件开始,分析Vue源码实现
  • 使用 Docker 部署 Spring Boot项目
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 在Unity中实现一个简单的消息管理器
  • - 转 Ext2.0 form使用实例
  • postgresql行列转换函数
  • zabbix3.2监控linux磁盘IO
  • 积累各种好的链接
  • ​iOS实时查看App运行日志
  • ​软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】​
  • #include<初见C语言之指针(5)>
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (9)目标检测_SSD的原理
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (附源码)springboot学生选课系统 毕业设计 612555
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (附源码)ssm码农论坛 毕业设计 231126
  • (亲测有效)推荐2024最新的免费漫画软件app,无广告,聚合全网资源!
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • ./和../以及/和~之间的区别
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .net 无限分类
  • .NET 中的轻量级线程安全
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件
  • .pyc文件是什么?