這是小卷對分布式系統(tǒng)架構(gòu)學(xué)習(xí)的第11篇文章,今天了解分布式緩存的理論知識以及Redis集群。
分布式緩存也是面試常見的問題,通常面試官會問為什么要用緩存,以及用的Redis是哪種模式,用的過程中遇到哪些問題這些
1. AP還是CP
Redis 集群就是典型的 AP 式,它具有高性能、高可用等特點,但它卻并不保證強(qiáng)一致性。
而能夠保證強(qiáng)一致性的 ZooKeeper、Doozerd、Etcd 等框架,吞吐量比不過Redis,通常不會用作“緩存框架”,而是作為通知、協(xié)調(diào)、隊列、分布式鎖等使用
2.透明多級緩存TMC
實際開發(fā)中,同時搭配進(jìn)程內(nèi)緩存和分布式緩存,來構(gòu)成透明多級緩存(Transparent Multilevel Cache,TMC)
多級緩存的查詢過程如下圖:

缺點:代碼侵入性大,由開發(fā)人員維護(hù)管理
一、二級緩存數(shù)據(jù)不一致問題解決:
- 設(shè)計原則:變更以分布式緩存中的數(shù)據(jù)為準(zhǔn),查詢以進(jìn)程內(nèi)緩存數(shù)據(jù)優(yōu)先
3.實現(xiàn)方案
3.1 memcached緩存
在服務(wù)端,memcached集群環(huán)境實際就是一個個memcached服務(wù)器的堆積
cache的分布式主要是在客戶端實現(xiàn),通過客戶端的路由處理來達(dá)到分布式解決方案的目的。客戶端做路由的原理,是在每次存取某key的value時,通過一致性哈希算法把key映射到某臺memcached服務(wù)器node上。
如下是memcached客戶端路由過程:

3.2 Redis緩存
與memcached客戶端支持分布式方案不同,Redis更傾向于在服務(wù)端構(gòu)建分布式存儲


以Redis集群模式為例,它沒有中心節(jié)點,具有線性可伸縮的功能。
節(jié)點與節(jié)點之間通過二進(jìn)制協(xié)議進(jìn)行通信,節(jié)點與客戶端之間通過ascii協(xié)議進(jìn)行通信
在數(shù)據(jù)的放置策略上,Redis Cluster將整個key的數(shù)值域分成2的14次方16384個hash槽,每個節(jié)點上可以存儲一個或多個hash槽,也就是說當(dāng)前Redis Cluster支持的最大節(jié)點數(shù)就是16384
總結(jié)下:數(shù)據(jù)hash分布在不同redis節(jié)點實例,主/從切換采用Sentinel
寫:只會寫master Instance,從sentinel獲取當(dāng)前的master instance;
讀:從redis node中基于權(quán)重選取一個實例讀取,失敗/超時則輪詢其他實例;
要想詳細(xì)了解redis的面試過程中的問題,可以參考下面的思維導(dǎo)圖自行整理:

4. 緩存風(fēng)險
4.1 緩存穿透
緩存風(fēng)險問題也是面試常考的八股文題目,這里還是簡單說明下
緩存穿透:查詢的數(shù)據(jù)在數(shù)據(jù)庫里根本不存在,緩存里也不會有,這樣的請求每次都不會命中緩存,會請求到末端數(shù)據(jù)庫。這種查詢不存在數(shù)據(jù)的現(xiàn)象就是緩存穿透
解決辦法:
- 對業(yè)務(wù)邏輯本身不能避免的緩存穿透:對返回為空的Key值進(jìn)行緩存,如果數(shù)據(jù)庫中對該key插入新記錄,就需要主動清理緩存的key值。
- 惡意攻擊導(dǎo)致的緩存穿透:緩存之前設(shè)置一個布隆過濾器來解決,思路就是判斷請求的數(shù)據(jù)是否存在,布隆過濾器可以判斷某個元素是否在集合中
4.2 緩存擊穿
概念:單個熱點key失效,在失效的那一刻,同時有大量請求打到DB上,造成數(shù)據(jù)庫壓力劇增的情況
解決辦法:
- 設(shè)置熱點key不過期,定時任務(wù)更新緩存或者設(shè)置互斥鎖,當(dāng)請求過來時,發(fā)現(xiàn)緩存不存在數(shù)據(jù)時,就給當(dāng)前請求加鎖,后面的請求等待或者返回,當(dāng)從數(shù)據(jù)庫中拿出來放到緩存中時,就可以釋放鎖資源。
4.3 緩存雪崩
概念:多個熱點key緩存失效,大量的key設(shè)置了相同的過期時間、導(dǎo)致緩存在同一時間全部失效,造成瞬時DB請求量大、壓力劇增。
解決辦法:
- 存數(shù)據(jù)的過期時間設(shè)置隨機(jī),防止同一時間大量數(shù)據(jù)過期現(xiàn)象發(fā)生
- 啟用透明多級緩存,多個服務(wù)節(jié)點因為加載一級緩存的時間不一樣,也能分散過期時間
4.4 緩存污染
概念:緩存中的數(shù)據(jù)與真實數(shù)據(jù)源中的數(shù)據(jù)不一致的現(xiàn)象
解決辦法:
使用更新緩存時遵循的設(shè)計模式,如:Cache Aside,Read/Write Through,Write Behind Caching這些
Cache Aside模式的工作方式:
- 讀數(shù)據(jù)時,先讀緩存,如緩存中沒有,則讀數(shù)據(jù)庫,再將數(shù)據(jù)寫入緩存中;
- 寫數(shù)據(jù)時,先寫數(shù)據(jù)庫,然后失效緩存(刪除緩存數(shù)據(jù));
面試可能遇到的兩個關(guān)于Cache Aside的問題:
1.更新先后順序,為什么先更新數(shù)據(jù)庫再刪除緩存?
- 假設(shè)先刪除緩存再更新數(shù)據(jù)庫,會有一段時間是緩存已刪除,數(shù)據(jù)庫未更新的情況。這時如果有請求進(jìn)來,緩存中沒查到,就會查數(shù)據(jù)庫中舊的數(shù)據(jù),再放到緩存里。造成問題就是:數(shù)據(jù)庫已經(jīng)是最新數(shù)據(jù),緩存中還是舊的,不一致的問題;
2.為什么是刪除緩存,而不是更新緩存?
- 和上面一樣,更新過程中,如果有其他更新請求進(jìn)來更新數(shù)據(jù)庫,緩存就會面臨多次修改賦值的復(fù)雜時序問題。所以直接刪除緩存就行。
總結(jié):本文只寫了一些關(guān)于分布式緩存的簡單理論內(nèi)容,實際面試時大多圍繞redis進(jìn)行提問,下次再寫關(guān)于redis的相關(guān)內(nèi)容