緩存可以有效加速應用的訪問速度,同時能夠下降後端負載,在應用架構中起着相當重要的做用,本文主要介紹緩存使用的一些技巧。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次命令時間 缺點:業務維護成本高、數據傾斜
緩存層因爲某些緣由不可用,全部請求到達存儲層,壓力暴增,可能致使存儲層也會級聯宕機。
「緩存+過時時間」的策略絕大部分狀況知足加速數據讀寫、保證數據按期更新的需求,可是也可能出現其它問題,假如某一個key是一個熱點key,併發量很大,而且重建緩存遇到複雜SQL、屢次IO等不可能短期完成狀況,當緩存失效的瞬間,大量線程重建,形成後端負載過大。
互斥鎖(分佈式鎖)
原理:只容許一個線程重建緩存,其它線程等待,直接從緩存中獲取數據 實現:使用Redis setnx或者其它方式來實現 問題:構建緩存過程出現問題或者時間過長,可能存在死鎖和線程池阻塞的風險
永遠不過時
原理:爲每一個value設置邏輯過時時間,當發現超過邏輯過時時間後,使用單獨線程從新構建緩存 問題:不保證一致性問題,代碼維護成本和內存成本(每次重建)增長
參考資料:《Redis開發與運維》