大型分布式系統(tǒng)中的緩存架構(gòu)
點(diǎn)擊上方藍(lán)色字體,選擇“設(shè)為星標(biāo)”
回復(fù)”學(xué)習(xí)資料“獲取學(xué)習(xí)寶典
作者:陳彩華
來(lái)自:51cto技術(shù)棧(ID:blog51cto)
本文主要介紹大型分布式系統(tǒng)中緩存的相關(guān)理論,常見(jiàn)的緩存組件以及應(yīng)用場(chǎng)景。
緩存概述

緩存概述
緩存的分類(lèi)
緩存主要分為四類(lèi),如下圖:

緩存的分類(lèi)
CDN 緩存
CDN(Content Delivery Network 內(nèi)容分發(fā)網(wǎng)絡(luò))的基本原理是廣泛采用各種緩存服務(wù)器,將這些緩存服務(wù)器分布到用戶(hù)訪問(wèn)相對(duì)集中的地區(qū)或網(wǎng)絡(luò)中。
在用戶(hù)訪問(wèn)網(wǎng)站時(shí),利用全局負(fù)載技術(shù)將用戶(hù)的訪問(wèn)指向距離最近的工作正常的緩存服務(wù)器上,由緩存服務(wù)器直接響應(yīng)用戶(hù)請(qǐng)求。
應(yīng)用場(chǎng)景:主要緩存靜態(tài)資源,例如圖片,視頻。
CDN 緩存應(yīng)用如下圖:

未使用 CDN 緩存

使用 CDN 緩存
CDN 緩存優(yōu)點(diǎn)如下圖:

優(yōu)點(diǎn)
反向代理緩存
反向代理位于應(yīng)用服務(wù)器機(jī)房,處理所有對(duì) Web 服務(wù)器的請(qǐng)求。
如果用戶(hù)請(qǐng)求的頁(yè)面在代理服務(wù)器上有緩沖的話(huà),代理服務(wù)器直接將緩沖內(nèi)容發(fā)送給用戶(hù)。
如果沒(méi)有緩沖則先向 Web 服務(wù)器發(fā)出請(qǐng)求,取回?cái)?shù)據(jù),本地緩存后再發(fā)送給用戶(hù)。通過(guò)降低向 Web 服務(wù)器的請(qǐng)求數(shù),從而降低了 Web 服務(wù)器的負(fù)載。
應(yīng)用場(chǎng)景:一般只緩存體積較小靜態(tài)文件資源,如 css、js、圖片。
反向代理緩存應(yīng)用如下圖:

反向代理緩存應(yīng)用圖
開(kāi)源實(shí)現(xiàn)如下圖:

開(kāi)源實(shí)現(xiàn)
本地應(yīng)用緩存
指的是在應(yīng)用中的緩存組件,其最大的優(yōu)點(diǎn)是應(yīng)用和 Cache 是在同一個(gè)進(jìn)程內(nèi)部,請(qǐng)求緩存非常快速,沒(méi)有過(guò)多的網(wǎng)絡(luò)開(kāi)銷(xiāo)等。
在單應(yīng)用不需要集群支持或者集群情況下各節(jié)點(diǎn)無(wú)需互相通知的場(chǎng)景下使用本地緩存較合適。
同時(shí),它的缺點(diǎn)也是應(yīng)為緩存跟應(yīng)用程序耦合,多個(gè)應(yīng)用程序無(wú)法直接的共享緩存,各應(yīng)用或集群的各節(jié)點(diǎn)都需要維護(hù)自己的單獨(dú)緩存,對(duì)內(nèi)存是一種浪費(fèi)。
應(yīng)用場(chǎng)景:緩存字典等常用數(shù)據(jù)。
緩存介質(zhì)如下圖所示:

緩存介質(zhì)
編程直接實(shí)現(xiàn)如下圖:

編程直接實(shí)現(xiàn)
Ehcache
基本介紹:Ehcache 是一種基于標(biāo)準(zhǔn)的開(kāi)源緩存,可提高性能,卸載數(shù)據(jù)庫(kù)并簡(jiǎn)化可伸縮性。
它是使用最廣泛的基于 Java 的緩存,因?yàn)樗δ軓?qiáng)大,經(jīng)過(guò)驗(yàn)證,功能齊全,并與其他流行的庫(kù)和框架集成。
Ehcache 可以從進(jìn)程內(nèi)緩存擴(kuò)展到使用 TB 級(jí)緩存的混合進(jìn)程內(nèi)/進(jìn)程外部署。
Ehcache 應(yīng)用場(chǎng)景如下圖:

Ehcache 應(yīng)用場(chǎng)景
Ehcache 的架構(gòu)如下圖:

Ehcache 架構(gòu)圖
Ehcache 的主要特征如下圖:

Ehcache 主要特征
Ehcache 緩存數(shù)據(jù)過(guò)期策略如下圖:

緩存數(shù)據(jù)過(guò)期策略
Ehcache 過(guò)期數(shù)據(jù)淘汰機(jī)制:即懶淘汰機(jī)制,每次往緩存放入數(shù)據(jù)的時(shí)候,都會(huì)存一個(gè)時(shí)間,在讀取的時(shí)候要和設(shè)置的時(shí)間做 TTL 比較來(lái)判斷是否過(guò)期。
Guava Cache
基本介紹:Guava Cache 是 Google 開(kāi)源的 Java 重用工具集庫(kù) Guava 里的一款緩存工具。
Guava Cache 特點(diǎn)與功能如下圖:

Guava Cache 特點(diǎn)與功能
Guava Cache 的應(yīng)用場(chǎng)景如下圖:

Guava Cache 應(yīng)用場(chǎng)景
Guava Cache 的數(shù)據(jù)結(jié)構(gòu)如下圖:

Guava Cache 數(shù)據(jù)結(jié)構(gòu)圖

Guava Cache 結(jié)構(gòu)特點(diǎn)
Guava Cache 的緩存更新策略如下圖:

Guava Cache 緩存更新策略
Guava Cache 的緩存回收策略如下圖:

Guava Cache 緩存回收策略
分布式緩存
指的是與應(yīng)用分離的緩存組件或服務(wù),其最大的優(yōu)點(diǎn)是自身就是一個(gè)獨(dú)立的應(yīng)用,與本地應(yīng)用隔離,多個(gè)應(yīng)用可直接的共享緩存。
分布式緩存的主要應(yīng)用場(chǎng)景如下圖:

分布式緩存應(yīng)用場(chǎng)景
分布式緩存的主要接入方式如下圖:

分布式緩存接入方式
下面介紹分布式緩存常見(jiàn)的 2 大開(kāi)源實(shí)現(xiàn) Memcached 和 Redis。
Memcached
Memcached 是一個(gè)高性能,分布式內(nèi)存對(duì)象緩存系統(tǒng),通過(guò)在內(nèi)存里維護(hù)一個(gè)統(tǒng)一的巨大的 Hash 表,它能夠用來(lái)存儲(chǔ)各種格式的數(shù)據(jù),包括圖像、視頻、文件以及數(shù)據(jù)庫(kù)檢索的結(jié)果等。
簡(jiǎn)單的說(shuō)就是將數(shù)據(jù)調(diào)用到內(nèi)存中,然后從內(nèi)存中讀取,從而大大提高讀取速度。
Memcached 的特點(diǎn)如下圖:

Memcached 特點(diǎn)
Memcached 的基本架構(gòu)如下圖:

Memcached 基本架構(gòu)
緩存數(shù)據(jù)過(guò)期策略:LRU(最近最少使用)到期失效策略,在 Memcached 內(nèi)存儲(chǔ)數(shù)據(jù)項(xiàng)時(shí),可以指定它在緩存的失效時(shí)間,默認(rèn)為永久。
當(dāng) Memcached 服務(wù)器用完分配的內(nèi)存時(shí),失效的數(shù)據(jù)被首先替換,然后是最近未使用的數(shù)據(jù)。
數(shù)據(jù)淘汰內(nèi)部實(shí)現(xiàn):懶淘汰機(jī)制為每次往緩存放入數(shù)據(jù)的時(shí)候,都會(huì)存一個(gè)時(shí)間,在讀取的時(shí)候要和設(shè)置的時(shí)間做 TTL 比較來(lái)判斷是否過(guò)期。
分布式集群實(shí)現(xiàn):服務(wù)端并沒(méi)有 “ 分布式 ” 功能。每個(gè)服務(wù)器都是完全獨(dú)立和隔離的服務(wù)。Memcached 的分布式,是由客戶(hù)端程序?qū)崿F(xiàn)的。

數(shù)據(jù)讀寫(xiě)流程圖

Memcached 分布式集群實(shí)現(xiàn)
Redis
Redis 是一個(gè)遠(yuǎn)程內(nèi)存數(shù)據(jù)庫(kù)(非關(guān)系型數(shù)據(jù)庫(kù)),性能強(qiáng)勁,具有復(fù)制特性以及解決問(wèn)題而生的獨(dú)一無(wú)二的數(shù)據(jù)模型。
它可以存儲(chǔ)鍵值對(duì)與 5 種不同類(lèi)型的值之間的映射,可以將存儲(chǔ)在內(nèi)存的鍵值對(duì)數(shù)據(jù)持久化到硬盤(pán),可以使用復(fù)制特性來(lái)擴(kuò)展讀性能。
Redis 還可以使用客戶(hù)端分片來(lái)擴(kuò)展寫(xiě)性能,內(nèi)置了 復(fù)制(replication),LUA 腳本(Lua scripting),LRU 驅(qū)動(dòng)事件(LRU eviction),事務(wù)(transactions) 和不同級(jí)別的磁盤(pán)持久化(persistence)。
并通過(guò) Redis 哨兵(Sentinel)和自動(dòng)分區(qū)(Cluster)提供高可用性(High Availability)。
Redis 的數(shù)據(jù)模型如下圖:

Redis 數(shù)據(jù)模型
Redis 的數(shù)據(jù)淘汰策略如下圖:

Redis 數(shù)據(jù)淘汰策略
Redis 的數(shù)據(jù)淘汰內(nèi)部實(shí)現(xiàn)如下圖:

Redis 數(shù)據(jù)淘汰內(nèi)部實(shí)現(xiàn)
Redis 的持久化方式如下圖:

Redis 持久化方式
Redis 底層實(shí)現(xiàn)部分解析如下圖:

啟動(dòng)的部分過(guò)程圖解

Server 端持久化的部分操作圖解
底層哈希表實(shí)現(xiàn)(漸進(jìn)式Rehash)如下圖:

初始化字典

新增字典元素圖解

Rehash 執(zhí)行流程
Redis 的緩存設(shè)計(jì)原則如下圖所示:

Redis 緩存設(shè)計(jì)原則
Redis 與 Memcached 的比較如下圖:

Redis 與 Memcached 比較
下面主要介紹緩存架構(gòu)設(shè)計(jì)常見(jiàn)問(wèn)題以及解決方案,業(yè)界案例。
分層緩存架構(gòu)設(shè)計(jì)

緩存帶來(lái)的復(fù)雜度問(wèn)題
常見(jiàn)的問(wèn)題主要包括如下幾點(diǎn):
數(shù)據(jù)一致性
緩存穿透
緩存雪崩
緩存高可用
緩存熱點(diǎn)
下面逐一介紹分析這些問(wèn)題以及相應(yīng)的解決方案。
數(shù)據(jù)一致性
因?yàn)榫彺鎸儆诔志没瘮?shù)據(jù)的一個(gè)副本,因此不可避免的會(huì)出現(xiàn)數(shù)據(jù)不一致問(wèn)題,導(dǎo)致臟讀或讀不到數(shù)據(jù)的情況。
數(shù)據(jù)不一致,一般是因?yàn)榫W(wǎng)絡(luò)不穩(wěn)定或節(jié)點(diǎn)故障導(dǎo)致問(wèn)題出現(xiàn)的常見(jiàn) 3 個(gè)場(chǎng)景以及解決方案:

緩存穿透
緩存一般是 Key-Value 方式存在,當(dāng)某一個(gè) Key 不存在時(shí)會(huì)查詢(xún)數(shù)據(jù)庫(kù),假如這個(gè) Key,一直不存在,則會(huì)頻繁的請(qǐng)求數(shù)據(jù)庫(kù),對(duì)數(shù)據(jù)庫(kù)造成訪問(wèn)壓力。
主要解決方案:
對(duì)結(jié)果為空的數(shù)據(jù)也進(jìn)行緩存,當(dāng)此 Key 有數(shù)據(jù)后,清理緩存。
一定不存在的 Key,采用布隆過(guò)濾器,建立一個(gè)大的 Bitmap 中,查詢(xún)時(shí)通過(guò)該 Bitmap 過(guò)濾。
緩存雪崩

緩存高可用
緩存是否高可用,需要根據(jù)實(shí)際的場(chǎng)景而定,并不是所有業(yè)務(wù)都要求緩存高可用,需要結(jié)合具體業(yè)務(wù),具體情況進(jìn)行方案設(shè)計(jì),例如臨界點(diǎn)是否對(duì)后端的數(shù)據(jù)庫(kù)造成影響。
主要解決方案:
分布式:實(shí)現(xiàn)數(shù)據(jù)的海量緩存。
復(fù)制:實(shí)現(xiàn)緩存數(shù)據(jù)節(jié)點(diǎn)的高可用。
緩存熱點(diǎn)
一些特別熱點(diǎn)的數(shù)據(jù),高并發(fā)訪問(wèn)同一份緩存數(shù)據(jù),導(dǎo)致緩存服務(wù)器壓力過(guò)大。
解決:復(fù)制多份緩存副本,把請(qǐng)求分散到多個(gè)緩存服務(wù)器上,減輕緩存熱點(diǎn)導(dǎo)致的單臺(tái)緩存服務(wù)器壓力
業(yè)界案例
案例主要參考新浪微博陳波的技術(shù)分享,可以查看原文《百億級(jí)日訪問(wèn)量的應(yīng)用如何做緩存架構(gòu)設(shè)計(jì)?》
技術(shù)挑戰(zhàn)

Feed 緩存架構(gòu)圖

架構(gòu)特點(diǎn)
新浪微博把 SSD 應(yīng)用在分布式緩存場(chǎng)景中,將傳統(tǒng)的 Redis/MC + MySQL 方式,擴(kuò)展為 Redis/MC + SSD Cache + MySQL 方式。
SSD Cache 作為 L2 緩存使用,第一降低了 MC/Redis 成本過(guò)高,容量小的問(wèn)題,也解決了穿透 DB 帶來(lái)的數(shù)據(jù)庫(kù)訪問(wèn)壓力。
主要在數(shù)據(jù)架構(gòu)、性能、儲(chǔ)存成本、服務(wù)化等不同方面進(jìn)行了優(yōu)化增強(qiáng)。


后臺(tái)回復(fù)?學(xué)習(xí)資料?領(lǐng)取學(xué)習(xí)視頻
如有收獲,點(diǎn)個(gè)在看,誠(chéng)摯感謝

