redis快取設計
阿新 • • 發佈:2019-12-31
快取的利於弊及應用場景
這裡我們主要討論以Redis為代表的基於記憶體的快取方案。
快取的優點
- 提升訪問速度,減少後端如資料庫儲存的時間消耗
- 減輕後端如資料庫的壓力
快取帶來的問題
任何系統每增加一個元件,在帶來新的特性的同時也必然會帶來額外的複雜度,可以說系統的設計過程就是一個折中的過程。快取的引入也帶來了一些需要考慮的問題:
- 資料不一致: 快取層和儲存層的資料存在著一定的時間視窗的不一致性,時間視窗跟快取更新策略有關
- 程式碼維護成本: 需要同時處理快取和儲存層的邏輯
- 運維成本: 為了保證redis的可用性和併發性,會引入
redis sentinel
或redis cluster
等架構,這又增加了系統複雜性和運維難度。
應用場景
- 開銷大的複雜運算
- 加速請求響應
快取更新策略
- LRU/LFU/FIFO演演算法
- 超時剔除
- 主動更新
應用
- 低一致性業務建議:最大記憶體+淘汰策略
- 高一致性:超時剔除和主動更新
快取穿透
快取穿透: 是指查詢一個根本不存在的資料, 快取層和儲存層都不會命中。這會造成儲存層壓力變大。
快取穿透的發現:
通常可以在程式中分別統計
- 總呼叫數
- 快取層命中數
- 儲存層命中數
如果發現大量儲存層空命中, 可能就是出現了快取穿透問題。
快取穿透的解決方案
- 快取空物件
- 佔用記憶體: 原因是為了防止大量空物件(被攻擊) 方案是可以設定比較短的過期時間,讓其自動剔除
- 資料不一致: 原因是
- bloomfilter攔截
- 這種方法適用於資料命中不高、 資料相對固定、 實時性低(通常是資料集較大) 的應用場景, 程式碼維護較為複雜,但是快取空間佔用少。
無底洞優化
由於快取叢集通常會將key進行hash,然後對映到相應的節點上,造成key的分佈與業務無關,批量操作通常需要從不同節點上獲取,相比於單機批量操作只涉及一次網路操作,分散式批量操作會涉及多次網路時間。
常見的IO優化思路:
- 命令本身的優化,例如優化SQL語句等
- 減少網路通訊次數
- pipeline
- mget
- 降低介入成本,例如客戶端使用長連/連線池、NIO等
叢集客戶端優化方案
- 序列IO,把key的請求按照節點分組,然後依次處理
- 並行IO,把key的請求按照節點分組,然後並行處理
- hash_tag實現, 可以將多個key強制分配到一個節點上,它的操作時間=1此網路時間+n次命令時間,效能最高,但是資料維護成本高,資料易傾斜
雪崩優化
雪崩定義:由於快取層承載著大量請求,有效地儲存了儲存層,但是如果快取層由於某些原因不能提供服務,於是所有的請求都會到達儲存層,儲存層的呼叫會暴增。
說到底就是快取扛不住了,把壓力衝擊到了儲存層。
預防和緩解快取雪崩問題的三個方面
- 保證快取層服務高可用性,redis提供了
Redis Sentinel
和Redis Cluster
- 依賴隔離元件為後端限流並降級,降級機制,如
Hystrix
- 提前演練,專案上線前,演練快取層宕掉後,應用及後端的負載情況以及可能出現的問題。
熱點key重建優化
快取+過期時間的策略既可以加速資料讀寫,又保證資料的定期更新,這種模式基本能夠滿足絕大部分需求。但有兩個問題:
- 熱點key,併發量非常大
- 重建快取不能在短時間完成(長時生成快取)
熱點key重建
- 互斥鎖
- 永遠不過期,但是重建期間會有不一致問題