推荐(免费):redis
缓存穿透:键中对应的缓存数据不存在,导致请求数据库造成数据库的双重压力。
缓存崩溃:redis过期后的瞬间,大量用户请求相同的缓存数据,导致所有这些请求都请求数据库,给数据库带来了双倍的压力。为了一把钥匙,
(资料图片仅供参考)
缓存雪崩:缓存服务器宕机或大量缓存集在一定时间内失效,导致所有请求都去数据库,数据库压力翻倍的情况。这是多把钥匙。
一、缓存穿透的解决方案
常用的方法可以使用布隆过滤器拦截数据。其次,还有一个解决方案,就是如果请求的数据为空,缓存空值,不会有穿透?服务器端编程语言(Professional Hypertext Preprocessor的缩写)
类getPrizeList {
/**
* redis实例
* @var \Redis
*/
私有$ redis
/**
* @var字符串
*/
private $ redis _ key=" | prize _ list ";
/**
*到期时间
* @var int
*/
private $ expire=30
/**
* getPrizeList构造函数。
* @param $redis
*/
公共函数__construct($redis)
{
$ this-redis=$ redis;
}
/**
* @返回数组| bool |字符串
*/
公共函数提取
{
$ result=$ this-redis-get($ this-redis _ key);
if(!isset($ result)){ 0
//应该在这里进行数据库查询。
//如果查询结果不存在,缓存其默认的空数组。
$ result=[];
$ this-redis-set($ this-redis _ key,$result,$ this-expire);
}
返回$ result
}
}二、缓存崩溃的解决方案
使用互斥键,即当一个键过期时,多个请求来允许一个请求操作数据库,其他请求等待第一个请求成功返回结果后再请求。服务器端编程语言(Professional Hypertext Preprocessor的缩写)
类getPrizeList {
/**
* redis实例
* @var \Redis
*/
私有$ redis
/**
* @var字符串
*/
private $ redis _ key=" | prize _ list ";
/**
* @var字符串
*/
private $ setnx _ key=" | prize _ list _ setnx ";
/**
*到期时间
* @var int
*/
private $ expire=30
/**
* getPrizeList构造函数。
* @param $redis
*/
公共函数__construct($redis)
{
$ this-redis=$ redis;
}
/**
* @返回数组| bool |字符串
*/
公共函数提取
{
$ result=$ this-redis-get($ this-redis _ key);
if(!isset($ result)){ 0
if($ this-redis-setnx($ this-setnx _ key,1,$ this-expire)){ 0
//应该在这里进行数据库查询。
//$result=数据库查询结果;
$ this-redis-set($ this-redis _ key,$result,$ this-expire);
$ this-redis-del($ this-setnx _ key);//删除互斥体
} else {
//其他请求每10毫秒重新请求一次。
睡眠(10);
self:fetch
}
}
返回$ result
}
}三、缓存雪崩的解决方案
这种情况是由于多个密钥同时过期造成的数据库压力。一种方法可以在密钥到期时间的基础上增加随机次数,以扩展到期时间,降低缓存时间到期的重复率。另一种方法是锁定和排队,有点像上面的缓存崩溃的解决方案。然而,请求的数量太大,例如5,000个请求到来,4,999个请求等待。这势必是一个永久性的问题,不仅用户体验差,在分布式环境下更是雪上加霜。因此,复杂性很少用于高并发场景。最好的解决方案是使用缓存标签来确定标签是否过期,然后请求数据库,缓存数据的过期时间应该设置得比缓存标签的过期时间长。所以当一个请求操作数据库时,其他请求会获取最后一个缓存的数据?服务器端编程语言(Professional Hypertext Preprocessor的缩写)
类getPrizeList {
/**
* redis实例
* @var \Redis
*/
私有$ redis
/**
* @var字符串
*/
private $ redis _ key=" | prize _ list ";
/**
*缓存标签密钥
* @var字符串
*/
private $ cash _ key=" | prize _ list _ cash ";
/**
*到期时间
* @var int
*/
private $ expire=30
/**
* getPrizeList构造函数。
* @param $redis
*/
公共函数__construct($redis)
{
$ this-redis=$ redis;
}
/**
* @返回数组| bool |字符串
*/
公共函数提取
{
$ cash _ result=$ this-redis-get($ this-cash _ key);
$ result=$ this-redis-get($ this-redis _ key);
if(!$ cash _ result){ 0
$this-redis-set($this-cash_key,1,$ this-expire);
//应该在这里进行数据库查询。
//$result=数据库查询结果,设置时间比cash_key长,这里设置为2倍;
$ this-redis-set($ this-redis _ key,$result,$ this-expire * 2);
}
返回$ result
}
}以上就是一起学习Redis缓存穿透、缓存击穿、缓存雪崩的原理和解决方案的详细内容!
来源:php中文网站