推薦(免費):redis
快取穿透:key中對應的快取資料不存在,導致去請求資料庫,造成資料庫的壓力倍增的情況
快取擊穿:redis過期後的一瞬間,有大量使用者請求同一個快取數據,導致這些請求都去請求資料庫,造成資料庫壓力倍增的情,針對一個key而言
##快取雪崩:快取伺服器宕機或大量快取集中某個時間段失效,導致請求全部去到資料庫,造成資料庫壓力倍增的情況,這個是針對多個key而言
一、快取穿透的解決方案
<?php class getPrizeList { /** * redis实例 * @var \Redis */ private $redis; /** * @var string */ private $redis_key = '|prize_list'; /** * 过期时间 * @var int */ private $expire = 30; /** * getPrizeList constructor. * @param $redis */ public function __construct($redis) { $this->redis = $redis; } /** * @return array|bool|string */ public function fetch() { $result = $this->redis->get($this->redis_key); if(!isset($result)) { //此处应该进行数据库查询... //如果查询结果不存在,给其默认空数组进行缓存 $result = []; $this->redis->set($this->redis_key, $result, $this->expire); } return $result; } }
二、快取擊穿解決方法
<?php class getPrizeList { /** * redis实例 * @var \Redis */ private $redis; /** * @var string */ private $redis_key = '|prize_list'; /** * @var string */ private $setnx_key = '|prize_list_setnx'; /** * 过期时间 * @var int */ private $expire = 30; /** * getPrizeList constructor. * @param $redis */ public function __construct($redis) { $this->redis = $redis; } /** * @return array|bool|string */ public function fetch() { $result = $this->redis->get($this->redis_key); if(!isset($result)) { if($this->redis->setnx($this->setnx_key, 1, $this->expire)) { //此处应该进行数据库查询... //$result = 数据库查询结果; $this->redis->set($this->redis_key, $result, $this->expire); $this->redis->del($this->setnx_key); //删除互斥锁 } else { //其他请求每等待10毫秒重新请求一次 sleep(10); self::fetch(); } } return $result; } }
三、快取雪崩的解決方法
<?php 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; } }
以上是一起學習 Redis快取穿透、快取擊穿、快取雪崩的原理和解決方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!