缓存雪崩:
当缓存服务器重启或者是在某一时间段大量缓存集体失效的时候,高并发请求集体请求后端数据库系统,就会对数据库系统带来很大压力。
解决方案:
1.加锁排队:
加锁排队可以减轻数据库压力,但无法提高系统吞吐量,真正的高并发情况下,假设缓存重建期间key一直是锁着的,后面的请求都在阻塞,会造成大量用户超时等待。
2.随机值缓存。
简单来说就是我们将缓存失效时间分散开,在原有失效时间的基础上增加随机值,这样缓存过期时间的重复率就会大大降低,很难引发集体缓存失效的事件。
class getPrizeList {
/**
* redis实例
* @var \Redis
*/
private $redis;
/**
* @var string
*/
private $redis_key = '|prize_list';
/**
* 缓存标记key
* @var string
*/
private $cash_key = '|prize_list_cash';
/**
* 过期时间
* @var int
*/
private $expire = 30;
/**
* getPrizeList constructor.
* @param $redis
*/
public function __construct($redis)
{
$this->redis = $redis;
}
/**
* @return array|bool|string
*/
public function fetch()
{
$cash_result = $this->redis->get($this->cash_key);
$result = $this->redis->get($this->redis_key);
if(!$cash_result) {
$this->redis->set($this->cash_key, 1, $this->expire);
//此处应该进行数据库查询...
//$result = 数据库查询结果, 并且设置的时间要比cash_key长,这里设置为2倍;
$this->redis->set($this->redis_key, $result, $this->expire * 2);
}
return $result;
}
}
缓存标记:记录缓存数据是否过期,如果过期会触发通知另外的线程在后台去更新实际key的缓存;
缓存数据:它的过期时间比缓存标记的时间延长1倍,例:标记缓存时间30分钟,数据缓存设置为60分钟。这样,当缓存标记key过期后,实际缓存还能把旧数据返回给调用端,直到另外的线程在后台更新完成后,才会返回新缓存。