redis 過期時間技巧之快取雪崩

2021-08-16 20:31:31 字數 1551 閱讀 6552

如今許多網際網路應用系統都重度依賴快取來提高讀操作的效能,對於這些系統來說如何正確地使用快取至關重要。本文從快取讀取這個視角來討論快取架構設計上的一些思路。重點關注如何防止快取雪崩。

引入快取後,讀資料的流程如下:

在正常情況下,一旦miss就去查db是沒有問題的。但是如果大量快取集中在某一時間段失效,將導致所有請求都去訪問後端的db,db壓力會很大,甚至被壓垮,造成雪崩。

電商系統的某個大促活動的首頁,首頁有很多新上架的商品。活動開始前,技術團隊對快取做了預熱,由於是指令碼化預熱,這些商品的cache資料幾乎都是同時建立好,並且過期時間都設定為5分鐘。這就會導致這大量的商品資料在5分鐘後集中失效。

cache系統剛上線(或者剛從崩潰中恢復過來),沒有對cache進行預熱。cache中什麼也沒有,這時瞬時大流量過來也會產生雪崩。

針對上面的場景一,可以對cache的過期時間做乙個均勻分布的處理。比如1-5分鐘內,隨機分布。

針對場景二,可以考慮使用排斥鎖(mutex)。即第乙個執行緒過來讀取cache,發現沒有,就去訪問db。後續執行緒再過來就需要等待第乙個執行緒讀取db成功,cache裡的value變得可用,後續執行緒返回新的value。偽**如下:

public object getcachevalue(string key, int expiredtime)  else  else 

}} finally

return cachevalue;

}}

方案細節:

排斥鎖方案對快取過期是零容忍的:cache一旦過期,後續所有讀操作就必須返回新的value。如果我們稍微放寬點限制:在cache過期時間t到達後,允許短時間內部分讀請求返回舊值,我們就能提出兼顧吞吐率的方案。實際上既然用了cache,系統就默許了容忍cache和db的資料短時間的不一致。

限制放寬後,下面我們提出乙個優化思路。時間t到達後,cache中的key和value不會被清掉,而只是被標記為過期(邏輯上過期,物理上不過期),然後程式非同步去重新整理cache。而後續部分讀執行緒在前面的執行緒重新整理cache成功之前,暫時獲取cache中舊的value返回。一旦cache重新整理成功,後續所有執行緒就能直接獲取cache中新的value。可以看到,這個思路很大程度上減少了排斥鎖的使用(雖然並沒有完全消除排斥鎖)。 

下面先看下偽**:

public object getcachevalue(string key, int expiredtime)  else }}

} catch (exception ex) finally

});return cachevalue;

}}// 判斷快取標記是否過期

private boolean i***pired(string signkey, boolean prolongtime)

return true;

}return false;

}// 設定signkey的過期時間

private void setsign(string key, int expiredseconds)

方案細節

Redis 過期時間 和 快取 例子

1.設定 key的生存時間,過期自動刪除 exprire key seconds 設定過期時間 秒數 ttl key 查詢剩餘時間 如果 設定了過期時間。對key進行 set 操作,會清除掉 key的過期時間 實際例子1 可以實現 限制頻率操作 如,限制 1分鐘的 ip只能訪問5次 1.設定 ip為...

redis過期時間

在redis中,可以給乙個鍵設定過期時間,等時間到了以後,該鍵會被自動刪除。這個機制經常被用來儲存驗證碼等有一定時效性的東西,資料的有效期過了以後,就會被自動刪除以節省記憶體空間。跟過期相關的命令有三個,分別是expire persist和ttl,用法如下 來看個簡單的例子 0.1 6379 set...

redis過期時間

如果redis中沒有設定expire過期時間,那麼redis中的資料將會是永久有效的,不會被自動刪除 在不超過最大記憶體的情況下 但是redis無論有沒有設定expire,他都會遵循redis的配置好的刪除機制,在配置檔案裡設定 redis最大記憶體不足 時,資料清除策略,預設為 volatile ...