什么是缓存?

黑马Redis学习——实战篇(2) 黑马Redis课程学习实战篇(2) 阅读详情
  1. 硬件的缓存?
    cpu缓存:位于cpu和内存之间的临时存储器
  2. 软件缓存?
    软件缓存分为三级
    1. 内存缓存(预先将数据写到容器(list,map,set)等数据存储单元中,就是软件内存缓存)
    2. 数据库缓存
    3. 网络缓存
  3. 内存缓存淘汰机制分为三种
    1. FIFO(First In,First Out)先进先出
      优点:是先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单。
      缺点:只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址

    2. LFU(Least Freauently Used)
      最不经常使用页置换算法,清理掉留给经常使用的使用

    3. LRU(Least Recently Used)喜新厌旧
      内存管理的一种页面置换算法,新加入的数据放到链表的头部,当缓存命中(被访问)数据移到链表的头部,当链表满的时候,将链表尾部的数据丢弃。

          //单链表
        public class LinkedList<T> {
        
            public LinkedList() {
                size = 0;
            }
        
            Node list;
            //链表有多少个节点
            int size;
        
            //添加节点
            //在头部添加节点
            public void add(T data) {
                Node head = list;
                Node curNode = new Node(data, list);
                list = curNode;
                size++;
        
            }
        
            //在链表的index位置插入一个新数据
            public void add(int index, T data) {
                checkPositionIndex(index);
                Node cur = list;
                Node hrad = list;
                for (int i = 0; i < index; i++) {
                    hrad = cur;
                    cur = cur.next;
                }
                Node node = new Node(data, cur);
                hrad.next = node;
                size++;
        
            }
        
            // 检查index 是否在链表范围结构
            public void checkPositionIndex(int index) {
                if (!(index >= 0 && index <= size)) {
                    throw new IndexOutOfBoundsException("index:" + index + ",size" + size);
                }
            }
        
            //删除节点
            public T remove() {
                if (list != null) {
                    Node node = list;
                    list = list.next;
                    //gc
                    node.next = null;
                    size--;
                    return node.data;
                }
        
                return null;
            }
        
            public T remove(int index) {
                checkPositionIndex(index);
                Node cur = list;
                Node hrad = list;
                for (int i = 0; i < index; i++) {
                    hrad = cur;
                    cur = cur.next;
                }
                hrad.next = cur.next;
                //gc
                cur.next = null;
                size--;
                return null;
        
            }
        
            public T removeLast() {
                if (list != null) {
                    Node node = list;
                    Node cur = list;
                    while (cur.next != null) {
                        node = cur;
                        cur = cur.next;
                    }
                    //gc
                    node.next = null;
                    size--;
                    return cur.data;
                }
                return null;
            }
        
            //修改节点
        
            public void updata(int index, T newData) {
                checkPositionIndex(index);
                Node head = list;
                for (int i = 0; i < index; i++) {
                    head = head.next;
                }
                head.data = newData;
            }
        
            //查询节点
            public T get() {
                Node node = list;
                if (node != null) {
                    return node.data;
        
                } else {
                    return null;
                }
            }
        
            public T get(int index) {
                checkPositionIndex(index);
                Node node = list;
                for (int i = 0; i < index; i++) {
                    node = node.next;
                }
                return node.data;
            }
        
        
            class Node {
                T data;
                Node next;
        
                public Node(T data,
                            Node next) {
                    this.data = data;
                    this.next = next;
                }
            }
        
            @Override
            public String toString() {
                Node node = list;
                for (int i = 0; i < size; i++) {
                    System.out.println("" + node.data);
        
                    node = node.next;
                }
                return super.toString();
            }
        }
      
      public class LruLinhedList<T> extends LinkedList<T> {
      
          // 用于限定内存空间的大小
          int memorySize;
          static final int DEFAULT_CAP = 6;
      
          public LruLinhedList() {
              this(DEFAULT_CAP);
          }
      
          public LruLinhedList(int memorySize) {
              this.memorySize = memorySize;
          }
      
          //    LRU 添加节点
          public void lruAdd(T data) {
              if (size >= memorySize) {
                  removeLast();
                  add(data);
              } else {
                  add(data);
              }
          }
      
          // 删除节点
          public T lruRmove() {
              return removeLast();
          }
      
          public T lruGet(int index) {
              checkPositionIndex(index);
              Node node = list;
              Node pro = list;
              for (int i = 0; i < index; i++) {
                  pro = node;
                  node = node.next;
              }
              T reData = node.data;
              //访问节点移开头
              pro.next = node.next;
              Node head = list;
              node.next = head;
              list = node;
              return reData;
      
          }
      
          public static void main(String[] args) {
              LruLinhedList<String> LinkedList = new LruLinhedList<>(6);
              for (int i = 0; i < 6; i++) {
                  LinkedList.lruAdd("" + i);
              }
              LinkedList.toString();
              System.out.println("" + LinkedList.lruGet(4));
      
              LinkedList.toString();
              LinkedList.lruAdd(90+"");
              LinkedList.toString();
      //        LinkedList.lruGet(23);
      //        LinkedList.toString();
          }
      
      }
      
      
【Redis缓存机制】缓存更新、缓存穿透、缓存雪崩、缓存击穿 当缓存区缓存了用户信息后,客户端就都会从redis中访问读取数据了。而如果这时候用户更新了数据库中的值,就会导致数据库存储的数据与redis存储数据不一致,在这之后进行读写操作就会发生各种意想不到的错误了因此,当我们要对数据库数据进行更新时,也要尽可能让edis中的数据也能跟着变化,避免用户读到错误的信息缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样每次查询缓存都不会命中,最后都会对数据库进行查询。就像是缓存被穿透了一样,每次请求都会直接到达数据库。 阅读详情

相关推荐

Mybatis缓存机制(一级缓存、二级缓存、三级缓存)

Mybatis 一级缓存、二级缓存、三级缓存

张Sir的博客 6794

容器、pod和缓存

为了防止容器重启导致缓存丢失,应该将缓存存储到持久化存储卷(PV)上,而不是依赖容器本地的临时文件系统。这样,你就能保证容器重启后,缓存数据得以保留。将缓存存储在持久化存储卷(PV)上确实会导致读取速度比直接从内存读取要慢一些,但如果使用的是 SSD 或高性能存储,性能差异通常是可以接受的。如果对缓存访问速度有更高的要求,可以结合使用内存存储和持久化存储来平衡性能和持久性。通过 Kubernetes 的PV和PVC,你可以在 Pod 中使用持久化存储,而不需要修改应用代码。

yxg520s的博客 1565

缓存击穿、缓存穿透和缓存雪崩

缓存击穿  定义: 缓存中的key一般设有过期时间,如果某个key过期了,恰在这个时候,有大量的并发请求访问这个key,则这些请求都会到达DB,导致DB瞬间压力过大,压垮DB。  解决方案: 1.设置互斥锁,mutex。当缓存失效时不时立即去访问数据库,而是使用缓存工具的操作成功带返回值的操作,比如redis的setnx(set if not exit),memcache的add,利用setnx实现

韩丽萍 2735

深入理解缓存(Cache):原理、应用与优化

一篇搞懂软件开发当中的缓存技术,彻底理解缓存!

2301_79819426的博客 2807

PID控制器(位置式和增量式)

PID控制算法

zhinian_hao的博客 4512

如何在RT-DETR-R18中修改ultralytics的yaml文件(附完整代码)

本文详细指导如何在RT-DETR模型中,通过修改Ultralytics框架的yaml配置文件,将Backbone从ResNet50轻量化替换为ResNet18。核心步骤包括自定义ResNet18基础模块、调整HybridEncoder的expansion参数至0.5,并协同修改检测头Decoder层数,最终提供完整的配置文件代码,助力开发者在资源受限环境下部署轻量级实时目标检测模型。

weixin_29091445的博客 288

什么是缓存?常见的缓存技术有哪些?

缓存(Cache)是一种高速数据存储层,其核心目标是通过存储频繁访问的数据副本,减少对底层较慢存储介质(如内存、磁盘、网络)的直接访问,从而提升系统性能和响应速度。缓存技术基于局部性原理(时间局部性和空间局部性),即程序在一段时间内倾向于重复访问某些数据或邻近数据。硬件级缓存CPU缓存:位于CPU与主存之间,分为L1(一级)、L2(二级)、L3(三级)缓存,逐级容量增大但速度递减,用于缓解CPU与内存间的速度差异。

破损的天堂鸟博客 4104

RiscV运行zephyr和Linux的方法

riscv基金会搞了一个网站,用于介绍如何使用riscv指令集进行开发。 对于运行zephyr和linux以及Qemu有非常大的帮助。 可以作为riscv开发的相关参考。 RISC-V - Getting Started Guide — RISC-V - Getting Started Guidehttps://risc-v-getting-started-guide.readthedocs.io/en/latest/index.html RISC-V - Getting Started Gu.

闲人的专栏 737

什么是缓存?缓存的作用

一.什么是缓存?## 首先我们要知道缓存其实就是一个临时的存储器。 缓存有 :cookie、session、application、cache、redis 二.作用 缓存主要是为了提高数据的读取速度。因为服务器和应用客户端之间存在着流量的瓶颈,所以读取大容量数据时,使用缓存来直接为客户端服务,可以减少客户端与服务器端的数据交互,从而大大提高程序的性能。 以前实现数据的缓存有很多种方法,有客户端的Cookie,有服务器端的Session和Application。其中Cookie是保存在客户端的一组数

weixin_45978023的博客 3万+

PY32F406K1CU6+I2C+ AT24C64 基本配置

【代码】PY32F406K1CU6+I2C+ AT24C64 基本配置。

sam的博客 90

【Matlab】刃边法计算mtf

摘要:刃边法是一种测量光学系统调制传输函数(MTF)的常用方法。本文介绍了基于Matlab的MTF计算实现方案,包括图像灰度化、梯度计算、刀口方向选择、梯度投影等关键步骤,并给出了完整的代码实现。该方案可通过添加图像预处理、多方向计算、函数封装等方式进行扩展,提高MTF计算的准确性和实用性,适用于不同应用场景的光学系统性能评估需求。(148字)

unber的博客 389

Redis的缓存雪崩、缓存击穿、缓存穿透与缓存预热、缓存降级

一、缓存雪崩: 1、什么是缓存雪崩: 如果缓在某一个时刻出现大规模的key失效,那么就会导致大量的请求打在了数据库上面,导致数据库压力巨大,如果在高并发的情况下,可能瞬间就会导致数据库宕机。这时候如果运维马上又重启数据库,马上又会有新的流量把数据库打死。这就是缓存雪崩。 2、问题分析: 造成缓存雪崩的关键在于同一时间的大规模的key失效,为什么会出现这个问题,主要有两种可能:第一种是Redis宕机,第二种可能就是采用了相同的过期时间。搞清楚原因之后,那么有什么解决方案呢? 3、解决方案: (1)

张维鹏的博客 3万+

Educoder:爬虫实战——求是网周刊文章爬取

第1关:获取新闻url importrequests importre defgeturls(): #**********Begin**********# url='http://www.qstheory.cn/dukan/qs/2014/2019-01/01/c_1123924172.htm' headers={ 'User-Agent':'Mozilla/5.0(Linux;Android6.0;Nexus5Buil...

weixin_46026136的博客 5255

缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等问题

前面一节说到了《为什么说Redis是单线程的以及Redis为什么这么快!》,今天给大家整理一篇关于Redis经常被问到的问题:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等概念的入门及简单解决方案。 一、缓存雪崩 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询...

徐刘根的博客 4万+

小梅哥Xilinx ZYNQ学习笔记2——38译码器

译码器(Decoder)是一种多输入多输出的组合逻辑电路,负责将二进制代码翻译为特定的对象(如逻辑电平等),功能与编码器相反。译码器一般分为通用译码器和数字显示译码器两大类。本设计的是通用译码器。三八译码器,即是 3 种输入状态翻译成 8 种输出状态。1.case开始开始,endcase结束;2.数字声明时,合法的基数格式有 4 中,包括:十进制('d 或 'D),十六进制('h 或 'H),二进制('b 或 'B),八进制('o 或 'O)。数值可指明位宽,也可不指明位宽。

m0_51430584的博客 1636

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

什么是缓存、为什么要用缓存、缓存分类、缓存&测试、缓存更新、缓存设计考虑点、缓存测试点

什么是缓存、为什么要用缓存、缓存分类、缓存&测试、缓存更新、缓存设计考虑点、缓存测试点

FixedStar 的博客 2773

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Redis 缓存预热,缓存雪崩,缓存击穿,缓存穿透

缓存预热就是系统启动前,提前将相关的缓存数据直接加载到缓存系统。避免在用户请求的时候,先查 询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据请求数量较高主从之间数据吞吐量较大,数据同步操作频度较高因为刚刚启动时,缓存中没有任何数据日常例行统计数据访问记录,统计访问频度较高的热点数据将统计结果中的数据分类,根据级别,redis优先加载级别较高的热点数据。

weixin_66015936的博客 1984

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Redis系列:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级

今天给大家整理一篇关于Redis经常被问到的问题:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等概念 一、缓存雪崩 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个...

Onechengxuyuan的博客 2616

缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级、缓存热点 key

关于Redis经常被问到的问题:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级、缓存热点 key等概念的入门及简单解决方案。 一、缓存雪崩 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一...

河湾 2107

Redis的缓存问题之缓存穿透、缓存雪崩、缓存击穿

缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。解决方案(4种)(1)给不同的Key的TTL添加随机值(推荐)操作简单,当我们在做缓存预热的时候,就有可能在同一时间批量插入大量的数据,那么如果它们的TTL都一样的话就可能出现大量key同时过期的情况!!!所以我们需要在设置过期时间TTL的时候,定义一个范围,追加该范围内的一个随机数。

花&败 4862

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

缓存分类、更新策略、缓存穿透、缓存雪崩、缓存击穿

lcx_defender的博客 1916

缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级的理解

缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级的理解

weixin_40587144的博客 1339

全缓存、行缓存和无缓存

在标准I/O中,核心对象是流。所谓流,它是一个过程,所有的I/O操作都是简单的从程序的移进或移出,我们把这种字符流叫做流。标准I/O基于流的操作都是缓存文件系统。 缓存类型分为三种,分别是全缓存、行缓存和无缓存。 全缓存:填满标准I/O缓存区才进行实际的I/O操作。磁盘上的了件用标准I/O打开,默认都是全缓存的。当缓存区填满或者进行flush操作时候才会进行磁盘操作。 行缓存:当输入输出遇到

puddinghamster的博客 1万+

什么是缓存,缓存策略有哪些?

1、什么是缓存? ☞ 缓存就是数据交换的缓冲区(称作:Cache),当某一硬件要读取数据时,会首先从缓存汇总查询数据,有则直接执行,不存在时从内存中获取。由于缓存的数据比内存快的多,所以缓存的作用就是帮助硬件更快的运行。 ☞ 缓存往往使用的是RAM(断电既掉的非永久存储),所以在用完后还是会把文件送到硬盘等存储器中永久存储。电脑中最大缓存就是内存条,硬盘上也有16M或者32...

qq_39283195的博客 1万+
上一篇: Kotlin 类、对象和继承 接口
下一篇: java类加载过程
jhonjson
博客等级 码龄11年 220粉丝 195原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值