微服務實踐目錄,可以參見連接。
緩存系列包括:
1.微服務管理-11.緩存概述
1.微服務管理-11.緩存-0.技術
1.微服務管理-11.緩存-1.多級緩存設計
1.微服務管理-11.緩存-2.典型緩存架構設計
1.微服務管理-11.緩存-3.實踐-緩存使用
1.微服務管理-11.緩存-4.總結
背景
在前面的幾篇文章中討論了很多關于緩存使用時要注意的事項。但在實際的工作中在哪些地方考慮這些事項其實還是不明確。為了幫助讀者在生產中更好的使用緩存,本文主要以例子的方式說明在生產環境中使用緩存的方式。
示例
結合前面幾篇文章中的內容,并通過盡量的減少對于(相對)慢速服務/設備的訪問來提高業務處理速度。但在業務處理過程中減少對于慢速服務/設備的訪問并不一定就可以提升業務處理速度,并還有可能帶來其他的問題。所以,這里展示幾個例子來解釋這些問題,并提供可用的生產環境方案。
大量請求的終極方案
在前幾篇文章中出現過大量請求的時候的一個終極方案,如下:
這個方案參照了之前使用cdn緩存業務接口的方式來設計。通過OpenResty中支持的腳本語言Lua去控制本地返回還是使用Redis中結果返回。還有如果發生miss之后還需要調用后端服務來更新緩存。
這種方式的緩存的特點:適合IO密集型業務中,不適合計算密集型業務。并在業務過程中查看的業務占系統業務的絕大部分。例如:大型線上商城中的商品展示,新聞網站,網站門戶,微博/陌生人社交,音視頻服務,圖片網站等。
緩存更新示例
在實際的緩存更新過程中一般有以下幾種方式來更新緩存:
這幾種方式針對不同的緩存模型來進行。
-
被動更新
使用領域事件,定時進行緩存的更新動作。在數據源發生變化時通過事件的方式通知各個關心這部分數據的服務去更新自己保存的信息一般情況下在事件驅動模式下可以完成。但很多時候服務/系統之前的數據的同步工作不會這么順利的解決,所以還可以使用定時輪詢數據源的方式檢查服務緩存數據是否和數據源數據一致。 -
主動更新
在用戶訪問的時候檢查并更新緩存。在用戶對業務進行訪問時對緩存的數據進行檢查和更新,這樣可以保證只有用戶用才對緩存進行操作,用戶不用這部分業務的時候就不對緩存進行操作。這樣可以減少對于計算資源的消耗很有幫助,還可以減少緩存中空間的占用。
被動更新的特點在于有一個系統中的觸發源去觸發數據的更新動作。主動更新的特點在于只有用戶在使用系統的特定功能時才會觸發更新的動作。被動更新可以保證緩存和數據源之間的數據永遠是一致的,并且不需要過多的補償機制來保證數據一致性。主動更新的方式就會發生緩存和數據源中數據不一致的問題。所以,在后面會討論在主動更新模式下盡量保證數據一致性的方式。
定時更新的方式在很多地方都有使用,例如CDN的定時溯源的機制就是以這種方式運行的。
被動更新
事件更新
事件更新中最核心的概念是事件,這里的事件最好是在領域驅動設計中的事件風暴階段中這里出來的事件。因為這種事件代表著業務發生的動作,也代表著業務價值的流動。
一般情況下領域驅動設計中的事件是從限界上下文中發送出來的由另一個限界上下文接收和處理。但在一些情況下也可以是同一個限界上下文中的不通過聚合發送和接收。
基于現在的系統架構模式幾乎都使用微服務模式,所以最好使用消息組播的方式來處理消息。這樣可以防止一個邏輯服務的不同實例都在處理同一個緩存key。
定時更新
在微服務架構模式下,任務、定時器都會由一個任務調度中心來完成。所以,在使用定時觸發緩存更新時還是使用分布式任務調度中心來完成任務的調度工作。這樣可以保證同一時間只有一個實例在處理。以這種方式簡單的進行排他工作,防止同時操作緩存的問題。
被動更新
用戶觸發更新也可以稱為非固定周期更新,因為用戶的觸發時間是不確定的、任何時候都可能。有一種隨機數的產生方式就是使用類似的機制:操作系統使用內核接受到中斷的時間點作為隨機數使用。所以,用戶觸發更新的方式就是一種隨機發生的緩存更新。
下面一一說明圖中內容的含義:
- 深藍色的矩形塊:緩存更新間隔
緩存更新間隔代表緩存最小更新周期,只有緩存在超過這個周期還沒有更新的情況下才會進行觸發更新。更新間隔中多次使用緩存則不進行更新。
緩存更新間隔的作用是防止用戶在很短的時間段內多次使用這部分數據,而產生的每次都要更新緩存的問題。如果每次都要更新緩存中的數據,那么和未使用緩存的系統行為就是一致的,那就相當于沒有使用緩存。 - 綠色箭頭:觸發事件
觸發事件是系統接收到的請求。在請求處理中要判斷是否超過了一個更新間隔,如果緩存的存在時間已經超過一個更新間隔則需要對緩存進行更新。
這里隱藏著一個點,在非固定周期中更新了緩存是需要重新設置緩存的過期時間的。因為這樣就會造成同一塊業務的緩存失效時間點不一致。而緩存失效時間點就可以避免緩存雪崩的產生。 - 綠色雙向箭頭:過期時間
過期時間是為了保證緩存中的數據可以正常的過期被提出緩存,這樣來提高緩存的使用率。
另外在過期時間中還隱藏了一個重要的問題:緩存存在是否就可以直接返回給業務?在緩存存在的情況下,更新緩存的動作是異步的執行了,讓現有的數據直接返回給業務。還是更新緩存的動作同步執行,等更新完緩存之后再返回。這里在下一節中詳細討論。 - 公式:更新率
更新率跟下面所要討論的緩存更新方式有很重要的關聯。這里先討論一下更新率代表著什么?更新率代表著數據不一致的情況最大可接受的范圍。因為數據源在更新間隔內更新了數據,在緩存使用服務中更新緩存的頻率。所以,在后面討論的同步和異步方式中,同步時推薦更新率月趨近于1越好,而異步方式越小越好。
因為同步方式更新率趨近于1,因為如果在觸發事件超過更新間隔時永遠都會更新緩存,所以這兩個值相等比較好。在異步更新時為了保證緩存和數據源的一致性,保持比較小的一個更新率可以保證數據的一致性,并能保證緩存空間被充分的利用。
同步、異步更新
如上圖中箭頭所指向位置,在這里使用同步方式還是使用異步方式。從這兩種方式產生的問題角度入手分析他們的優缺點:
- 同步
同步的方式會造成接口響應時間偏差較大,因為有些不調用溯源接口,有些調用。這導致接口在不同時間的行為不一致造成接口響應時間偏差較大。 - 異步
異步方式當前返回的值都是緩存中的值,在特定的時間點上返回的數據是不一致的。可能對冪等性有干擾。
不管同步還是異步都有可能造成緩存擊穿問題,所以更新緩存的過程中最好進行一些排他動作以防止洪泛的發生。
總結
主動更新、被動更新這些技術適應于不同的場景。它們各自有各自的優缺點,在技術設計階段需要考慮實際的業務場景來決策到底使用那種方式合適。這個很多時候是需要設計人員的經驗來進行決策。所以,任何一種軟件設計過程都是一個決策和權衡的過程。
使用緩存的目標就是:通過減少對慢速服務的訪問,來提速。所以在實際的緩存環境中,最主要的目標是減少訪問慢速來達到使用緩存提速的目標。而在這個過程中可以使用的整體方案很多,可以通過不同事項的調整來完成自己的方案。