快取,你真的用對了嗎
快取,是網際網路分層架構中,非常重要的一個部分,通常用它來降低資料庫壓力,提升系統整體效能,縮短訪問時間。
有架構師說“快取是萬金油,哪裡有問題,加個快取,就能優化”,快取的濫用,可能會導致一些錯誤用法。
快取,你真的用對了麼?
誤用一:把快取作為服務與服務之間傳遞資料的媒介
服務1和服務2約定好key和value,通過快取傳遞資料
服務1將資料寫入快取,服務2從快取讀取資料,達到兩個服務通訊的目的
該方案存在的問題是:
資料管道,資料通知場景,MQ更加適合
多個服務關聯同一個快取例項,會導致服務耦合
《服務通過快取傳遞資料,絕不推薦》一文中有更加深刻的討論,此處不再展開。
誤用二:使用快取未考慮雪崩
常規的快取玩法,如上圖:
服務先讀快取,快取命中則返回
快取不命中,再讀資料庫
什麼時候會產生雪崩?
答:如果快取掛掉,所有的請求會壓到資料庫,如果未提前做容量預估,可能會把資料庫壓垮(在快取恢復之前,資料庫可能一直都起不來),導致系統整體不可服務。
如何應對潛在的雪崩?
答:提前做容量預估,如果快取掛掉,資料庫仍能扛住,才能執行上述方案。
否則,就要進一步設計。
常見方案一:高可用快取
使用高可用快取叢集,一個快取例項掛掉後,能夠自動做故障轉移。
常見方案二:快取水平切分
使用快取水平切分,一個快取例項掛掉後,不至於所有的流量都壓到資料庫上。
誤用三:呼叫方快取資料
服務提供方快取,向呼叫方遮蔽資料獲取的複雜性(這個沒問題)
服務呼叫方,也快取一份資料,先讀自己的快取,再決定是否呼叫服務(這個有問題)
該方案存在的問題是:
呼叫方需要關注資料獲取的複雜性
更嚴重的,服務修改db裡的資料,淘汰了服務cache之後,難以通知呼叫方淘汰其cache裡的資料,從而導致資料不一致
有人說,服務可以通過MQ通知呼叫方淘汰資料,額,難道下游的服務要依賴上游的呼叫方,分層架構設計不是這麼玩的
誤用四:多服務共用快取例項
服務A和服務B共用一個快取例項(不是通過這個快取例項互動資料)
該方案存在的問題是:
可能導致key衝突,彼此沖掉對方的資料
畫外音:可能需要服務A和服務B提前約定好了key,以確保不衝突,常見的約定方式是使用namespace:key的方式來做key。
不同服務對應的資料量,吞吐量不一樣,共用一個例項容易導致一個服務把另一個服務的熱資料擠出去
共用一個例項,會導致服務之間的耦合,與微服務架構的“資料庫,快取私有”的設計原則是相悖的
建議的玩法是:
各個服務私有化自己的資料儲存,對上游遮蔽底層的複雜性。
總結
快取使用小技巧:
服務與服務之間不要通過快取傳遞資料
如果快取掛掉,可能導致雪崩,此時要做高可用快取,或者水平切分
呼叫方不宜再單獨使用快取儲存服務底層的資料,容易出現數據不一致,以及反向依賴
不同服務,快取例項要做垂直拆分