• 缓存穿透、缓存雪崩、缓存击穿问题及其解决方案


    今天想起之前面试的时候问我缓存击穿问题及其解决方案,当时还并没有接触到缓存知识,啥也没答出来,回去后查了一下,也没有记录下来,现在就这个问题好好总结一下吧!
    1.缓存处理流程
    以laravel框架开发的项目为例,客户端请求数据,控制器接收用户请求调用模型查询用户所需的数据返回给客户端,业务逻辑非常简单,但是当成千上万的客户频繁的请求数据呢?那样系统会变得很慢,客户的请求长时间得不到回应,这时候就要使用缓存技术了,这样业务逻辑就变成了前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果。
    2.缓存穿透
    缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起id为负数或者不存在的很大的数值,这样会给数据库带来很大压力。
    解决方案:(1)对用户的输入数据进行校验,如id的值只能是正整数,对于id<=0的数直接拦截,使用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一定不存在的数据会被拦截掉
    (2)如果一个查询返回的为空,仍然将这个空结果存入到缓存中,但是它的过期时间非常的短,最长不会超过5分钟。这样可以防止攻击者反复用同一个id暴力攻击。
    3.缓存雪崩
    缓存雪崩是指在设置缓存的时候采用了相同的过期时间,导致大量的数据在某一时间同时过期,用户的请求全部转向数据库,数据库压力瞬间增大导致雪崩
    解决方案:(1)用加锁或者队列来保证缓存的单线程
    (2)在设置失效时间的基础上增加随机值如1-5分钟,这样可以使得过期时间的重复率降低
    4.缓存击穿
    对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一key缓存,前者则是很多key。
    缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
    解决方案:(1)使用互斥锁
    在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。
    代码实现如下:
    public String get(key) {
    String value = redis.get(key);
    if (value == null) { //代表缓存值过期
    //设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
    if (redis.setnx(key_mutex, 1, 3 * 60) == 1) { //代表设置成功
    value = db.get(key);
    redis.set(key, value, expire_secs);
    redis.del(key_mutex);
    } else { //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
    sleep(50);
    get(key); //重试
    } } else {
    return value;
    }
    }

    就是在第一次查询缓存不存在的情况下先查询数据库,之后回设缓存,当再次请求时就可以读取到缓存中的数据
    (2)设置热点信息永不过期

  • 相关阅读:
    生成文件的MD5文件
    磁场动 电子不动, 有 洛伦兹力 吗 ?
    牛顿水桶 的 水面凹陷 和 变轻 就是 个 离心力, 大家 这么 慌乱 干什么 ?
    《【竞价】宏观微观统一量子化波动方程》 回复
    一些有意义的课题 : 氢原子光谱 氢原子电子云 小孔衍射 双缝干涉
    调和级数 和 双盲测试
    webrtc降噪原理
    关于浏览器显示的图片点击下载
    Windows 下如何添加和删除服务
    领域驱动设计知识语境、限界上下文、领域
  • 原文地址:https://www.cnblogs.com/pcblogs/p/12967104.html
Copyright © 2020-2023  润新知