文章目錄
-
- 緩存穿透
-
- 定義
- 解決政策
- 布隆過濾器
-
- 布隆過濾器原理
- 布隆過濾器優缺點
- 增加布隆過濾器之後的模型
- 布隆過濾器的使用場景
- 緩存擊穿
-
- 解決方案
- 總結
緩存穿透
定義
有很多使用者,請求接口。
為了防止mysql壓力過大,在通路量很大且資料變動不頻繁的情況下,我們通過增加redis緩存減少mysql的壓力。
正常的流程為下圖所示。

public function redisDemo()
{
$key = $_POST['key'];
//從redis擷取資料
$redisServer = new Redis();
$redisInfo = $redisServer->connect('127.0.0.1','6379');
if($redisInfo == NULL){
throw new ErrorException("redis connect error");
}
$redisValueInfo = $redisServer->get($key);
if(!empty($redisValueInfo)){
echo "redis 中有資料,可以直接傳回";
return $redisValueInfo;
}
//redis中無資料,從mysql中查找
$mysqlServer = mysqli_connect('127.0.0.1','user','123');
$select_db = mysqli_select_db($mysqlServer,'test');
if (empty($select_db)) {
echo "mysql異常";
throw new ErrorException("redis connect error");
}
//查詢代碼
$sql = "select * from db_test WHERE `id` = ".$key." limit 1";
$mysqlRes = mysqli_query($mysqlServer,$sql);
while ($row = mysqli_fetch_row($mysqlRes)) {
$res[] = $row;
}
if(empty($res)){
echo "mysql資料為空";
return "nil";
}else{
//如果mysql查到資料,放入緩存并增加過期時間
$redisServer->set($key,json_encode($res));
$redisServer->expire($key,100);
}
return "nil";
}
那麼如上的流程,存在一種情況,redis中沒有資料,資料庫也沒有此資料,最後會傳回nil。
但是每次通路都會請求redis也會請求mysql。
這樣子相當于這條請求穿透了redis也穿透了mysql。
當這種請求數目多的時候,對mysql伺服器壓力很大,很有可能導緻服務崩潰。
這就是緩存穿透。
解決政策
當然,有人可能會想到解決政策,如果mysql中沒有,我們就在redis中增加過濾政策。
那麼會出現兩種情況。
如果key未設定緩存過期時間,則redis的占用會越來越大。
如果key設定了過期時間,好處是會過濾其中一部分請求,但是redis也會增長,mysql依然會面臨一定壓力的通路。
我們可以在redis後增加一層強有力的過濾。
布隆過濾器。
布隆過濾器
那麼,為什麼用布隆過濾器好,并且,為什麼要用布隆過濾器呢?
這裡簡單說明介紹一下布隆過濾器,之後會在部落格中詳細介紹。
布隆過濾器是一個叫“布隆”的人提出的,它本身是一個很長的二進制向量,既然是二進制的向量,那麼顯而易見的,存放的不是0,就是1。參見位圖。
布隆過濾器原理
比如我們需要向布隆過濾器添加幾個數字,1,2,3,4,5布隆過濾器長度為8。
初始每個位都是0。
1,2,3,4,5經過hash分别對應位置1。
但是有一個問題,如果這些格子裡面放置的都是1,不一定代表給定的資料一定重複,也許其他資料經過三種固定的計算方式算出來的結果也是相同的。這也很好了解吧,比如我們需要判斷對象是否相等,是不可以僅僅判斷他們的哈希值是否相等的。
也就是說布隆過濾器隻能判斷資料是否一定不存在,而無法判斷資料是否一定存在。
布隆過濾器優缺點
優點:由于存放的不是完整的資料,是以占用的記憶體很少,而且新增,查詢速度夠快;
缺點: 随着資料的增加,誤判率随之增加;無法做到删除資料;隻能判斷資料是否一定不存在,而無法判斷資料是否一定存在。
增加布隆過濾器之後的模型
布隆過濾器的使用場景
- 在爬蟲系統中,我們需要對 URL 進行去重,已經爬過的網頁就可以不用爬了。但是 URL 太多了,幾千萬幾個億,如果用一個集合裝下這些URL 位址那是非常浪費空間的。這時候就可以考慮使用布隆過濾器。它可以大幅降低去重存儲消耗,隻不過也會使得爬蟲系統錯過少量的頁面。
- 郵箱系統的垃圾郵件過濾功能也普遍用到了布隆過濾器,因為用了這個過濾器,是以平時也會遇到某些正常的郵件被放進了垃圾郵件目錄中,這個就是誤判所緻,機率很低。
- 推薦系統,已經推薦過的不在進行推薦。
緩存擊穿
上述就是緩存穿透現象,現在說一下緩存擊穿現象。
緩存擊穿是因為請求的資料不在mysql中,緩存擊穿相比于緩存穿透要簡單一些,緩存擊穿為redis鍵值失效或者redis伺服器出現異常,請求直接打在資料庫上。
這些資料在mysql上是有的,是以并不會出現穿透的現象,但是同樣會給redis很大的壓力。
這時候,布隆過濾器已經沒有作用了,因為資料是有的不能過濾掉。
此時的邏輯
解決方案
如果是緩存失效的問題,可以根據業務具體判斷是否不設定失效時間。
如果是redis伺服器的問題,我們可以增加一些有利的防護。
1.redis哨兵,redis cluster避免全盤崩潰。
2.在結束後可以利用redis RDB和AOF去進行恢複資料。
總結
緩存有利有弊,需要根據業務形态以及結合自身考慮去使用。
請再努力一些。
–2020.5.20晚。