精华内容
下载资源
问答
  • 面试中缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级怎么解答 面试中缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级怎么解答 面试中缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级怎么解答
  • 》,今天给大家整理一篇关于Redis经常被问到的问题:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等概念的入门及简单解决方案。 一、缓存雪崩 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未...

    前面一节说到了《为什么说Redis是单线程的以及Redis为什么这么快!》,今天给大家整理一篇关于Redis经常被问到的问题:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等概念的入门及简单解决方案。

    一、缓存雪崩

    缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。

    缓存正常从Redis中获取,示意图如下:

    这里写图片描述

    缓存失效瞬间示意图如下:

    这里写图片描述

    缓存失效时的雪崩效应对底层系统的冲击非常可怕!大多数系统设计者考虑用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。还有一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

    以下简单介绍两种实现方式的伪代码:

    (1)碰到这种情况,一般并发量不是特别多的时候,使用最多的解决方案是加锁排队,伪代码如下:

    //伪代码
    public object GetProductListNew() {
        int cacheTime = 30;
        String cacheKey = "product_list";
        String lockKey = cacheKey;
    
        String cacheValue = CacheHelper.get(cacheKey);
        if (cacheValue != null) {
            return cacheValue;
        } else {
            synchronized(lockKey) {
                cacheValue = CacheHelper.get(cacheKey);
                if (cacheValue != null) {
                    return cacheValue;
                } else {
    	            //这里一般是sql查询数据
                    cacheValue = GetProductListFromDB(); 
                    CacheHelper.Add(cacheKey, cacheValue, cacheTime);
                }
            }
            return cacheValue;
        }
    }
    

    加锁排队只是为了减轻数据库的压力,并没有提高系统吞吐量。假设在高并发下,缓存重建期间key是锁着的,这是过来1000个请求999个都在阻塞的。同样会导致用户等待超时,这是个治标不治本的方法!

    注意:加锁排队的解决方式分布式环境的并发问题,有可能还要解决分布式锁的问题;线程还会被阻塞,用户体验很差!因此,在真正的高并发场景下很少使用!

    (2)还有一个解决办法解决方案是:给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存,实例伪代码如下:

    //伪代码
    public object GetProductListNew() {
        int cacheTime = 30;
        String cacheKey = "product_list";
        //缓存标记
        String cacheSign = cacheKey + "_sign";
    
        String sign = CacheHelper.Get(cacheSign);
        //获取缓存值
        String cacheValue = CacheHelper.Get(cacheKey);
        if (sign != null) {
            return cacheValue; //未过期,直接返回
        } else {
            CacheHelper.Add(cacheSign, "1", cacheTime);
            ThreadPool.QueueUserWorkItem((arg) -> {
    			//这里一般是 sql查询数据
                cacheValue = GetProductListFromDB(); 
    	        //日期设缓存时间的2倍,用于脏读
    	        CacheHelper.Add(cacheKey, cacheValue, cacheTime * 2);                 
            });
            return cacheValue;
        }
    } 
    

    解释说明:

    1、缓存标记:记录缓存数据是否过期,如果过期会触发通知另外的线程在后台去更新实际key的缓存;

    2、缓存数据:它的过期时间比缓存标记的时间延长1倍,例:标记缓存时间30分钟,数据缓存设置为60分钟。 这样,当缓存标记key过期后,实际缓存还能把旧数据返回给调用端,直到另外的线程在后台更新完成后,才会返回新缓存。

    关于缓存崩溃的解决方法,这里提出了三种方案:使用锁或队列、设置过期标志更新缓存、为key设置不同的缓存失效时间,还有一各被称为“二级缓存”的解决方法,有兴趣的读者可以自行研究。

    二、缓存穿透

    缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。

    有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。

    另外也有一个更为简单粗暴的方法,如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。通过这个直接设置的默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库,这种办法最简单粗暴!

    //伪代码
    public object GetProductListNew() {
        int cacheTime = 30;
        String cacheKey = "product_list";
    
        String cacheValue = CacheHelper.Get(cacheKey);
        if (cacheValue != null) {
            return cacheValue;
        }
    
        cacheValue = CacheHelper.Get(cacheKey);
        if (cacheValue != null) {
            return cacheValue;
        } else {
            //数据库查询不到,为空
            cacheValue = GetProductListFromDB();
            if (cacheValue == null) {
                //如果发现为空,设置个默认值,也缓存起来
                cacheValue = string.Empty;
            }
            CacheHelper.Add(cacheKey, cacheValue, cacheTime);
            return cacheValue;
        }
    }
    

    把空结果,也给缓存起来,这样下次同样的请求就可以直接返回空了,即可以避免当查询的值为空时引起的缓存穿透。同时也可以单独设置个缓存区域存储空值,对要查询的key进行预先校验,然后再放行给后面的正常缓存处理逻辑。

    三、缓存预热

    缓存预热这个应该是一个比较常见的概念,相信很多小伙伴都应该可以很容易的理解,缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!

    解决思路:

    1、直接写个缓存刷新页面,上线时手工操作下;

    2、数据量不大,可以在项目启动的时候自动进行加载;

    3、定时刷新缓存;

    四、缓存更新

    除了缓存服务器自带的缓存失效策略之外(Redis默认的有6中策略可供选择),我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种:

    (1)定时去清理过期的缓存;

    (2)当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。

    两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂!具体用哪种方案,大家可以根据自己的应用场景来权衡。

    五、缓存降级

    当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。

    降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。

    在进行降级之前要对系统进行梳理,看看系统是不是可以丢卒保帅;从而梳理出哪些必须誓死保护,哪些可降级;比如可以参考日志级别设置预案:

    (1)一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级;

    (2)警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级,并发送告警;

    (3)错误:比如可用率低于90%,或者数据库连接池被打爆了,或者访问量突然猛增到系统能承受的最大阀值,此时可以根据情况自动降级或者人工降级;

    (4)严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级。

    六、总结

    这些都是实际项目中,可能碰到的一些问题,也是面试的时候经常会被问到的知识点,实际上还有很多很多各种各样的问题,文中的解决方案,也不可能满足所有的场景,相对来说只是对该问题的入门解决方法。一般正式的业务场景往往要复杂的多,应用场景不同,方法和解决方案也不同,由于上述方案,考虑的问题并不是很全面,因此并不适用于正式的项目开发,但是可以作为概念理解入门,具体解决方案要根据实际情况来确定!


    参考文章:

    1、http://www.cnblogs.com/zhangweizhong/p/6258797.html
    2、http://www.cnblogs.com/zhangweizhong/p/5884761.html
    3、http://blog.csdn.net/zeb_perfect/article/details/54135506

    在这里插入图片描述

    【视频福利】2T免费学习视频,搜索或扫描上述二维码关注微信公众号:Java后端技术(ID: JavaITWork)回复:1024,即可免费获取!内含SSM、Spring全家桶、微服务、MySQL、MyCat、集群、分布式、中间件、Linux、网络、多线程,Jenkins、Nexus、Docker、ELK等等免费学习视频,持续更新!

    展开全文
  • 今天给大家整理一篇关于Redis经常被问到的问题:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等概念的入门及简单解决方案。 一、缓存雪崩 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间...

    今天给大家整理一篇关于Redis经常被问到的问题:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等概念的入门及简单解决方案。

    一、缓存雪崩


    缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。

    缓存正常从Redis中获取,示意图如下:

    在这里插入图片描述

    缓存失效瞬间示意图如下:

    在这里插入图片描述

    缓存失效时的雪崩效应对底层系统的冲击非常可怕!大多数系统设计者考虑用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。还有一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

    以下简单介绍两种实现方式的伪代码:

    (1)碰到这种情况,一般并发量不是特别多的时候,使用最多的解决方案是加锁排队,伪代码如下:

    在这里插入图片描述
    加锁排队只是为了减轻数据库的压力,并没有提高系统吞吐量。假设在高并发下,缓存重建期间key是锁着的,这是过来1000个请求999个都在阻塞的。同样会导致用户等待超时,这是个治标不治本的方法!

    注意:加锁排队的解决方式分布式环境的并发问题,有可能还要解决分布式锁的问题;线程还会被阻塞,用户体验很差!因此,在真正的高并发场景下很少使用!

    (2)还有一个解决办法解决方案是:给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存,实例伪代码如下:

    在这里插入图片描述
    解释说明:

    1、缓存标记:记录缓存数据是否过期,如果过期会触发通知另外的线程在后台去更新实际key的缓存;

    2、缓存数据:它的过期时间比缓存标记的时间延长1倍,例:标记缓存时间30分钟,数据缓存设置为60分钟。 这样,当缓存标记key过期后,实际缓存还能把旧数据返回给调用端,直到另外的线程在后台更新完成后,才会返回新缓存。

    关于缓存崩溃的解决方法,这里提出了三种方案:使用锁或队列、设置过期标志更新缓存、为key设置不同的缓存失效时间,还有一各被称为“二级缓存”的解决方法,有兴趣的读者可以自行研究。

    二、缓存穿透


    缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。

    有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。

    另外也有一个更为简单粗暴的方法,如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。通过这个直接设置的默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库,这种办法最简单粗暴!

    在这里插入图片描述
    把空结果,也给缓存起来,这样下次同样的请求就可以直接返回空了,即可以避免当查询的值为空时引起的缓存穿透。同时也可以单独设置个缓存区域存储空值,对要查询的key进行预先校验,然后再放行给后面的正常缓存处理逻辑。

    三、缓存预热


    缓存预热这个应该是一个比较常见的概念,相信很多小伙伴都应该可以很容易的理解,缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!

    解决思路:

    1、直接写个缓存刷新页面,上线时手工操作下;

    2、数据量不大,可以在项目启动的时候自动进行加载;

    3、定时刷新缓存;

    四、缓存更新


    除了缓存服务器自带的缓存失效策略之外(Redis默认的有6中策略可供选择),我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种:

    (1)定时去清理过期的缓存;

    (2)当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。

    两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂!具体用哪种方案,大家可以根据自己的应用场景来权衡。

    五、缓存降级


    当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。

    降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。

    在进行降级之前要对系统进行梳理,看看系统是不是可以丢卒保帅;从而梳理出哪些必须誓死保护,哪些可降级;比如可以参考日志级别设置预案:

    (1)一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级;

    (2)警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级,并发送告警;

    (3)错误:比如可用率低于90%,或者数据库连接池被打爆了,或者访问量突然猛增到系统能承受的最大阀值,此时可以根据情况自动降级或者人工降级;

    (4)严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级。

    六、总结


    这些都是实际项目中,可能碰到的一些问题,也是面试的时候经常会被问到的知识点,实际上还有很多很多各种各样的问题,文中的解决方案,也不可能满足所有的场景,相对来说只是对该问题的入门解决方法。一般正式的业务场景往往要复杂的多,应用场景不同,方法和解决方案也不同,由于上述方案,考虑的问题并不是很全面,因此并不适用于正式的项目开发,但是可以作为概念理解入门,具体解决方案要根据实际情况来确定!

    展开全文
  • Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间 件。 它支持多种类型的数据结构,如字符串(String),散列(Hash),列表(List),集合 (Set),有序集合(Sorted Set...

    Redis简介:
    Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间件。 它支持多种类型的数据结构,如字符串(String),散列(Hash),列表(List),集合(Set),有序集合(Sorted Set或者是ZSet)与范围查询,Bitmaps,Hyperloglogs 和地理空间(Geospatial)索引半径查询。其中常见的数据结构类型有:String、List、Set、Hash、ZSet这5种。
    Redis 内置了复制(Replication),LUA脚本(Lua scripting), LRU驱动事件(LRUeviction),事务(Transactions) 和不同级别的磁盘持久化(Persistence),并通过Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性(High Availability)。
    Redis也提供了持久化的选项,这些选项可以让用户将自己的数据保存到磁盘上面进行存储。根据实际情况,可以每隔一定时间将数据集导出到磁盘(快照),或者追加到命令日志中(AOF只追加文件),他会在执行写命令时,将被执行的写命令复制到硬盘里面。您也可以关闭持久化功能,将Redis作为一个高效的网络的缓存数据功能使用。
    Redis不使用表,他的数据库不会预定义或者强制去要求用户对Redis存储的不同数据进行关联。
    数据库的工作模式按存储方式可分为:硬盘数据库和内存数据库。Redis 将数据储存在内存里面,读写数据的时候都不会受到硬盘 I/O 速度的限制,所以速度极快。

    为什么使用redis:

    (一)性能
    	我们在碰到需要执行耗时特别久,且结果不频繁变动的SQL,就特
    别适合将运行结果放入缓存。这样,后面的请求就去缓存中读取,使得请求能够迅速响应。
    	
    (二)并发
    	在大并发的情况下,所有的请求直接访问数据库,数据库会出现连
    接异常。这个时候,就需要使用redis做一个缓冲操作,让请求先访问到redis,
    而不是直接访问数据库。
    

    Redis为什么这么快:

    1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速,						
    数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;
    3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致
    的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出
    现死锁而导致的性能消耗;
    4、使用多路I/O复用模型,非阻塞IO5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,
    Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去
    移动和请求;
    以上几点都比较好理解,下边我们针对多路 I/O 复用模型进行简单的探讨:
    (1)多路 I/O 复用模型
    多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在
    空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤
    醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只
    依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。
    这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用
    技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis
    在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,
    主要由以上几点造就了 Redis 具有很高的吞吐量。
    五、那么为什么Redis是单线程的
    我们首先要明白,上边的种种分析,都是为了营造一个Redis很快的氛围!官方FAQ表示,
    因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的
    大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单
    线程的方案了(毕竟采用多线程会有很多麻烦!)。
    

    一、缓存雪崩
    缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。

    二、缓存穿透
    缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。
    有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
    另外也有一个更为简单粗暴的方法,如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。通过这个直接设置的默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库,这种办法最简单粗暴!

    三、缓存预热
    缓存预热这个应该是一个比较常见的概念,相信很多小伙伴都应该可以很容易的理解,缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!
    解决思路:
    1、直接写个缓存刷新页面,上线时手工操作下;
    2、数据量不大,可以在项目启动的时候自动进行加载;
    3、定时刷新缓存;

    四、缓存更新
    除了缓存服务器自带的缓存失效策略之外(Redis默认的有6中策略可供选择),我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种:
    (1)定时去清理过期的缓存;
    (2)当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。
    两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂!具体用哪种方案,大家可以根据自己的应用场景来权衡。

    五、缓存降级
    当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。
    降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。
    在进行降级之前要对系统进行梳理,看看系统是不是可以丢卒保帅;从而梳理出哪些必须誓死保护,哪些可降级;比如可以参考日志级别设置预案:
    (1)一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级;
    (2)警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级,并发送告警;
    (3)错误:比如可用率低于90%,或者数据库连接池被打爆了,或者访问量突然猛增到系统能承受的最大阀值,此时可以根据情况自动降级或者人工降级;
    (4)严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级。

    展开全文
  • 缓存雪崩 我们可以简单的理解为:由于原有缓存失效,新缓存还没有存入到redis的期间 比方说:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期,所有原本应该访问缓存的请求都去查询数据库了,...

    缓存雪崩
    我们可以简单的理解为:由于原有缓存失效,新缓存还没有存入到redis的期间
    比方说:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期,所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。
    解决办法:加最多的解决方案就是锁,或者队列的方式来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。还有一个简单方案就是缓存失效时间分散开,不设置固定的实效时间,采用随机失效的策略来解决
    缓存穿透:
    是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空,这就相当于进行了两次无用的查询。像这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题
    解决办法
    最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。另外也有一个更为简单粗暴的方法,如果一个查询返回的数据为空,不管是数据不存在,还是系统故障,我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。
    缓存预热:
    缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!
    操作方式:
    1、直接写个缓存刷新页面,上线时手工操作下;
    2、数据量不大,可以在项目启动的时候自动进行加载;
    然后就是缓存更新:
    1、定时去清理过期的缓存;
    2.、当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存
    缓存降级:
    当访问量剧增、服务出现问题,比如响应时间慢或不响应,或者非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有问题的服务。redis可以帮助系统实现数据降级载体,系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。降级的最终目的是保证核心服务可用,即使是有损的

    展开全文
  • 一、缓存使用流程 时间 事件 T1 客户端发起请求 T2 后台接收请求,先去缓存中取数据,如果取到数据直接返回数据,请求结束,如果没有取到数据,执行T3 T3 从数据库中取数据,如果取到数据更新...
  • 三、缓存预热解决思路:四、缓存更新解决思路:五、缓存降级 缓存雪崩 由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期 时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的...
  • 什么时候需要缓存降级? 当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以...
  • 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和...
  • 关于Redis经常被问到的问题:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级、缓存热点 key等概念的入门及简单解决方案。 一、缓存雪崩 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如...
  • 一、缓存雪崩 1、概念 缓存同一时间实效(由于设置相同的缓存时间),同时访问数据库,从而对数据库cpu和内存造成巨大压力,严重的会导致数据库宕机,从而形成一系列连锁反应,造成整个系统崩溃。 2、解决方案 A...
  • 一、缓存处理流程 前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果。 二、缓存穿透 描述: 缓存穿透是指...
  • 缓存 - 缓存降级

    2021-02-10 11:22:54
    在大促或者某些特殊情况下,某些页面占用了一些稀缺服务资源,在紧急情况下可以对其整个降级,以达到丢卒保帅; 页面片段降级 比如商品详情页中的商家部分因为数据错误了,此时需要对其进行降级; 页面异步请求...
  • 缓存穿透 缓存雪崩 环迅预热 缓存降级
  • Redis之缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级 1、缓存雪崩 发生场景:当Redis服务器重启或者大量缓存在同一时期失效时,此时大量的流量会全部冲击到数据库上面,数据库有可能会因为承受不住而宕机 ...
  • Redis缓存雪崩和缓存穿透、缓存预热、缓存降级 缓存雪崩 大量的key同时失效 由于原有缓存失效,新缓存还没有存入到redis的期间 比方说:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期,所有...
  • 缓存降级是指当访问量剧增、服务出现问题(比如响应时间慢或者不响应)或者非核心服务影响到核心流程的性能时,即使是有损部分其他服务,仍然需要保证主服务可用,可以将其他次要访问的数据进行缓存降级,从而提升主...
  • 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和...
  • 读多写少缓存 读少写多队列 雪崩(获取车次有没有票) 限流 rearrentlock 1.redis获取 2.没命中加锁 3.再次确认缓存是否命中 4.然后在取db放入redis返回 5.最后释放锁 缺点粒度小 concurrenthashmap<String,...
  • 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和...
  • 一、缓存雪崩: 1、什么是缓存雪崩: 如果缓在某一个时刻出现大规模的key失效,那么就会导致大量的请求打在了数据库上面,导致数据库压力巨大,如果在高并发的情况下,可能瞬间就会导致数据库宕机。这时候如果运维...
  • 什么是缓存雪崩,缓存穿透,缓存预热,缓存更新,缓存降级?一、缓存雪崩:二、缓存穿透三、缓存预热四、缓存更新五、缓存降级 一、缓存雪崩: 由于原有缓存失效,新缓存未到期间(例如我们设置缓存采用了一样的过期...
  • 关于Redis经常被问到的问题:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级、缓存热点 key等概念的入门及简单解决方案。 一、缓存雪崩 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如...
  • 分布式缓存问题:Redis 的缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等概念一、缓存雪崩缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在...
  • 缓存预热 缓存预热,是指系统上线后,先将数据加载到缓存系统,手动或定时刷新。 缓存更新 缓存更新,是指根据需要定期或...缓存降级,是为保证核心服务可用,使部分关键数据自动降级,同时也可避免缓存雪崩。 ...
  • 一、缓存预热: 缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样避免,用户请求的时候,再去加载相关的数据。 解决方法: 1、直接写一个缓存刷新页面,上线时手工操作下。 2、数据量不大,可以...
  •  缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。 二.缓存雪崩:  如果缓存集中在...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 49,904
精华内容 19,961
关键字:

缓存降级