天天看點

一文帶領你認識企業級别的緩存技術解決方案的運作原理和開發實戰

作者:小心程式猿QAQ

資料不一緻的原因

在引入緩存後,資料就會分散在兩個不同的資料源中。由于資料的更新是實時的,是以很難保持資料的一緻性,除非采用強一緻性方案。在探索适當的解決方案之前,我們需要分析導緻資料不一緻的主要原因,并針對性地解決這些問題:

一文帶領你認識企業級别的緩存技術解決方案的運作原理和開發實戰

邏輯失敗導緻的資料不一緻

之前我們詳細分析了三種更新政策。在并發的情況下,無論是先删除緩存再更新資料庫,還是先更新資料庫再使緩存過期,都可能導緻資料不一緻的情況。這主要是因為在并發操作下,異步讀寫請求的時序可能導緻了資料不一緻,我們将其稱為“邏輯失敗”。解決這種由并發操作時序導緻的問題的核心思想是将異步操作串行化執行。

實體失敗導緻的資料不一緻

Cache Aside 模式中,先更新資料庫再删除緩存以及異步雙删政策等在同一個事務中,通常情況下,當使用分布式緩存時,如果緩存服務耗時較長,将更新資料庫和使緩存失效操作放在同一個事務中,會導緻大量的資料庫連接配接挂起,嚴重降低系統性能,甚至可能因為資料庫連接配接數過多而導緻系統崩潰。這種由于緩存操作失敗而導緻的資料不一緻稱為"實體失敗"。大多數情況下,我們會采用重試的方式解決實體失敗的情況。

資料一緻性的解決方案

  • 實體失敗導緻的資料不一緻:在絕大部分業務場景中,我們通常追求的是最終一緻性。為了解決因實體失敗而導緻的資料不一緻,常見的解決方案包括消費消息異步删除緩存和訂閱Binlog。
  • 邏輯失敗導緻的資料不一緻:而對于邏輯失敗導緻的資料不一緻,常用的解決方案則是通過隊列實作異步操作的同步化。

消費消息異步删除緩存

當涉及到消費消息異步删除緩存時,需要考慮資料一緻性的問題。在這種情況下,如果緩存的删除操作是在消息消費後異步進行的,那麼存在以下兩種可能的資料一緻性問題:

消息處理失敗導緻的資料不一緻:如果消息消費過程中發生了錯誤,導緻緩存删除操作未能正确執行,資料就會出現不一緻。為了解決這個問題,可以采取一些措施,如記錄消費狀态、定期檢查未完成的消息、重試消費等。

延遲删除導緻的資料不一緻:由于異步删除緩存的操作通常需要一定的時間,是以在緩存删除完成之前,可能會出現查詢時擷取到已經被删除的資料的情況。這種延遲删除可能會導緻短暫的資料不一緻。為了解決這個問題,可以采用一些方法,如使用合适的緩存過期時間、添加版本控制或标記來跟蹤資料更新狀态等。

主要流程如下圖所示

一文帶領你認識企業級别的緩存技術解決方案的運作原理和開發實戰

為了確定資料一緻性,可以考慮以下幾點建議:

使用事務:如果可能的話,在消費消息和删除緩存的操作之間使用事務,確定它們要麼都成功,要麼都失敗。這可以減少資料不一緻的可能性。

監控和日志記錄:設定監控機制來檢測消息消費和緩存删除的狀态,并記錄日志以便排查問題和進行故障恢複。

定期校驗和修複:定期檢查資料一緻性,并在發現問題時進行修複。可以編寫一些腳本或工具來掃描資料并修複不一緻性。

綜上所述,要確定消費消息異步删除緩存的資料一緻性,需要采取适當的措施來處理潛在的問題,并實施監控和修複機制來確定資料的準确性和一緻性。

訂閱Binlog

主要流程如下圖所示:

一文帶領你認識企業級别的緩存技術解決方案的運作原理和開發實戰

利用隊列串行化

在分析緩存旁路模式(cache aside pattern)時,我們發現在高并發情況下可能會發生資料不一緻的情況,盡管這種情況發生的機率很低。

此外,在并發讀寫的情況下,如果我們先删除緩存再更新資料庫,也可能導緻資料不一緻的問題。這些問題都是由于并發時序導緻的,即寫請求還未完成時,讀請求就會讀取到舊資料。

然而,如果我們能夠確定請求的處理能夠串行化,即讀請求在寫請求之後處理,那麼就能保證讀請求能夠讀取到最新的資料,進而避免資料不一緻的問題。綜上所述,我們在處理資料一緻性的問題時需要考慮并發場景下請求處理的時序關系。

具體分析

采用隊列将請求進行串行化。每個隊列隻對應一個工作線程。對于更新資料的寫請求,我們将其放入隊列中,等待異步處理;對于讀請求,如果可以從緩存中擷取資料,則直接傳回;如果緩存中沒有資料,我們将讀請求放入隊列中,等待寫請求完成資料更新後再處理。

存在的問題

一文帶領你認識企業級别的緩存技術解決方案的運作原理和開發實戰
  • 讀請求長時間阻塞:确實,如果隊列中有多個寫請求,讀請求可能會長時間阻塞。為了解決這個問題,可以設定一個适當的逾時時間,并在逾時後直接從資料庫中讀取資料傳回。這可以確定系統在高并發情況下的響應性。同時,在進行壓力測試時,應注意隊列中累積的寫請求數量,如果積壓過多,可以考慮隊列的優化措施或相應解決方案。
  • 多個隊列分散壓力:是的,通過根據資料項進行哈希等路由方式,建立多個隊列并行執行可以提高系統的吞吐量。這樣可以将負載均衡到多個隊列上,降低單個隊列的壓力,進而提高整體性能。
  • 操作複雜需要考慮全面:确實,将請求進行串行化通過隊列是一種有效的資料一緻性方案,但也需要考慮到隊列的可用性、阻塞情況以及容災恢複政策等問題。確定隊列的穩定性和可靠性非常重要,盡量避免單點故障,并建立相應的容災方案。

最終一緻性

除了提到的三種通用方法,為緩存設定過期時間并定期進行全量同步也是一種接近最終一緻性的簡單有效方式。通過設定合理的過期時間,可以在緩存中保持資料的一緻性,并定期進行全量同步,以確定緩存中的資料與資料庫中的資料保持一緻。這種方法可以在一定程度上提高系統的性能,并減少對隊列串行化的依賴。

總結而言,選擇适合業務場景的技術方案非常重要。在決策時,請綜合考慮系統性能、資料一緻性要求以及資源的限制,并進行權衡和優化。

繼續閱讀