Redis緩存使用技巧

緩存可以有效加速應用的訪問速度,同時能夠下降後端負載,在應用架構中起着相當重要的做用,本文主要介紹緩存使用的一些技巧。node

緩存更新策略

  • LRU/LFU/FIFO算法剔除算法

    場景:數據一致性要求較低
    原理:緩存使用量超過了預設值,使用maxmemory-policy來選擇何種剔除策略對現有數據進行刪除
    問題:數據清理由算法決定,開發人員只能選擇使用哪一種算法,數據一致性最差
  • 超時剔除後端

    場景:數據一致性要求低
    原理:給緩存設置過時時間(expire),自動刪除
    問題:一段時間窗口內存在一致性問題
  • 主動更新緩存

    場景:數據一致性要求較高
    原理:真實數據更新後,當即更新緩存
    問題:主動更新發生問題,這條數據很長時間不會發生更新

總結:

低一致性業務使用最大內存+淘汰策略
高一致性業務使用超時剔除+主動更新網絡

緩存粒度控制

緩存的粒度在緩存應用時也有着很重要的影響,究竟緩存所有屬性仍是部分屬性?能夠從三個維度來進行權衡。多線程

  • 通用性架構

    緩存所有數據比部分更加通用,可是較多狀況下,應用只須要其中幾個重要的屬性
  • 空間佔用併發

    緩存所有數據佔用更多的空間,可能會形成內存的浪費,並且每次傳輸產生的網絡流量較大,極端狀況會阻塞網絡
  • 代碼維護運維

    部分數據一旦表結構變更,增長新字段則須要修改業務代碼,而且須要從新刷新緩存

總結:

緩存粒度問題容易被忽視,可是使用不當,可能形成更多無用空間的浪費、網絡帶寬的浪費、代碼通用型較差等狀況,須要綜合以上三點進行取捨分佈式

緩存穿透優化

緩存穿透指查詢一個不存在的數據,致使不存在的數據每次請求都要到存儲層查詢,使後端存儲層負載過大,極端狀況可能致使宕掉。

  • 緩存空對象

    原理:緩存不命中,查詢存儲層,仍然不命中,則將空對象保存至緩存層中,而後再返回
    場景:數據命中率不高,頻繁變化實時性高
    問題:1.空值佔用更多的鍵,佔用更多的內存空間,若是被攻擊,可能致使內存快速增加,利用較短的過時時間來自動剔除;
    2.緩存層和存儲層必定時間窗口數據不一致,利用消息系統或者其它方式清楚緩存中空對象。
  • 布隆過濾攔截器

    原理:在緩存層和存儲層之間,將存在的key用布隆過濾器提早保存,若是key存在,則不訪問存儲層,能夠經過Bitmaps來實現。
    場景:數據命中率不高、數據相對固定、實時性低(數據集較大)
    問題:代碼維護複雜

無底洞優化

業務增加致使須要增長緩存節點來提升性能,可是增長節點後性能不但沒有反轉反而降低。分佈式場景下,一次批量操做須要訪問多個Redis節點,須要屢次網絡訪問時間。

  • 串行命令

    原理:n個key均勻分佈在Redis Cluster各個節點上,逐次執行n個get命令
    耗時:n次網絡時間+n次命令時間
    缺點:大量keys請求延遲
  • 串行IO

    原理: 使用JedisClusterCRC16計算出key的slot,而後找到對應的節點,將屬於同一個節點的key進行歸檔,對每一個節點執行mget操做
    耗時:node次網絡時間+n次命令時間
    缺點:大量node延遲
  • 並行IO 

    原理:對於串行IO中,得出每一個節點的key列表,經過多線程來對每一個節點進行mget操做
    耗時:max_slow(node網絡時間)+n次命令時間
    缺點:變成複雜、多線程問題定位較難
  • hash_tag

    原理:利用Redis Cluster功能,將多個key強制分配到一個節點
    耗時:1次網絡時間+n次命令時間
    缺點:業務維護成本高、數據傾斜

雪崩優化

緩存層因爲某些緣由不可用,全部請求到達存儲層,壓力暴增,可能致使存儲層也會級聯宕機。

  • 保證緩存層服務高可用:Redis Sentinel、Redis Cluster
  • 依賴隔離組件爲後端限流降級:Hystrix
  • 提早演練:模擬緩存層宕掉,應用以及後端的負載狀況和可能出現的問題

熱點key重建優化

「緩存+過時時間」的策略絕大部分狀況知足加速數據讀寫、保證數據按期更新的需求,可是也可能出現其它問題,假如某一個key是一個熱點key,併發量很大,而且重建緩存遇到複雜SQL、屢次IO等不可能短期完成狀況,當緩存失效的瞬間,大量線程重建,形成後端負載過大。

  • 互斥鎖(分佈式鎖)

    原理:只容許一個線程重建緩存,其它線程等待,直接從緩存中獲取數據
    實現:使用Redis setnx或者其它方式來實現
    問題:構建緩存過程出現問題或者時間過長,可能存在死鎖和線程池阻塞的風險
  • 永遠不過時

    原理:爲每一個value設置邏輯過時時間,當發現超過邏輯過時時間後,使用單獨線程從新構建緩存
    問題:不保證一致性問題,代碼維護成本和內存成本(每次重建)增長

    參考資料:《Redis開發與運維》

相關文章
相關標籤/搜索