作者:陳彩華
來自:51cto技術棧(ID:blog51cto)
本文主要介紹大型分布式系統中緩存的相關理論,常見的緩存組件以及應用場景。
緩存概述
緩存概述
緩存的分類
緩存主要分為四類,如下圖:
緩存的分類
CDN 緩存
CDN(Content Delivery Network 內容分發網絡)的基本原理是廣泛采用各種緩存服務器,將這些緩存服務器分布到用戶訪問相對集中的地區或網絡中。
在用戶訪問網站時,利用全局負載技術將用戶的訪問指向距離最近的工作正常的緩存服務器上,由緩存服務器直接響應用戶請求。
應用場景:主要緩存靜態資源,例如圖片,視頻。
CDN 緩存應用如下圖:
未使用 CDN 緩存
使用 CDN 緩存
CDN 緩存優點如下圖:
優點
反向代理緩存
反向代理位於應用服務器機房,處理所有對 Web 服務器的請求。
如果用戶請求的頁面在代理服務器上有緩沖的話,代理服務器直接將緩沖內容發送給用戶。
如果沒有緩沖則先向 Web 服務器發出請求,取回數據,本地緩存后再發送給用戶。通過降低向 Web 服務器的請求數,從而降低了 Web 服務器的負載。
應用場景:一般只緩存體積較小靜態文件資源,如 css、js、圖片。
反向代理緩存應用如下圖:
反向代理緩存應用圖
開源實現如下圖:
開源實現
本地應用緩存
指的是在應用中的緩存組件,其最大的優點是應用和 Cache 是在同一個進程內部,請求緩存非常快速,沒有過多的網絡開銷等。
在單應用不需要集群支持或者集群情況下各節點無需互相通知的場景下使用本地緩存較合適。
同時,它的缺點也是應為緩存跟應用程序耦合,多個應用程序無法直接的共享緩存,各應用或集群的各節點都需要維護自己的單獨緩存,對內存是一種浪費。
應用場景:緩存字典等常用數據。
緩存介質如下圖所示:
緩存介質
編程直接實現如下圖:
編程直接實現
Ehcache
基本介紹:Ehcache 是一種基於標准的開源緩存,可提高性能,卸載數據庫並簡化可伸縮性。
它是使用最廣泛的基於 Java 的緩存,因為它功能強大,經過驗證,功能齊全,並與其他流行的庫和框架集成。
Ehcache 可以從進程內緩存擴展到使用 TB 級緩存的混合進程內/進程外部署。
Ehcache 應用場景如下圖:
Ehcache 應用場景
Ehcache 的架構如下圖:
Ehcache 架構圖
Ehcache 的主要特征如下圖:
Ehcache 主要特征
Ehcache 緩存數據過期策略如下圖:
緩存數據過期策略
Ehcache 過期數據淘汰機制:即懶淘汰機制,每次往緩存放入數據的時候,都會存一個時間,在讀取的時候要和設置的時間做 TTL 比較來判斷是否過期。
Guava Cache
基本介紹:Guava Cache 是 Google 開源的 Java 重用工具集庫 Guava 里的一款緩存工具。
Guava Cache 特點與功能如下圖:
Guava Cache 特點與功能
Guava Cache 的應用場景如下圖:
Guava Cache 應用場景
Guava Cache 的數據結構如下圖:
Guava Cache 數據結構圖
Guava Cache 結構特點
Guava Cache 的緩存更新策略如下圖:
Guava Cache 緩存更新策略
Guava Cache 的緩存回收策略如下圖:
Guava Cache 緩存回收策略
分布式緩存
指的是與應用分離的緩存組件或服務,其最大的優點是自身就是一個獨立的應用,與本地應用隔離,多個應用可直接的共享緩存。
分布式緩存的主要應用場景如下圖:
分布式緩存應用場景
分布式緩存的主要接入方式如下圖:
分布式緩存接入方式
下面介紹分布式緩存常見的 2 大開源實現 Memcached 和 Redis。
Memcached
Memcached 是一個高性能,分布式內存對象緩存系統,通過在內存里維護一個統一的巨大的 Hash 表,它能夠用來存儲各種格式的數據,包括圖像、視頻、文件以及數據庫檢索的結果等。
簡單的說就是將數據調用到內存中,然后從內存中讀取,從而大大提高讀取速度。
Memcached 的特點如下圖:
Memcached 特點
Memcached 的基本架構如下圖:
Memcached 基本架構
緩存數據過期策略:LRU(最近最少使用)到期失效策略,在 Memcached 內存儲數據項時,可以指定它在緩存的失效時間,默認為永久。
當 Memcached 服務器用完分配的內存時,失效的數據被首先替換,然后是最近未使用的數據。
數據淘汰內部實現:懶淘汰機制為每次往緩存放入數據的時候,都會存一個時間,在讀取的時候要和設置的時間做 TTL 比較來判斷是否過期。
分布式集群實現:服務端並沒有 “ 分布式 ” 功能。每個服務器都是完全獨立和隔離的服務。 Memcached 的分布式,是由客戶端程序實現的。
數據讀寫流程圖
Memcached 分布式集群實現
Redis
Redis 是一個遠程內存數據庫(非關系型數據庫),性能強勁,具有復制特性以及解決問題而生的獨一無二的數據模型。
它可以存儲鍵值對與 5 種不同類型的值之間的映射,可以將存儲在內存的鍵值對數據持久化到硬盤,可以使用復制特性來擴展讀性能。
Redis 還可以使用客戶端分片來擴展寫性能,內置了 復制(replication),LUA 腳本(Lua scripting),LRU 驅動事件(LRU eviction),事務(transactions) 和不同級別的磁盤持久化(persistence)。
並通過 Redis 哨兵(Sentinel)和自動分區(Cluster)提供高可用性(High Availability)。
Redis 的數據模型如下圖:
Redis 數據模型
Redis 的數據淘汰策略如下圖:
Redis 數據淘汰策略
Redis 的數據淘汰內部實現如下圖:
Redis 數據淘汰內部實現
Redis 的持久化方式如下圖:
Redis 持久化方式
Redis 底層實現部分解析如下圖:
啟動的部分過程圖解
Server 端持久化的部分操作圖解
底層哈希表實現(漸進式Rehash)如下圖:
初始化字典
新增字典元素圖解
Rehash 執行流程
Redis 的緩存設計原則如下圖所示:
Redis 緩存設計原則
Redis 與 Memcached 的比較如下圖:
Redis 與 Memcached 比較
下面主要介紹緩存架構設計常見問題以及解決方案,業界案例。
分層緩存架構設計
緩存帶來的復雜度問題
常見的問題主要包括如下幾點:
-
數據一致性
-
緩存穿透
-
緩存雪崩
-
緩存高可用
-
緩存熱點
下面逐一介紹分析這些問題以及相應的解決方案。
數據一致性
因為緩存屬於持久化數據的一個副本,因此不可避免的會出現數據不一致問題,導致臟讀或讀不到數據的情況。
數據不一致,一般是因為網絡不穩定或節點故障導致問題出現的常見 3 個場景以及解決方案:
緩存穿透
緩存一般是 Key-Value 方式存在,當某一個 Key 不存在時會查詢數據庫,假如這個 Key,一直不存在,則會頻繁的請求數據庫,對數據庫造成訪問壓力。
主要解決方案:
-
對結果為空的數據也進行緩存,當此 Key 有數據后,清理緩存。
-
一定不存在的 Key,采用布隆過濾器,建立一個大的 Bitmap 中,查詢時通過該 Bitmap 過濾。
緩存雪崩
緩存高可用
緩存是否高可用,需要根據實際的場景而定,並不是所有業務都要求緩存高可用,需要結合具體業務,具體情況進行方案設計,例如臨界點是否對后端的數據庫造成影響。
主要解決方案:
-
分布式:實現數據的海量緩存。
-
復制:實現緩存數據節點的高可用。
緩存熱點
一些特別熱點的數據,高並發訪問同一份緩存數據,導致緩存服務器壓力過大。
解決:復制多份緩存副本,把請求分散到多個緩存服務器上,減輕緩存熱點導致的單台緩存服務器壓力
業界案例
案例主要參考新浪微博陳波的技術分享,可以查看原文《百億級日訪問量的應用如何做緩存架構設計?》
技術挑戰
Feed 緩存架構圖
架構特點
新浪微博把 SSD 應用在分布式緩存場景中,將傳統的 Redis/MC + MySQL 方式,擴展為 Redis/MC + SSD Cache + MySQL 方式。
SSD Cache 作為 L2 緩存使用,第一降低了 MC/Redis 成本過高,容量小的問題,也解決了穿透 DB 帶來的數據庫訪問壓力。
主要在數據架構、性能、儲存成本、服務化等不同方面進行了優化增強。
...