快取驚群現象,在各種快取中都會存在這種現象,這裡以redis為例,提供一種解決思路,留作參考~
首先,所謂的快取過期引起的「驚群」現象是指,在大併發情況下,我們通常會用快取來給資料庫分壓,但是會有這麼一種情況發生,那就是當乙個快取資料失效之後會導致同時有多個併發執行緒去向後端資料庫發起請求去獲取同乙個資料,這樣如果在一段時間內同時生成了大量的快取,然後在另外一段時間內又有大量的快取失效,這樣就會導致後端資料庫的壓力突然增大,這種現象就可以稱為「快取過期產生的驚群現象」!
以下**的思路,就是利用「鎖機制」來防止驚群現象。先看**:
class komaredis
$this->redis = new redis();
$this->redis->connect($config['server'], $config['port']);
return $this->redis;
}/**
* @param array $config
* @return redis操作類物件
*/public static function getinstance($config = array())
return self::$_instance;
}/**
* 獲取快取
* @param $key string $name
* @return array,object,number,string,boolean
* @desc 此方法使用了鎖機制來防止防止快取過期時所產生的驚群現象,保證只有乙個程序不獲取資料,可以更新,其他程序仍然獲取過期資料
*/public function getbylock($key)
else else
} else }}
/*** 設定快取
* @param $key string $name 快取鍵
* @param $value $string ,array,object,number,boolean $value 快取值
* @param null $ttl $string ,number $ttl 過期時間,如果不設定,則使用預設時間,如果為 infinity 則為永久儲存
* @return bool
* @desc 此方法儲存的資料會自動加入一些其他資料來避免驚群現象,如需儲存原始資料,請使用 set
*/public function setbylock($key, $value, $ttl = null)
else
empty($ttl) or $ttl += 300; //增加redis快取時間,使程式有足夠的時間生成快取
$arg = array("data" => $value, "expire" => $exp);
$rs = $this->redis->setex($key, $ttl, json_encode($arg, true));
$this->redis->del($key . ".lock");
return $rs;
}/**
* 返回redis物件
* redis有非常多的操作方法,我們只封裝了一部分
* 拿著這個物件就可以直接呼叫redis自身方法
*/public function redis()
}
原理就是:
首先,在儲存資料的時候,設定資料的過期時間比實際設定的過期時間多300秒,然後儲存的資料中,通過乙個陣列來儲存資料,陣列中乙個鍵用來存放真實的資料,另外乙個鍵用來存放資料的真實過期時間,這個留到後期獲取資料的時候做校驗,然後把對應這個資料的「鎖」刪除掉。
這裡這麼做的原因和讀取資料的做法相關!
然後,在讀取資料的時候,依然像平時一樣直接讀取,如果資料已經超過了有效期(注意:這裡的有效期並非設定的有效期,而是更該之後的有效期),那麼就只能去讀後端資料庫。如果資料依然有效,則需要去判斷,判斷資料「在真正的有效期內是否失效」,如果沒有失效,則直接返回資料!
重點是,假如資料「在偽造的有效期內沒有失效,而在真正的有效期內已經失效」,那麼這時就需要去判斷「資料的鎖」!
通過**「$lock = $this->redis->incr($key . ".lock");」可以獲取資料的鎖,「$lock === 1」表示資料沒有鎖,那麼這一次請求需要傳送到後端資料庫去讀取最新的資料,否則的話表示該資料已經加了鎖,也就是已經有乙個執行緒去後端讀取資料了,那麼後來的執行緒也就沒有許可權再去後端取資料,需要等到前面的那個執行緒執行結束,但是這次讀取就只能讀取「舊的資料」了!
通過上面的解釋也就明白,為什麼在儲存資料的時候需要「刪除資料的鎖」!因為一旦資料被重新儲存,那麼說明已經有乙個執行緒去後端得到了最新的資料,那麼該資料的鎖就可以釋放,然後下乙個執行緒在獲取資料的時候如果有需要就可以得到這個鎖,然後才有許可權進入到後端去讀取新資料!
來自:
Redis快取過期機制
redis可以通過設定乙個過期時間expire來處理快取,其中處理方式有兩種 主動 定期刪除,redis會抽查隨機的key,預設1秒十次,一旦抽查的key過期了,就會給刪除,配置的屬性在redis.conf中,hz等於10,表示1秒抽查10次 hz 10 被動 惰性刪除,key到期後不去主動檢測,而...
快取問題 五 Redis 快取過期刪除機制
redis 無論有沒有設定expire,都會遵循redis的配置好的刪除機制,規則如下 預設的規則是volatile lru設定了expire的key,將會在過期時間到後刪除 沒有設定expire的快取key,不會被刪除 當到達最大設定記憶體maxmemory時redis先刪除設定了過期時間且過期的...
Redis 快取過期處理與記憶體淘汰機制
計算機記憶體有限,越大越貴,redis的高併發高效能都是基於記憶體的,用硬碟的話gg。設定了expire的key快取過期了,但是伺服器的記憶體還是會被占用,這是因為redis所基於的兩種刪除策略 redis有兩種策略 主動 定時刪除 被動 惰性刪除 所以,雖然key過期了,但是只要沒有被redis清...