新闻中心

记录团队成长点滴以及对技术、理念的探索,同时我们乐于分享!

Redis缓存击穿的原因以及解决方案

2020-09-21 09:46:56 分类:技术学堂

原因描述–缓存击穿

缓存击穿跟缓存雪崩有些类似,雪崩是大面积缓存失效,导致数据库崩溃,而缓存击穿是一个 key 是热点,不停地扛住大并发请求,全都集中访问此 key, 而当此 key 过期瞬间,持续的大并发就击穿缓存,全都打在 DB 上。就又引发雪崩的问题。


解决方法–缓存击穿

方法一:把这个热点 key 设置为永久有效。


方法二:使用互斥锁,这是比较常用的方法,简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去查询数据库,而是先使用缓存工具的某些带成功操作返回值的操作(比如 Redis 的 SETNX 或者 Memcache 的 ADD)去 set 一个 mutex key,当操作返回成功时,再进行查询数据库的操作并回设缓存;否则,就重试整个 get 缓存的方法。


互斥代码:


function get($key){

    $value = $redis->get($key);

    if($value == null){

        //不存在,设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能查询数据库

        if ($redis->setnx("key_mutex", 1, 3 * 60) == 1){

            $value = "";//这是查询数据库文件

            $redis->set(key, value, expire_secs);

            $redis->del(key_mutex);

        }else{

            //这个时候代表同时候的其他线程已经查询数据库并回设到缓存了,这时候重试获取缓存值即可

            sleep(50);

            get(key);  //重试

        }

    }else{

        //存在则直接返回

        return $value;

    }

}