zoukankan      html  css  js  c++  java
  • redis缓存穿透、缓存击穿、缓存雪崩原因及解决方案介绍

    一、解释
    1、缓存穿透:key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。
    2、缓存击穿:key对应的数据存在,但在redis中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
    3、缓存雪崩:当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。

    二、解决方案
    1、缓存穿透:
    方案1:常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
    方案2:另外一个更为简单粗暴方法,如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),仍然把空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。
    2、缓存击穿:
    key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题。
    方案1:业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。
    SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。

    方案2:使用key查询缓存只负责查询缓存,不从DB加载,使用定时任务定时刷新缓存,这样两个人任务分离

    方案3:从DB中加载缓存的时候,使用分布式锁,只允许一个线程加载缓存;
    3、缓存雪崩:
    与缓存击穿的区别在于这里针对很多key缓存,前者则是某一个key。
    使用锁或队列、设置过期标志更新缓存、为key设置不同的缓存失效时间、或者使用双缓存策略

    参考:
    https://www.cnblogs.com/xichji/p/11286443.html
    https://blog.csdn.net/aoxida/article/details/118803642

  • 相关阅读:
    C/C++数组名与指针区别深入探索(转)
    mysql 的编译安装
    rpm的问题 ~/.rpmmacros %_rpmlock_path
    GCC中的弱符号与强符号(转)
    关于printf系列函数
    如何修改机器名
    multiple definition of XXXX 的解决
    由无名对象(临时对象)引发的关于“引用”的思考
    关于date中时间字符串的格式
    月薪不同,面试题不同!
  • 原文地址:https://www.cnblogs.com/InternetJava/p/15731272.html
Copyright © 2011-2022 走看看