redis缓存穿透和雪崩和击穿
原创
一、Redis缓存穿透
缓存穿透是指查询一个不存在的数据,由于缓存中没有这个数据,于是向数据库发起查询,数据库也返回不存在,但这样的查询仍然会每次都穿透缓存到达数据库,给数据库带来压力。
二、Redis缓存雪崩
缓存雪崩是指当缓存中大量数据几乎同时过期或者缓存服务宕机,让大量请求到达数据库,从而让数据库压力剧增,甚至让数据库崩溃。
三、Redis缓存击穿
缓存击穿是指某个热点数据过期的瞬间,大量请求到达数据库,让数据库压力瞬间增大。与缓存雪崩的区别在于,缓存击穿只是针对某一个热点数据,而缓存雪崩是大量数据同时过期。
四、解决方案
1. 针对缓存穿透的解决方案:
(1)接口层增多校验:如布隆过滤器,对于一定不存在的数据,在接口层就进行拦截,防止请求到达数据库。
(2)缓存空值:当数据库查询最终为空时,仍然将这个空值缓存起来,设置一个较短的过期时间,避免大量请求穿透缓存到达数据库。
2. 针对缓存雪崩的解决方案:
(1)均匀设置过期时间:避免大量数据同时过期,可以将过期时间设置为随机值或者固定时间加上一个随机数。
(2)使用熔断机制:当缓存服务出现故障时,使用熔断机制,直接返回预设的默认值或者失误信息,避免请求到达数据库。
3. 针对缓存击穿的解决方案:
(1)热点数据不过期或者延长过期时间:针对热点数据,可以设置不过期,或者适当延长过期时间,避免热点数据被频繁查询。
(2)使用互斥锁:当热点数据过期时,只允许一个请求到达数据库,其他请求等待,避免瞬间大量请求到达数据库。
五、示例代码
1. 使用Redis缓存空值:
<?PHP
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$key = 'cache_key';
$value = $redis->get($key);
if ($value) {
echo "Cache hit: " . $value;
} else {
$result = queryDatabase($key);
if ($result) {
$redis->setex($key, 60, $result);
} else {
$redis->setex($key, 60, '');
}
echo "Cache miss: " . $result;
}
?>