基於Redis實現快取系統的注意點與一些常見問題

2021-10-17 15:51:21 字數 3267 閱讀 6284

在我的部落格閱讀本文

5. 快取使用過程中的一些問題

6. 參考

在計算機系統中,預設有兩種快取:

llc一般幾mb,page cache一般幾gb,磁碟一般幾tb,可以看出快取系統有以下特徵

所謂快取,就是將需要多次讀取的資料暫存起來,這樣在後面,應用程式需要多次讀取的時候,就不必從資料來源重複載入資料了,這樣就可以降低資料來源的計算負載壓力,提高資料響應速度。

一般來說,有三種策略:

**旁路快取(cache aside)策略:讀操作命中快取直接返回,否則從後端資料庫載入到快取再返回,並寫入快取中。寫操作直接更新資料庫,然後刪除快取。這種策略的優點是一切以後端資料庫為準,可以保證快取和資料庫的一致性。缺點是寫操作會讓快取失效,再次讀取時需要從資料庫中載入。**redis一般都是使用這個策略。

**通讀快取(read throught)策略:應用層讀寫只需要操作快取,不需要關心後端資料庫。應用層在操作快取時,快取層會自動從資料庫中載入或寫回到資料庫中,這種策略的優點是,快取中擁有最新的資料,對於應用層的使用非常友好,只需要操作快取即可,缺點是需要快取層支援和後端資料庫的聯動。**redis無法自動與mysql等後端資料庫聯動,需要額外寫業務**來實現這個策略。

寫回策略(write back)策略:這裡主要是指非同步寫回策略,同步就是通讀快取了。寫操作只寫入快取,等資料就要過期(淘汰)時寫入到資料庫中。優點是寫入飛快,缺點是資料丟失風險較大

一般遵循「八二原理」設定為總資料量的 15% 到 30%,兼顧訪問效能和記憶體空間開銷。

redis的記憶體總是會滿的,因此我們需要設定相應的的刪除方案,對記憶體資料進行清理。

總結來說就是三塊:

定期刪除

惰性刪除

記憶體淘汰

redis每隔一端時間會檢查一部分已經過期的key進行刪除。

redis會在獲取某個key時檢查是否過期,過期就刪除

需要注意,volatile-lfu和allkeys-lfu是redis 4.0 後新增的。

注意:

lru 會把所有的資料組織成乙個鍊錶,鍊錶的頭和尾分別表示 mru 端和 lru 端,分別代表最近最常使用的資料和最近最不常用的資料:

lru 演算法背後的想法非常樸素:它認為剛剛被訪問的資料,肯定還會被再次訪問,所以就把它放在 mru 端;長久不訪問的資料,肯定就不會再被訪問了,所以就讓它逐漸後移到 lru 端,在快取滿時,就優先刪除它。

在 redis 中,lru 演算法被做了簡化,以減輕資料淘汰對快取效能的影響(否則需要維護鍊錶)。具體來說,redis 缺省會記錄每個資料的最近一次訪問的時間戳(由鍵值對資料結構 redisobject 中的 lru 字段記錄)。然後,redis 在決定淘汰的資料時,第一次會隨機選出 n 個資料,把它們作為乙個候選集合。接下來,redis 會比較這 n 個資料的 lru 字段,把 lru 字段值最小的資料從快取中淘汰出去。

lfu 快取策略是在 lru 策略基礎上,為每個資料增加了乙個計數器,來統計這個資料的訪問次數。當使用 lfu 策略篩選淘汰資料時,首先會根據資料的訪問次數進行篩選,把訪問次數最低的資料淘汰出快取。如果兩個資料的訪問次數相同,lfu 策略再比較這兩個資料的訪問時效性,把距離上一次訪問時間更久的資料淘汰出快取。

總結來看:

特別注意,在設定資料的過期時間時,盡量指定過期時間,而不是指定多久後後刪除,在主從環境中會出現不一致的情況(從庫保留資料時間 = 從庫同步到資料 + 過期時間,而從庫同步到資料的時間 在 主庫寫入資料的時間之後)

這裡用蔣德鈞老師的一張圖:

快取雪崩是指大量的應用請求無法在 redis 快取中進行處理,緊接著,應用將大量請求傳送到資料庫層,導致資料庫層的壓力激增。

可能有兩個原因:

快取中有大量資料同時過期,導致大量請求無法得到處理。redis伺服器宕機。

針對第1點,有以下方案:

針對第2點,有以下方案:

快取擊穿是指,針對某個訪問非常頻繁的熱點資料的請求,無法在快取中進行處理,緊接著,訪問該資料的大量請求,一下子都傳送到了後端資料庫,導致了資料庫壓力激增,會影響資料庫處理其他請求。

一般考慮是對於訪問特別頻繁的熱點資料,不設定過期時間。

快取穿透是指要訪問的資料既不在 redis 快取中,也不在資料庫中,導致請求在訪問快取時,發生快取缺失,再去訪問資料庫時,發現資料庫中也沒有要訪問的資料。

有以下方案:

下面重點說以下布隆過濾器,這是乙個概率學的演算法實現,布隆過濾器有以下特點:

符合布隆過濾器不一定存在,不符合布隆過濾器一定不存在

布隆過濾器由乙個初值都為 0 的 bit 陣列和 n 個雜湊函式組成,可以用來快速判斷某個資料是否存在。當我們想標記某個資料存在時(例如,資料已被寫入資料庫),布隆過濾器會通過三個操作完成標記:

這樣,當應用想要查詢 x 時,只要 比較原來為1的位置 是否包含於x計算後為1的位置中,一旦又乙個不符合(為0),則不在快取中,否則可能在。

在一些場景下,有些資料被訪問的次數非常少,甚至只會被訪問一次。當這些資料服務完訪問請求後,如果還繼續留存在快取中的話,就只會白白占用快取空間。這種情況,就是快取汙染

需要根據業務設定合適的快取淘汰(驅逐)策略。

在redis切片集群中比較容易遇到的乙個問題:資料傾斜

這裡po乙個**:

基於redis佇列的日誌系統實現

1 log的儲存不應該被當前執行緒的session影響,和log4j一樣,執行到哪一步就記錄哪一步,輸出到資料庫,不能出現錯誤回滾或則儲存失敗。2 log的儲存和插入不能影響當前執行緒,不能因為日誌儲存過多而影響當前程序響應速度,或則占用資料庫資源影響程序的讀寫。先將日誌產生後放入快取佇列中,不影響...

C 基於Redis快取實現單點登入SSO的例項

最近公司的多個業務系統要統一整合使用同乙個登入,這就是我們耳熟能詳的單點登入,現在就net基於redis快取實現單點登入做乙個簡單的分享。單點登入 single sign on 簡稱為 sso,是目前比較流行的企業業務整合的解決方案之一。sso的定義是在多個應用系統中,使用者只需要登入一次就可以訪問...

基於Redis的訊息中心快取搭建

在以往的經歷中出現了在大批使用者湧入訊息中心時,造成資料庫負載急劇公升高的問題,經過排查,發現原因主要有以下幾點 訊息中心相關表中,部分體量較大的資料表沒有建立索引,查詢操作中資料庫連線不能及時釋放,導致api伺服器不能及時響應,拖垮api伺服器 目前的訪問量級對訊息中心沒有做資料庫的讀寫分離,導致...