概述
快取更新是指在資料發生變化時,保持快取和資料庫的資料一致性的問題。如果快取和資料庫的資料不一致,會導致使用者看到過期或者錯誤的資料,影響業務邏輯和使用者體驗。
為了實現快取更新,我們可以採用以下四種方式其中的一種:
-
Cache Aside策略:應用程式直接與資料庫和快取互動,並負責維護快取的一致性
- 查詢:先查詢快取,如果快取中沒有,則查詢資料庫,並將結果寫入快取
- 更新:先更新資料庫,然後刪除快取或者更新快取
-
Read/Write Through策略:應用程式只和快取互動,而是使用快取與資料庫互動
- 查詢:先查詢快取,如果快取中沒有,則快取從資料庫中載入資料,並寫入快取
- 更新:先更新快取,再由快取同步更新資料庫
-
Write Behind 策略:應用程式只和快取互動。當有資料更新時,只更新快取,不直接更新資料庫,改為非同步的方式更新資料庫
-
Refresh-Ahead策略:應用程式只和快取互動,由後臺服務與資料庫互動
- 查詢:只查詢快取
- 更新:由後臺服務自動從資料庫中查詢最新的資料,並將資料寫入快取中,
不同於以上三種,應用程式無需等待資料的重新整理,也無需自己去觸發資料的重新整理,而是後臺服務來完成這些操作
Cache Aside
Cache Aside策略上文已經介紹過了,它是透過應用層面來實現的,分為兩種場景:
- Cache Aside查詢策略
- Cache Aside更新策略
Cache Aside查詢策略
如下圖所示:透過程式碼查詢快取,快取命中則返回,如果沒有命中則查詢資料庫並設定值
Cache Aside更新策略
如下圖所示:透過程式碼更新快取,先更新資料庫,後更新快取
這種策略簡單易用,但是需要維護快取和資料庫的一致性,可能出現快取穿透或快取雪崩的問題,一般採用延遲雙刪來保證最終一致性
延遲雙刪
延遲雙刪是一種保證資料一致性的常用策略,它的基本思想是在更新資料庫後,先刪除快取,然後等待一段時間,再次刪除快取。這樣做的目的是為了防止在資料庫和快取主從同步的過程中,有其他請求查詢到舊的快取資料,並寫回到快取中,具體的流程如下:
- 更新資料庫資料
- 刪除快取資料
- 休眠一段時間,時間依據資料的讀取耗費的時間而定。
- 再次刪除快取資料
延遲雙刪的休眠時間是根據業務讀取資料平均耗時來設定的,目的是確保讀請求可以結束,寫請求可以刪除讀請求造成的髒資料的問題。一般來說,休眠時間可以設定為500毫秒左右,但具體還要根據實際情況調整。休眠時間設定過長會影響效能和實時性,設定過短會導致資料不一致的風險。
延遲雙刪的優點是簡單易實現,能夠提高資料的最終一致性。但是延遲雙刪的缺點也非常明顯:
- 延遲雙刪不是強一致性,有等待環節,如果系統要求低延時,這種場景就不合適了
- 延遲雙刪不適合“秒殺”這種頻繁修改資料和要求資料強一致的場景
- 延遲雙刪的延時時間是一個預估值,不能確保資料庫和redis在這個時間段內都實時同步或持久化成功了
- 延遲雙刪不能完全避免redis存在髒資料的問題,只能減輕這個問題,要想徹底解決,還需要用到同步鎖解決
Read/Write Through
Read/Write Through只與快取做互動,分為兩種場景:
- Read/Write Through查詢策略
- Read/Write Through更新策略
Read/Write Through查詢策略
如下圖所示:先查詢快取,如果快取沒有,由快取去資料庫查詢,而不是應用層,查詢後更新快取
Read/Write Through更新策略
如下圖所示:先更新快取,再由快取同步更新資料庫
Write Behind
Write Behind 策略是指在寫入資料時,只更新快取中的資料,然後建立一個非同步任務或者定時任務來批次更新資料庫中的資料。這樣,應用程式無需等待資料庫的響應,也無需自己去同步更新資料庫和快取,而是交由快取服務來完成這些操作,如下圖所示:
Refresh-Ahead
是指在讀取資料時,如果快取中的資料即將過期,則由CDC服務自動從資料庫中查詢最新的資料,並將資料寫入快取中,然後返回給應用程式。不同於以上三種,應用程式無需等待資料的重新整理,也無需自己去觸發資料的重新整理,而是交由CDC服務來完成這些操作。
Refresh-Ahead 模式的工作原理如下:
- 當客戶端訪問快取中的某個資料項時,首先檢查該資料項是否即將過期,如果是,則啟動一個後臺執行緒或服務去從資料來源中獲取最新的資料,並替換掉快取中的舊資料;同時返回給客戶端
- 如果該資料還沒有即將過期,則直接返回給客戶端
- 如果該資料項已經過期,則從資料來源中獲取最新的資料,並替換掉快取中的舊資料,並返回給客戶端新資料。
CDC
CDC,全稱為Change Data Capture。它是一種軟體設計模式,可以讓使用者檢測和管理資料來源的增量變化,並將這些變化應用到企業的下游環節。CDC 技術可以實時捕獲資料的變化,只需要很少的資源,而不是全量資料批處理。CDC 可以幫助實現資料同步、資料倉儲載入、資料分析等場景。
CDC 的優點:
- 提高資料訪問的效能和效率,因為它避免了重複地查詢整個資料集,而只需要獲取增量資料
- 提高資料一致性和可靠性,因為它可以及時地將資料來源的變化同步到下游系統,避免了資料過期或丟失的風險
- 提高資料分析和洞察的能力,因為它可以實時地反映資料的狀態
- 提高資料整合和轉換的靈活性和可擴充套件性,因為它可以適應不同型別和結構的資料來源和目標,支援多種場景和用例。
CDC 的應用場景:
- 資料同步:可將資料來源中的變化同步到其他資料庫或資料儲存中,例如快取、搜尋索引、備份等。
- 資料倉儲載入:可將資料來源中的變化載入到資料倉儲或資料湖中,支援離線或實時的資料分析和報告。
- 資料分析:可將資料來源中的變化傳送到流式處理平臺或機器學習平臺中,支援實時或批次的資料處理和建模
- 資料觸發:可將資料來源中的變化作為觸發器,啟用其他系統或服務中的業務流程或邏輯,例如通知、審計、驗證等
CDC 的實現方式有多種,其中比較成熟的開源專案就是Debezium。它為CDC提供了一套低延遲的資料流平臺支援多種資料庫。例如:MongoDB、MySQL、PostgreSQL、SQL Server、Oracle等等。使用Debezium監控資料來源,並使用Kafka作為訊息服務,將資料來源的變化作為事件傳送到快取。這樣,快取可以非同步地接收和處理資料變化,而不需要定期地查詢資料來源
四種策略的選擇
我們介紹了四種常見的快取更新策略:Cache Aside
、Read/Write Through
、Write Behind Caching
、Refresh-Ahead
。在實際應用時,應該結合具體業務和應用場景來選擇合適的快取策略,接下來我們透過對比效能、資料一致性、冗餘資料、程式碼複雜度、業務邏輯、可靠性這幾個點來說明:
策略 | 效能 | 一致性 | 冗餘資料 | 程式碼複雜度 | 業務邏輯 | 可靠性 |
---|---|---|---|---|---|---|
Cache Aside | 較高 | 較低 | 較少 | 較高 | 較複雜 | 較低 |
Read/Write Through | 較低 | 最高 | 較多 | 最高 | 最簡單 | 最高 |
Write Behind Caching | 最高 | 最低 | 較少 | 較低 | 較簡單 | 較高 |
Refresh-Ahead | 次高 | 次高 | 較多 | 最高 | 較複雜 | 最高 |
注意:
Refresh-Ahead策略是假定無CDC的情況下進行對比的
效能
Cache Aside
的效能較高,它只在快取未命中時才訪問資料庫Read/Write Through
的效能較低,它在每次讀寫時都需要訪問資料庫Write Behind Caching
的效能最高,它只在快取未命中時才訪問資料庫,而寫入操作是非同步的Refresh-Ahead
的效能介於Cache Aside
和Write Behind Caching
之間,它只在即將過期時才訪問資料庫,並且寫入操作也是非同步的
資料一致性
Cache Aside
的資料一致性較低,它只在快取未命中時才更新快取,而寫入操作則是直接更新資料庫,並將快取中的資料刪除或更新Read/Write Through
的資料一致性最高,它在每次讀寫時都更新資料庫和快取Write Behind Caching
的資料一致性最低,它只在快取未命中時才更新快取,而寫入操作則是先更新快取,並在非同步更新資料庫,有較大的延遲。Refresh-Ahead
的資料一致性介於Read/Write Through
和Cache Aside
之間,它保證了快取中的資料總是最新的,但是有一定的延遲
冗餘資料
Cache Aside
的冗餘資料較少,它只將經常訪問的資料儲存到快取中Read/Write Through
的冗餘資料較多,它需要將資料庫的所有資料都儲存到快取中Write Behind Caching
的冗餘資料與Cache Aside
相同,因為它也只將經常訪問的資料儲存到快取中Refresh-Ahead
的冗餘資料與Read/Write Through
相同,它也需要將資料庫的所有資料都儲存到快取中
程式碼複雜度
Cache Aside
的程式碼複雜度較高,它需要同時與快取和資料庫互動,並處理可能出現的異常情況Read/Write Through
的程式碼複雜度最高,它需要實現資料庫的讀寫介面Write Behind Caching
的程式碼複雜度較低,它只需要實現簡單的快取操作,並在非同步執行資料庫寫入操作Refresh-Ahead
的程式碼複雜度與Read/Write Through
相同,他它需要實現資料庫的讀寫介面(關於這點可以使用Debezium)
業務邏輯
Cache Aside
的業務邏輯較複雜,它需要同時與快取和資料庫互動,且返回的資料是最新的Read/Write Through
的業務邏輯最簡單,它只與快取互動,且返回的資料是最新的Write Behind Caching
的業務邏輯較簡單,它也只與快取互動,且返回的資料是最新的,由於是非同步更新,所以比Read/Write Through
要複雜一些Refresh-Ahead
的業務邏輯較複雜,它會同時與快取和資料庫互動,需要處理可能出現的異常情況,且返回的資料有可能是舊的,也有可能是新的(關於這點也可以使用Debezium)
可靠性
Cache Aside
的可靠性較低,因為它將快取作為資料庫的輔助層Read/Write Through
的可靠性最高,因為它將快取作為資料庫的代理層Write Behind Caching
的可靠性較高,因為它將快取作為資料庫前置層Refresh-Ahead
的可靠性與Read/Write Through
相同,因為它也將快取作為資料庫的代理層