缓存 订阅
缓存(cache),原始意义是指访问速度比一般随机存取存储器(RAM)快的一种高速存储器,通常它不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术。缓存的设置是所有现代计算机系统发挥高性能的重要因素之一。 展开全文
缓存(cache),原始意义是指访问速度比一般随机存取存储器(RAM)快的一种高速存储器,通常它不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术。缓存的设置是所有现代计算机系统发挥高性能的重要因素之一。
信息
外文名
cache
类    别
高速缓存、磁盘缓存
原    理
程序局部性原理
中文名
缓存
学    科
计算机
目    的
提高数据存取速度
缓存简介
缓存是指可以进行高速数据交换的存储器,它先于内存与CPU交换数据,因此速率很快。L1 Cache(一级缓存)是CPU第一层高速缓存。内置的L1高速缓存的容量和结构对CPU的性能影响较大,不过高速缓冲存储器均由静态RAM组成,结构较复杂,在CPU管芯面积不能太大的情况下,L1级高速缓存的容量不可能做得太大。一般L1缓存的容量通常在32—256KB。L2 Cache(二级缓存)是CPU的第二层高速缓存,分内部和外部两种芯片。内部的芯片二级缓存运行速率与主频相同,而外部的二级缓存则只有主频的一半。L2高速缓存容量也会影响CPU的性能,原则是越大越好,普通台式机CPU的L2缓存一般为128KB到2MB或者更高,笔记本、服务器和工作站上用CPU的L2高速缓存最高可达1MB-3MB。由于高速缓存的速度越高价格也越贵,故有的计算机系统中设置了两级或多级高速缓存。紧靠内存的一级高速缓存的速度最高,而容量最小,二级高速缓存的容量稍大,速度也稍低 [1]  。缓存只是内存中少部分数据的复制品,所以CPU到缓存中寻找数据时,也会出现找不到的情况(因为这些数据没有从内存复制到缓存中去),这时CPU还是会到内存中去找数据,这样系统的速率就慢下来了,不过CPU会把这些数据复制到缓存中去,以便下一次不要再到内存中去取。随着时间的变化,被访问得最频繁的数据不是一成不变的,也就是说,刚才还不频繁的数据,此时已经需要被频繁的访问,刚才还是最频繁的数据,又不频繁了,所以说缓存中的数据要经常按照一定的算法来更换,这样才能保证缓存中的数据是被访问最频繁的。
收起全文
精华内容
下载资源
问答
  • 缓存

    千次阅读 2020-02-26 11:39:45
    服务器缓存 优先去缓存中查找数据 数据不存在,再去数据库中查找 django 内置缓存系统 (参考博客) 提供缓存api 少的代码实现缓存 多种缓存 扩展性 setting中配置 set/get/delete 支持过期 常见问题 缓存雪崩 ...
    • 服务器优化,减少磁盘IO
    • 服务器缓存
      • 优先去缓存中查找数据
      • 数据不存在,再去数据库中查找
    • django 内置缓存系统 (参考博客
      • 提供缓存api
      • 少的代码实现缓存
      • 多种缓存
      • 扩展性
      • setting中配置
      • set/get/delete
      • 支持过期
      • 常见问题
        • 缓存雪崩 -> 缓存时间错开、多台设备缓存
        • 穿透 -> 缓存过期,同时来了多个用户访问此数据(导致此条数据被同时查询多遍)
          • 添加标记,已经有人在查询,其他人等待
        • 缓存时间 结合具体的业务场景
          • 新闻
          • 电影
    展开全文
  • 缓存穿透、缓存击穿、缓存雪崩区别和解决方案

    万次阅读 多人点赞 2018-09-19 14:35:57
    一、缓存处理流程  前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果。     二、缓存穿透  描述:  缓存...

    一、缓存处理流程

          前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果。

          

     

    二、缓存穿透

           描述:

           缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。

          解决方案:

    1. 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
    2. 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击

     

    三、缓存击穿

          描述:

          缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力

          解决方案:

    1. 设置热点数据永远不过期。
    2. 加互斥锁,互斥锁参考代码如下:

             

     

              说明:

              1)缓存中有数据,直接走上述代码13行后就返回结果了

             2)缓存中没有数据,第1个进入的线程,获取锁并从数据库去取数据,没释放锁之前,其他并行进入的线程会等待100ms,再重新去缓存取数据。这样就防止都去数据库重复取数据,重复往缓存中更新数据情况出现。

              3)当然这是简化处理,理论上如果能根据key值加锁就更好了,就是线程A从数据库取key1的数据并不妨碍线程B取key2的数据,上面代码明显做不到这点。

     

    四、缓存雪崩

          描述:

          缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,        缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

         解决方案

    1. 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
    2. 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
    3. 设置热点数据永远不过期。
    展开全文
  • 浅谈 MyBatis 三级缓存

    万次阅读 2020-03-15 21:38:10
    1、一级缓存 ​ MyBatis 默认开启了一级缓存,一级缓存是在SqlSession 层面进行缓存的。即,同一个SqlSession ,多次调用同一个Mapper和同一个方法的同一个参数,只会进行一次数据库查询,然后把数据缓存到缓冲中,...

    1、一级缓存

    ​ MyBatis 默认开启了一级缓存,一级缓存是在SqlSession 层面进行缓存的。即,同一个SqlSession ,多次调用同一个Mapper和同一个方法的同一个参数,只会进行一次数据库查询,然后把数据缓存到缓冲中,以后直接先从缓存中取出数据,不会直接去查数据库。但是不同的SqlSession对象,因为不用的SqlSession都是相互隔离的,所以相同的Mapper、参数和方法,它还是会再次发送到SQL到数据库去执行,返回结果。

    2、二级缓存

    ​ 为了解决这个问题,需要手动开启二级缓存,在SqlSessionFactory层面给各个SqlSession 对象共享。默认二级缓存是不开启的,需要手动进行配置。
    mybatis-config.xml文件中添加

    <setting name="cacheEnabled" value="true"/>
    

    xxxMapper.xml文件中添加

    <cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024" ></cache>
    

    各个属性意义如下:
    eviction:缓存的回收策略。
    ​ LRU - 最近最少使用,移除最长时间不被使用的对象。
    ​ FIFO - 先进先出,按对象进入缓存的顺序来移除它们。
    ​ SOFT - 软引用,移除基于垃圾回收器状态和软引用规则的对象。
    ​ WEAK - 弱引用,更积极地移除基于垃圾收集器和弱引用规则的对象。
    ​ 默认的是LRU。
    flushInterval:缓存刷新间隔。
    ​ 缓存多长时间清空一次,默认不清空,设置一个毫秒值。
    readOnly:是否只读。
    ​ true:只读:mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。mybatis为了加快获取数据,直接就会将数据在缓存中的引用交给用户 。不安全,速度快。
    ​ false:读写(默认):mybatis觉得获取的数据可能会被修改,mybatis会利用序列化&反序列化的技术克隆一份新的数据给你。安全,速度相对慢。
    size:缓存存放多少个元素。
    type:指定自定义缓存的全类名(实现Cache接口即可)。ps:要使用二级缓存,对应的POJO必须实现序列化接口 。
    useCache="true"是否使用一级缓存,默认false。sqlSession.clearCache();只是清除当前session中的一级缓存。
    useCache配置:如果一条句每次都需要最新的数据,就意味着每次都需要从数据库中查询数据,可以把这个属性设置为false,如:

    <select id="selectUserById" resultMap="map" useCache="false">
    

    ​ 刷新缓存(就是清空缓存)
    ​ 二级缓存默认会在insert、update、delete操作后刷新缓存,可以手动配置不更新缓存,如下:

    <update id="updateUserById" parameterType="User" flushCache="false" />
    

    3、自定义缓存

    ​ 自定义缓存对象,该对象必须实现 org.apache.ibatis.cache.Cache 接口。
    ​ 为了方便日后的开发工作和降低学习成本,我们可以使用第三方缓存,在这里笔者推荐使用EhCache。

    EhCache是一个快速的、轻量级的、易于使用的、进程内的缓存。它支持read-only和read/write缓存,内存和磁盘缓存。是一个非常轻量级的缓存实现,而且从1.2之后就支持了集群,目前的最新版本是2.8。

    部署

    3.1. 导入所需jar:
    ​ 核心包:ehcache-core-2.6.8.jar
    ​ 整合包:mybatis-ehcache-1.0.3.jar
    ​ 依赖jar包:slf4j-api-1.6.6.jar,slf4j-jdk14-1.6.6.jar

    3.2. 导入所需配置文件:
    ehcache.xml,下面是对配置文件的一些讲解

    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
     
     <!-- 磁盘保存路径 -->
     <diskStore path="D:\java\ehcache" />
     
     <defaultCache 
       maxElementsInMemory="10000" 
       maxElementsOnDisk="10000000"
       eternal="false" 
       overflowToDisk="true" 
       timeToIdleSeconds="120"
       timeToLiveSeconds="120" 
       diskExpiryThreadIntervalSeconds="120"
       memoryStoreEvictionPolicy="LRU">
     </defaultCache>
     
    </ehcache>
     
    <!-- 
    
    属性说明:
    diskStore:指定数据在磁盘中的存储位置。
    defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略。
     
    以下属性是必须的:
    maxElementsInMemory - 在内存中缓存的element的最大数目。
    maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大。
    eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断。
    overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上。
     
    以下属性是可选的:
    timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大。
    timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大。
    diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区。
    diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
    diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作。
    memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)。
    
     -->
    

    3.3. 在xxxMapper.xml文件中添加

    <cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
    

    ​ 如果在其他的xxxMapper.xml文件中也想要使用,只需在该文件下配置,namespace为配置过得命名空间地址。

    <cache-ref namespace="dao.UserMapper"/>
    

    ​ mybatis默认是启用cache的,所以对于某一条不想被cache的sql需要把useCache="false"加上。例如:

    <select id="selectUserById" useCache="false">
    

    ​ 进行测试后,会在“磁盘保存路径”中产生了相关的文件。

    混〔IT〕的小学生 热爱编程,喜欢挑战新事物! 撩撩博主 😃

    展开全文
  • Redis缓存穿透、缓存雪崩问题分析

    万次阅读 多人点赞 2018-06-01 22:16:35
    把redis作为缓存使用已经是司空见惯,但是使用redis后也可能会碰到一系列的问题,尤其是数据量很大的时候,经典的几个问题如下: (一)缓存和数据库间数据一致性问题 分布式环境下(单机就不用说了)非常容易出现...

    把redis作为缓存使用已经是司空见惯,当redis中的数据量起来了以后你就得考虑以下几个问题:

    (一)缓存和数据库间数据一致性问题

    分布式环境下(单机就不用说了)非常容易出现缓存和数据库间的数据一致性问题,针对这一点的话,只能说,如果你的项目对缓存的要求是强一致性的,那么请不要使用缓存。我们只能采取合适的策略来降低缓存和数据库间数据不一致的概率,而无法保证两者间的强一致性。合适的策略包括 合适的缓存更新策略,更新数据库后要及时更新缓存、缓存失败时增加重试机制,例如MQ模式的消息队列。


    ()缓存穿透问题

    现象:用户大量并发请求的数据(key)对应的数据在redis和数据库中都不存在,导致尽管数据不存在但还是每次都会进行查DB。

    为什么key对应数据在缓存和db中不存在还会每次都进行DB查询呢?因为很多开发同学写的代码写的逻辑都是先从redis缓存中查一把,如果缓存中为空则从DB中查,如果DB中查到的数据不为空则设置到缓存并返回给接口。那么问题来了,如果从DB中查询的数据为空呢??

    解决方案

    • 从DB中查询出来数据为空,也进行空数据的缓存,避免DB数据为空也每次都进行数据库查询;
    • 使用布隆过滤器,但是会增加一定的复杂度及存在一定的误判率;

    bloomfilter就类似于一个hash set,用于快速判某个元素是否存在于集合中,其典型的应用场景就是快速判断一个key是否存在于某容器,不存在就直接返回。布隆过滤器的关键就在于hash算法和容器大小,下面先来简单的实现下看看效果,我这里用guava实现的布隆过滤器:

    <dependencies>  
         <dependency>  
             <groupId>com.google.guava</groupId>  
             <artifactId>guava</artifactId>  
             <version>23.0</version>  
         </dependency>  
    </dependencies>  
    public class BloomFilterTest {
    
        private static final int capacity = 1000000;
        private static final int key = 999998;
    
        private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), capacity);
    
        static {
            for (int i = 0; i < capacity; i++) {
                bloomFilter.put(i);
            }
        }
    
        public static void main(String[] args) {
            /*返回计算机最精确的时间,单位微妙*/
            long start = System.nanoTime();
    
            if (bloomFilter.mightContain(key)) {
                System.out.println("成功过滤到" + key);
            }
            long end = System.nanoTime();
            System.out.println("布隆过滤器消耗时间:" + (end - start));
            int sum = 0;
            for (int i = capacity + 20000; i < capacity + 30000; i++) {
                if (bloomFilter.mightContain(i)) {
                    sum = sum + 1;
                }
            }
            System.out.println("错判率为:" + sum);
        }
    }
    成功过滤到999998
    布隆过滤器消耗时间:215518
    错判率为:318

    可以看到,100w个数据中只消耗了约0.2毫秒就匹配到了key,速度足够快。然后模拟了1w个不存在于布隆过滤器中的key,匹配错误率为318/10000,也就是说,出错率大概为3%,跟踪下BloomFilter的源码发现默认的容错率就是0.03:

    public static <T> BloomFilter<T> create(Funnel<T> funnel, int expectedInsertions /* n */) {
      return create(funnel, expectedInsertions, 0.03); // FYI, for 3%, we always get 5 hash functions
    }

    我们可调用BloomFilter的这个方法显式的指定误判率:

    private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), capacity,0.01);

    我们断点跟踪下,误判率为0.02和默认的0.03时候的区别:

    对比两个出错率可以发现,误判率为0.02时数组大小为8142363,0.03时为7298440,误判率降低了0.01,BloomFilter维护的数组大小也减少了843923,可见BloomFilter默认的误判率0.03是设计者权衡系统性能后得出的值。要注意的是,布隆过滤器不支持删除操作。用在这边解决缓存穿透问题就是:

    public String getByKey(String key) {
        // 通过key获取value
        String value = redisService.get(key);
        if (StringUtil.isEmpty(value)) {
            if (bloomFilter.mightContain(key)) {
                value = userService.getById(key);
                redisService.set(key, value);
                return value;
            } else {
                return null;
            }
        }
        return value;
    }

    (三)缓存雪崩问题

    现象:大量key同一时间点失效,同时又有大量请求打进来,导致流量直接打在DB上,造成DB不可用。

    解决方案

    • 设置key永不失效(热点数据);
    • 设置key缓存失效时候尽可能错开;
    • 使用多级缓存机制,比如同时使用redsi和memcache缓存,请求->redis->memcache->db;
    • 购买第三方可靠性高的Redis云服务器;

    books 引申阅读: 使用quartz实现高级定制化定时任务(包含管理界面)

    books 推荐阅读:elastic search搜索引擎实战demo:https://github.com/simonsfan/springboot-quartz-demo,分支:feature_es

    展开全文
  • 清除微信内置浏览器缓存

    万次阅读 2018-08-22 21:19:44
    在做微信开发的时候(主要是微信内网页或者比较大型的手机网站)的时候,更改了页面代码,但是微信内置浏览器有缓存,还是之前的效果,影响调试,而且还死活清除不掉!!!!!怎么办? 我的第一想法是关闭手机的...
  • 缓存穿透,缓存击穿,缓存雪崩解决方案分析

    万次阅读 多人点赞 2017-01-06 11:12:50
    设计一个缓存系统,不得不要考虑的问题就是:缓存穿透、缓存击穿与失效时的雪崩效应。 缓存穿透 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则...
  • 1查询缓存 1.1什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。 mybaits提供一级缓存,和二级缓存。 一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中...
  • 》,今天给大家整理一篇关于Redis经常被问到的问题:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等概念的入门及简单解决方案。 一、缓存雪崩 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未...
  • VUE 缓存 设置缓存 使用缓存

    万次阅读 2019-08-06 18:58:38
    VUE.JS 使用缓存我建议用good-storage ,简单方便好用,下面来看看怎么使用它 good-storage 是一个插件,需要安装 localStorage 临时缓存(主动清除缓存才会销毁) sessionStorage 长期缓存(关闭浏览器自动销毁...
  • 希望:在大数据时代,由于网络请求的并发,导致的数据库I/O开销巨大,所以为了缓解数据库的压力,缓存技术必不可少,而这其中redis基本是服务器的缓存服务之一,虽然缓存技术很好用,但是也会出现各种各样的问题,...
  • Caffeine 缓存

    万次阅读 2017-12-13 17:07:05
    缓存和 Map 之间的一个根本区别在于缓存可以回收存储的 item。 回收策略为在指定时间删除哪些对象。此策略直接影响缓存的命中率 — 缓存库的一个重要特征。 Caffeine 因使用 Window TinyLfu 回收策略,提供了一个...
  • vue点击详情页面keep-alive的缓存问题

    万次阅读 2020-11-02 09:52:51
    今天有个列表 点击以后 进入详情 然后在返回,再点击其他的...这样子对用户体验感是非常不好滴,查了半天资料 发现了activated这个api 解决有些不需要被缓存的组件页面 设置 activated 即可以再次进行事件的响应 ...
  • 缓存穿透,缓存击穿,缓存雪崩

    千次阅读 2019-02-28 13:33:45
    文章目录缓存穿透,缓存击穿,缓存雪崩1、什么是缓存穿透2、如何解决缓存穿透方案一方案二3、什么是缓存击穿4、缓存击穿与缓存雪崩的区别5、如何解决缓存击穿方案一方案二方案三方案四6、什么是缓存雪崩7、如何避免...
  • 缓存在系统中的位置 因为大型系统,其数据库资源比较紧俏,并且数据库的访问速度并发量远不如目前的各种内存缓存系统。所以缓存的主要意义是减少数据库压力,增加访问速度。其位置是建立在数据库层和业务逻辑层之间...
  • 一、缓存使用方式 1、客户端请求业务系统 2、业务系统首先判断redis是否存在数据 3、如果数据存在redis则返回给业务系统 4、业务系统返回给客户端 5、如果redis不存在数据,则业务服务区数据库中查询数据 ...
  • 1.缓存过期 缓存过期:在使用缓存时,可以通过TTL(Time To Live)设置失效时间,当TTL为0时,缓存失效。 为什么要设置缓存的过期时间呢? 一、为了节省内存 例如,在缓存中存放了近3年的10亿条博文数据,但是经常被...
  • 释义:缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。 解决办法: 事前:尽量保证整个 redis 集群的高可用性,发现机器宕机尽快补上。选择合适的内存...
  • 缓存相关的设置 1. <setting name="cacheEnabled" value="false"/> 关闭二级缓存,一级缓存可正常使用 2. <select useCache="false"> 关闭二级缓存,一级缓存可正常使用 3. <select flushCache=...
  • Nginx缓存

    万次阅读 2019-09-22 21:52:44
    缓存文件放在哪儿? 如何指定哪些请求被缓存缓存的有效期是多久? 如何指定哪些请求不被缓存? 1 缓存文件放在哪儿? 配置 $ vim $NGINX_HOME/conf/nginx.conf worker_processes auto; events { use epoll; ...
  • 缓存使用带来的一致性问题 ---- 数据同步,有四类方式 (1)要求高的场景下,使用实时更新策略----- 即数据有变化时,更新的线程直接同步缓存数据 (2)如果允许,可以单独架设第三方方案,来同步缓存数据,常见的...
  • MyBatis缓存

    千次阅读 2019-09-25 10:57:35
    MyBatis提供查询缓存,用于减轻数据库压力,提高性能。MyBatis提供了一级缓存和二级缓存。 一级缓存是SqlSession级别的缓存,每个SqlSession对象都有一个哈希表用于缓存数据,不同SqlSession对象之间缓存不共享。同...
  • 快速了解缓存穿透与缓存雪崩

    千次阅读 多人点赞 2019-07-26 08:00:00
    缓存穿透 缓存系统,一般流程都是按照key去查询缓存,如果不存在对应的value,就去后端系统(例如:持久层数据库)查找。如果key对应的value是一定不存在的,并且对该key并发请求量很大,就会对后端系统造成很大的...
  • http缓存策略之强缓存与协商缓存

    千次阅读 2020-04-11 16:45:25
    因此通过浏览器的缓存机制,协同服务器让浏览器缓存那些不需要频繁变动的资源就可以有效地降低流量消耗和响应时间。 一、什么是http缓存 http缓存指的是:当客户端向服务器请求资源时,会先查...
  • 缓存穿透:缓存中查询不到,然后去查询数据库,数据库中也没有 缓存穿透主要是可能一些恶意的查询,比如查询数据库中-1的主键值这样的数据,但是缓存中肯定没有这样的数据,所以全部查询到了数据库中。这样就是缓存...
  • 我没想到他会这么问
  • QQ技术交流群173683866 526474645 欢迎加入交流讨论,打广告的一律飞机票 使用 WindowsessionStorage 和 localStorage 属性 ...localStorage 缓存在浏览器的数据,只有清空浏览器缓存才会删除这些数据 sessionSt...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 386,401
精华内容 154,560
关键字:

缓存