Redis 優化

myjob發表於2019-06-11

redis快取穿透

快取穿透:是指查詢一個資料庫一定不存在的資料。正常的使用快取流程大致是,資料查詢先進行快取查詢,如果key不存在或者key已經過期,再對資料庫進行查詢,並把查詢到的物件,放進快取。如果資料庫查詢物件為空,則不放進快取。

問題:假如有惡意攻擊,就可以利用這個漏洞,對資料庫造成壓力,甚至壓垮資料庫。

解決方法

  1. 設定預設值存放到快取。這樣第二次到緩衝中獲取就有值了,而不會繼續訪問資料庫。
  2. 根據快取資料Key的設計規則,將不符合規則的key進行過濾。採用布隆過濾器,將所有可能存在的資料雜湊到一個足夠大的BitSet中,不存在的資料將會被攔截掉,從而避免了對底層儲存系統的查詢壓力

快取擊穿

快取擊穿:個別訪問量很高的資料,資料過期取不到資料的時候,轉而去請求資料庫,會對資料庫造成壓力。
解決方法:永遠不過期

redis快取雪崩

快取雪崩:是指在某一個時間段,快取集中過期失效。

產生雪崩的原因之一,比如在寫本文的時候,馬上就要到雙十二零點,很快就會迎來一波搶購,這波商品時間比較集中的放入了快取,假設快取一個小時。那麼到了凌晨一點鐘的時候,這批商品的快取就都過期了。而對這批商品的訪問查詢,都落到了資料庫上,對於資料庫而言,就會產生週期性的壓力波峰。

解決方法

  1. 也是像解決快取穿透一樣加鎖排隊,實現同上;
  2. 建立備份快取,快取A和快取B,A設定超時時間,B不設值超時時間,先從A讀快取,A沒有讀B,並且更新A快取和B快取;
  3. 設定快取超時時間的時候加上一個隨機的時間長度,比如這個快取key的超時時間是固定的5分鐘加上隨機的2分鐘,可從一定程度上避免雪崩問題;而且,熱門類目的商品快取時間長一些,冷門類目的商品快取時間短一些,也能節省快取服務的資源。

一致性問題

分散式環境下(單機就不用說了)非常容易出現快取和資料庫間的資料一致性問題,針對這一點的話,只能說,如果你的專案對快取的要求是強一致性的,那麼請不要使用快取。我們只能採取合適的策略來降低快取和資料庫間資料不一致的概率,而無法保證兩者間的強一致性。合適的策略包括 合適的快取更新策略,更新資料庫後要及時更新快取、快取失敗時增加重試機制,例如MQ模式的訊息佇列。

資料淘汰策略

定時刪除

策略 : 在設定鍵的過期時間的同時,建立一個定時器,讓定時器在鍵的過期時間來臨時,立即執行對鍵的刪除操作。
優點 : 對記憶體友好,保證過期鍵會盡可能快地被刪除,並釋放過期鍵所佔用的記憶體。
缺點 : 對CPU時間不友好,佔用太多CPU時間,影響伺服器的響應時間和吞吐量。

惰性刪除

策略 : 放任過期鍵不管,每次從鍵空間讀寫操作時,都檢查鍵是否過期,如果過期,刪除該鍵,如果沒有過期,返回該鍵。
優點 : 對CPU時間友好,讀寫操作鍵時才對鍵進行過期檢查,刪除過期鍵的操作只會在非做不可的情況下進行。
缺點 : 對記憶體不友好,只要鍵不刪除,就不會釋放記憶體,浪費太多記憶體,有記憶體洩漏風險。

定期刪除

策略 :
對定時刪除策略和惰性刪除策略的一種整合和折中。每隔一段時間執行一次定時刪除,並通過限制刪除操作執行的總時長和總頻率來限制刪除操作對CPU佔用時間的影響。通過定期刪除過期鍵,有效減少了因為過期鍵而帶來的記憶體浪費。
難點:確定刪除操作執行的總時長和總頻率。執行太頻繁,執行時間過長,就會退化成定時刪除策略,影響客戶端請求效率;執行得太少,執行時間太短,會演變為惰性刪除,存在記憶體浪費的情況。
Redis伺服器使用惰性刪除和定期刪除兩種策略,通過配合使用,很好地在合理使用CPU時間和避免浪費記憶體之間取得平衡。

舉例:
從過期鍵中隨機選取 20 個 key
遍歷這 20 個 key,並對過期的 key進行刪除操作
如果過期的 key 比率超過25%,則重複步驟 1
同時,為了保證過期掃描不會出現迴圈過度,導致執行緒卡死現象,增加了掃描時間的上限,預設不會超過 25ms以及頻次上線10次。

主動清理

當前已用記憶體超過maxmemory限定時,觸發主動清理策略。
清理時會根據使用者配置的maxmemory-policy來做適當的清理。
主動清理策略主要有一下六種:

volatile-lru : 從已設定過期時間的資料集(server.db[i].expires)中挑選最近最少使用 的資料淘汰。
volatile-ttl : 從已設定過期時間的資料集(server.db[i].expires)中挑選將要過期的數 據淘汰。
volatile-random : 從已設定過期時間的資料集(server.db[i].expires)中任意選擇資料 淘汰。
allkeys-lru : 從資料集(server.db[i].dict)中挑選最近最少使用的資料淘汰。
allkeys-random : 從資料集(server.db[i].dict)中任意選擇資料淘汰。
no-enviction : 禁止驅逐資料

相關文章