避免掉入 SETNX(SET if Not eXists) 陷阱的最好方法就是永遠不要使用它:
setnx lock "lock"
expire lock 100
del lock
場景:某個查詢資料庫的介面,因為呼叫量比較大,所以加了快取,並設定快取過期後重新整理.
問題是當併發量比較大的時候,如果沒有鎖機制,那麼快取過期的瞬間,大量併發請求會穿透快取直接查詢資料庫,造成雪崩效應. 如果有鎖機制,那麼就可以控制只有一個請求去更新快取,其它的請求視情況要麼等待,要麼使用過期的快取.
$key = "cache_update_lock"; //鎖
$random = md5( uniqid(getmypid()."_".mt_rand()."_", true) ); //隨機值
$ttl = 10; //nx表示not exists,ex表示expire,ttl表示time to live,單位是秒.
if( $redis->set($key, $random, ["nx", "ex" => $ttl]) ) {
$cache->update(); //加鎖後執行業務邏輯,這裡是更新快取
if($redis->get($key) == $random) {
$redis->del($key);
}
避免掉入 SETNX(SET if Not eXists) 陷阱的最好方法就是永遠不要使用它:
setnx lock "lock"
expire lock 100
del lock
場景:某個查詢資料庫的介面,因為呼叫量比較大,所以加了快取,並設定快取過期後重新整理.
問題是當併發量比較大的時候,如果沒有鎖機制,那麼快取過期的瞬間,大量併發請求會穿透快取直接查詢資料庫,造成雪崩效應. 如果有鎖機制,那麼就可以控制只有一個請求去更新快取,其它的請求視情況要麼等待,要麼使用過期的快取.
$key = "cache_update_lock"; //鎖
$random = md5( uniqid(getmypid()."_".mt_rand()."_", true) ); //隨機值
$ttl = 10; //nx表示not exists,ex表示expire,ttl表示time to live,單位是秒.
if( $redis->set($key, $random, ["nx", "ex" => $ttl]) ) {
$cache->update(); //加鎖後執行業務邏輯,這裡是更新快取
if($redis->get($key) == $random) {
$redis->del($key);
}
}