緩存:高速存取數據的前哨站

緩存的根本思想,源於一個在計算機科學中被反覆驗證的黃金法則——局部性原理(Principle of Locality)。該原理包含兩個層面:

1)時間局部性(Temporal Locality):如果一個數據項被訪問,那麼在不久的將來,它極有可能被再次訪問。例如,一篇熱門新聞的詳情頁、一個爆款商品的庫存信息。

2)空間局部性(Spatial Locality):如果一個數據項被訪問,那麼與它物理位置相鄰的數據項也極有可能被訪問。這個原理在處理器緩存和硬盤預讀中體現得更明顯,在應用層緩存中,可以引申為相關聯的數據也可能被一併訪問。

緩存正是利用了這一原理,將那些被頻繁訪問的“熱點數據”從低速的後端存儲(如數據庫)中複製一份,暫存到高速的存儲介質(通常是內存)中。當後續請求再次需要這些數據時,系統可以直接從高速的緩存中獲取,從而繞過緩慢且昂貴的數據庫訪問路徑。

從局部性原理到一致性模型:深入剖析緩存設計的核心權衡_數據庫

本地緩存和遠程緩存是兩種緩存策略,主要區別在於數據存儲位置和訪問方式。

1)本地緩存(Local Cache):將數據存儲在應用內存中,訪問速度快,適合小量且頻繁訪問的數據。但應用關閉或重啓可能導致數據丟失,多應用實例間可能存在數據一致性問題。常見實現有Guava Cache和Caffeine Cache。

2)遠程緩存(Remote Cache):將數據存儲在網絡服務器上,可以在多應用實例間共享,解決數據一致性問題,且數據不會因應用關閉而丟失。雖訪問速度相對慢,但通過優化網絡和數據結構,性能可得到提升。常見實現有Redis和Memcached。

在現代大型系統中,通常採用多級緩存的策略,即同時使用進程內緩存和分佈式緩存,以兼顧速度與一致性,構建一個縱深防禦體系。

從局部性原理到一致性模型:深入剖析緩存設計的核心權衡_數據_02

一致性
緩存一致性(Cache Consistency)是指在使用緩存的系統中,確保源數據(如數據庫)與緩存數據間保持同步。在併發系統中,由於多個服務節點可能同時進行數據讀寫,維護緩存一致性成為了一個重要且具有挑戰性的問題。
以下是一些常見的處理緩存一致性的策略。
1)旁路緩存(Cache-Aside ):最經典的模式。讀操作先讀緩存,未命中則讀數據庫並回寫緩存;寫操作則先更新數據庫,再失效(Delete)緩存。選擇失效而非更新緩存,是為了避免複雜場景下的併發寫問題。
2)讀/寫穿透(Read/Write-Through):應用層只與緩存交互,由緩存服務自身負責與數據庫的同步。
3)寫回(Write-Back) :寫操作只更新緩存,緩存根據一定策略(如定時、定量)批量異步地將數據刷回數據庫。性能最高,但一致性最弱,且有數據丟失風險。
選擇哪種策略,取決於業務對數據一致性要求的容忍度,這是一個需要在成本、性能和一致性之間做出的權衡。

過載保護
緩存的過載保護的核心目標是防止數據庫過載,因為緩存的主要職責是降低數據庫的壓力並提升數據訪問的效率。當緩存未能找到數據時,請求會直接訪問數據庫,如果這種情況在大量請求中頻繁發生,可能導致數據庫因過載而崩潰。

緩存穿透

緩存穿透(Cache Penetration)是指查詢一個在緩存和數據庫中都不存在的數據。如果每個請求都穿透到數據庫,那麼緩存就變成了擺設,這會給數據庫帶來很大的壓力,影響正常的服務。

為了防止這種情況,可以使用布隆過濾器來判斷一個元素是否在集合中。如果布隆過濾器表示不存在,那麼就肯定不存在;如果布隆過濾器表示可能存在,再去查詢緩存。另一種策略是緩存空結果,即使數據庫中沒有數據,也可以在緩存中存儲一個空對象或空結果,並設置一個較短的過期時間。

從局部性原理到一致性模型:深入剖析緩存設計的核心權衡_數據_03

緩存擊穿
緩存擊穿(Cache Breakdown)是指在使用緩存時,當某個熱點數據的緩存過期或不存在時,大量併發請求同時訪問該數據,導致請求直接落到數據庫上。
為了防止這種情況,在緩存失效時,使用互斥鎖來保證只有一個請求能夠訪問數據源,其他請求等待並從緩存中獲取數據。

緩存雪崩
緩存雪崩(Cache Avalanche)是指在使用緩存系統時,當緩存中的大量熱點數據同時失效或清空時,導致大量請求直接落到數據庫上。
為了防止這種情況,可以通過設置緩存過期時間的隨機性,比如在基礎過期時間上添加一個隨機值,確保緩存數據在不同的時間過期。另外也可以使用限流方式,避免高流量請求同時大道數據庫。