快取擊穿是開發中可能會遇到的問題:
快取擊穿是指快取中沒有但資料庫中有的資料(一般是快取時間到期),這時由於併發使用者特別多,同時讀快取沒讀到資料,又同時去資料庫去取資料,引起資料庫壓力瞬間增大,造成過大壓力
Redis鎖是解決快取擊穿問題的一個很好的辦法。
Laravel 7 中自帶有 \Illuminate\Cache\RedisLock
Redis鎖類,直接使用就行,用起來也很方便。
RedisLock
的建構函式如下:
/**
* @param \Illuminate\Redis\Connections\Connection $redis redis例項
* @param string $name redis鎖的鍵名
* @param int $seconds redis鎖的失效時間
* @param string|null $owner redis鎖的值,如果不設定或者為null,基類會將其設定為隨機字串
*/
public function __construct($redis, $name, $seconds, $owner = null)
{
parent::__construct($name, $seconds, $owner);
$this->redis = $redis;
}
在這個類中,使用 acquire()
方法獲得互斥的Redis鎖,使用 release()
方法釋放鎖。
使用示例:
use Illuminate\Cache\RedisLock;
function RedisLockTest()
{
//獲取redis例項
$redis = Redis::connection();
$key = 'redis_test_key';
//獲取redis鎖例項
$redisLock = new RedisLock($redis, $key . '_lock', 30);
$res = $redis->get($key);
if (empty($res)) {
//拿到互斥鎖
if ($redisLock->acquire()) {
//模擬從資料庫中獲取資料的過程
sleep(5);
$value = date('Y-m-d H:i:s');
//更新快取,過期時間可以根據實際情況調整
$redis->setex($key, 60, $value);
//釋放鎖
$redisLock->release();
return $value;
//未拿到互斥鎖
} else {
//等待2秒,然後重新獲取快取值,讓其他獲取到鎖的程式取得資料並設定快取,等待時間可以根據實際情況調整
sleep(2);
return $this->getArticleInCache();
}
} else {
return $res;
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結