本文源碼:GitHub·點這裡 || GitEE·點這裡
在業務系統中,查詢時最容易出現性能問題的子產品,查詢面對的資料量大,篩選條件複雜,是以在系統架構中引入緩存層,則是非常必要的,用來緩存熱點資料,達到快速響應的目的。
緩存使用的基本原則:
所有緩存資料,必須設定過期時間;
核心業務流程不通過緩存層;
緩存層移除,不影響現有流程;
系統各個端首頁資料不實時查詢;
報表資料不實時查詢加載;
歸檔資料(定時統計的結果資料)不實時查詢;
這裡是業務架構中常用的緩存政策,緩存通過犧牲強一緻性來提高性能,是以并不是所有的業務都适合用緩存,實際考量都會針對具體的業務,比如使用者相關次元的資料修改頻率低,會使用緩存,但是使用者權限資料(比如:免費次數)會考慮實時校驗,緩存層使用的相對較少。
Cache-Aside模式
業務中最常用的緩存層設計模式,基本實作邏輯和相關概念如下:
緩存命中:直接查詢緩存且命中,傳回資料;
緩存加載:查詢緩存未命中,從資料庫中查詢資料,擷取資料後并加載到緩存;
緩存失效:資料更新寫到資料庫,操作成功後,讓緩存失效,查詢時候再重新加載;
緩存穿透:查詢資料庫不存在的對象,也就不存在緩存層的命中;
緩存擊穿:熱點key在失效的瞬間,高并發查詢這個key,擊穿緩存,直接請求資料庫;
緩存雪崩:緩存Key大批量到過期時間,導緻資料庫壓力過大;
命中率:緩存設計的是否合理要看命中率,命中率高說明緩存有效抗住了大部分請求,命中率可以通過Redis監控資訊計算,一般來說命中率在(70-80)%都算合理。
并發問題
執行讀操作未命中緩存,然後查詢資料庫中取資料,資料已經查詢到還沒放入緩存,同時一個更新寫操作讓緩存失效,然後讀操作再把查詢到資料加載緩存,導緻緩存的髒資料。
在遵守緩存使用原則下出現該情況機率非常低,可以通過複雜的Paxos協定保證一緻性,一般情況是不考量該場景的處理,如果緩存管理過于複雜,會和緩存層核心理念相悖。
基本描述代碼:
Read-Throug模式
當應用系統向緩存系統請求資料時,如果緩存中并沒有對應的資料存在,緩存系統将向底層資料源的讀取資料。如果資料在緩存中存在,則直接傳回緩存中存在的資料。把更新資料庫的操作由緩存層代勞了。
Write-Through模式
更新寫資料時,如果沒有命中緩存,則直接更新資料庫,如果命中了緩存,則先更新緩存,然後由緩存系統自行更新資料庫。
Write-Behind模式
應用系統對緩存中的資料進行更新時,隻更新緩存,不更新資料庫,緩存系統會異步批量向底層資料源更新資料。
業務開發模式中,會涉及到一個問題:如何最大限度保證資料庫和Redis緩存的資料一緻性?
首先說明一下:資料庫和緩存強一緻性同步成本太高,如果追求強一緻,緩存層存在的價值就會很低,如上緩存模式一中幾乎可以解決大部分業務場景問題。
解決這個問題的方式很多:
方案一說明:
資料庫更新寫入資料成功;
準備一個先進先出模式的消息隊列;
把更新的資料包裝為一個消息放入隊列;
基于消息消費服務更新Redis緩存;
分析:消息隊列的穩定和可靠性,操作層面資料庫和緩存層解耦。
方案二說明:
提供一個資料庫Binlog訂閱服務,并解析修改日志;
服務擷取修改資料,并向Redis服務發送消息;
Redis資料進行修改,類似MySQL的主從同步機制;
分析:系統架構層面多出一個服務,且需要解析MySQL日志,操作難度較大,但流程上更為合理。
總結描述
分布式架構中,緩存層面的基本需求就是提高響應速度,不斷優化,追求資料庫和Redis緩存的資料快速一緻性,從提供的各種方案中都可以看出,這也在增加緩存層面處理的複雜性,架構邏輯複雜,就容易導緻程式錯誤,是以針對業務選擇合理的處理邏輯,這點很關鍵。
通過info指令檢視Redis服務的參數資訊,可以通過傳參檢視指定分類配置。通過config..set設定具體配置參數。例如:
傳參說明:
memory:記憶體消耗相關資訊
server:有關Redis伺服器的正常資訊
clients:用戶端連接配接部分
stats:一般統計
cpu:CPU消耗統計資訊
應用案例:
通過上述參數組合,把Redis相關配置參數列印出來,然後可視化輸出,俨然一副高端的感覺。
配置參數說明:
這裡隻對兩個參數說明一下,計算命中率的關鍵資訊:
keyspace_misses:查找緩存Key失敗的次數;
keyspace_hits:查找緩存Key命中的次數;
公式:命中率=命中次數/(hits+misses)查找總次數。
Redis的資料是放在記憶體中的,是以速度快,自然也就受到記憶體大小的限制,如果記憶體使用超過配置,Redis有不同的回收處理政策。
記憶體子產品參數:maxmemory_policy
noenviction:不回收資料,查詢直接傳回錯誤,但可以執行删除;
allkeys-lru:從所有的資料中挑選最近最少使用的資料淘汰;
volatile-lru:已設定過期時間的資料中挑選最近最少使用的資料淘汰;
allkeys-random:從所有資料中任意選擇資料淘汰;
volatile-random:從已設定過期時間的資料中任意選擇資料淘汰;
volatile-ttl:從已設定過期時間的資料中挑選将要過期的資料淘汰;
大部分情況下,業務都是希望最熱點資料可以被緩存,是以相對使用allkeys-lru政策偏多。這裡要根據業務模式特點衡量。
推薦閱讀:《架構設計系列》,蘿蔔青菜,各有所需
序号
标題
01
架構基礎:單服務.叢集.分布式,基本差別和聯系
02
架構設計:分布式業務系統中,全局ID生成政策
03
架構設計:分布式系統排程,Zookeeper叢集化管理
04
架構設計:接口幂等性原則,防重複送出Token管理