3種緩存讀寫(xiě)策略都不了解?面試很難讓你通過(guò)啊兄弟!
本文轉(zhuǎn)載自微信公眾號(hào)「JavaGuide」,作者Guide哥 。轉(zhuǎn)載本文請(qǐng)聯(lián)系JavaGuide公眾號(hào)。
看到很多小伙伴簡(jiǎn)歷上寫(xiě)了“熟練使用緩存”,但是被我問(wèn)到“緩存常用的 3 種讀寫(xiě)策略”的時(shí)候卻一臉懵逼。
造成這個(gè)問(wèn)題的原因是我們?cè)趯W(xué)習(xí) Redis 的時(shí)候,可能只是簡(jiǎn)單了寫(xiě)一些 Demo,并沒(méi)有去關(guān)注緩存的讀寫(xiě)策略,或者說(shuō)壓根不知道這回事。
但是,搞懂 3 種常見(jiàn)的緩存讀寫(xiě)策略對(duì)于實(shí)際工作中使用緩存以及面試中被問(wèn)到緩存都是非常有幫助的!
下面我會(huì)簡(jiǎn)單介紹一下自己對(duì)于這 3 種緩存讀寫(xiě)策略的理解。
另外,這 3 種緩存讀寫(xiě)策略各有優(yōu)劣,不存在最佳,需要我們根據(jù)具體的業(yè)務(wù)場(chǎng)景選擇更適合的。
個(gè)人能力有限。如果文章有任何需要補(bǔ)充/完善/修改的地方,歡迎在評(píng)論區(qū)指出,共同進(jìn)步!——愛(ài)你們的 Guide哥
Cache Aside Pattern(旁路緩存模式)
Cache Aside Pattern 是我們平時(shí)使用比較多的一個(gè)緩存讀寫(xiě)模式,比較適合讀請(qǐng)求比較多的場(chǎng)景。
Cache Aside Pattern 中服務(wù)端需要同時(shí)維系 DB 和 cache,并且是以 DB 的結(jié)果為準(zhǔn)。
下面我們來(lái)看一下這個(gè)策略模式下的緩存讀寫(xiě)步驟。
寫(xiě) :
- 先更新 DB
- 然后直接刪除 cache 。
簡(jiǎn)單畫(huà)了一張圖幫助大家理解寫(xiě)的步驟。
讀 :
- 從 cache 中讀取數(shù)據(jù),讀取到就直接返回
- cache 中讀取不到的話,就從 DB 中讀取數(shù)據(jù)返回
- 再把數(shù)據(jù)放到 cache 中。
簡(jiǎn)單畫(huà)了一張圖幫助大家理解讀的步驟。
你僅僅了解了上面這些內(nèi)容的話是遠(yuǎn)遠(yuǎn)不夠的,我們還要搞懂其中的原理。
比如說(shuō)面試官很可能會(huì)追問(wèn):“在寫(xiě)數(shù)據(jù)的過(guò)程中,可以先刪除 cache ,后更新 DB 么?”
答案: 那肯定是不行的!因?yàn)檫@樣可能會(huì)造成數(shù)據(jù)庫(kù)(DB)和緩存(Cache)數(shù)據(jù)不一致的問(wèn)題。為什么呢?比如說(shuō)請(qǐng)求 1 先寫(xiě)數(shù)據(jù) A,請(qǐng)求 2 隨后讀數(shù)據(jù) A 的話就很有可能產(chǎn)生數(shù)據(jù)不一致性的問(wèn)題。這個(gè)過(guò)程可以簡(jiǎn)單描述為:
請(qǐng)求 1 先把 cache 中的 A 數(shù)據(jù)刪除 -> 請(qǐng)求 2 從 DB 中讀取數(shù)據(jù)->請(qǐng)求 1 再把 DB 中的 A 數(shù)據(jù)更新。
當(dāng)你這樣回答之后,面試官可能會(huì)緊接著就追問(wèn):“在寫(xiě)數(shù)據(jù)的過(guò)程中,先更新 DB,后刪除 cache 就沒(méi)有問(wèn)題了么?”
答案:理論上來(lái)說(shuō)還是可能會(huì)出現(xiàn)數(shù)據(jù)不一致性的問(wèn)題,不過(guò)概率非常小,因?yàn)榫彺娴膶?xiě)入速度是比數(shù)據(jù)庫(kù)的寫(xiě)入速度快很多!
比如請(qǐng)求 1 先讀數(shù)據(jù) A,請(qǐng)求 2 隨后寫(xiě)數(shù)據(jù) A,并且數(shù)據(jù) A 不在緩存中的話也有可能產(chǎn)生數(shù)據(jù)不一致性的問(wèn)題。這個(gè)過(guò)程可以簡(jiǎn)單描述為:
請(qǐng)求 1 從 DB 讀數(shù)據(jù) A->請(qǐng)求 2 寫(xiě)更新數(shù)據(jù) A 到數(shù)據(jù)庫(kù)并把刪除 cache 中的 A 數(shù)據(jù)->請(qǐng)求 1 將數(shù)據(jù) A 寫(xiě)入 cache。
現(xiàn)在我們?cè)賮?lái)分析一下 Cache Aside Pattern 的缺陷。
缺陷 1:首次請(qǐng)求數(shù)據(jù)一定不存在 cache 的問(wèn)題
解決辦法:可以將熱點(diǎn)數(shù)據(jù)可以提前放入 cache 中。
缺陷 2:寫(xiě)操作比較頻繁的話導(dǎo)致 cache 中的數(shù)據(jù)會(huì)被頻繁被刪除,這樣會(huì)影響緩存命中率 。
解決辦法:
- 數(shù)據(jù)庫(kù)和緩存數(shù)據(jù)強(qiáng)一致場(chǎng)景 :更新 DB 的時(shí)候同樣更新 cache,不過(guò)我們需要加一個(gè)鎖/分布式鎖來(lái)保證更新 cache 的時(shí)候不存在線程安全問(wèn)題。
- 可以短暫地允許數(shù)據(jù)庫(kù)和緩存數(shù)據(jù)不一致的場(chǎng)景 :更新 DB 的時(shí)候同樣更新 cache,但是給緩存加一個(gè)比較短的過(guò)期時(shí)間,這樣的話就可以保證即使數(shù)據(jù)不一致的話影響也比較小。
Read/Write Through Pattern(讀寫(xiě)穿透)
Read/Write Through Pattern 中服務(wù)端把 cache 視為主要數(shù)據(jù)存儲(chǔ),從中讀取數(shù)據(jù)并將數(shù)據(jù)寫(xiě)入其中。cache 服務(wù)負(fù)責(zé)將此數(shù)據(jù)讀取和寫(xiě)入 DB,從而減輕了應(yīng)用程序的職責(zé)。
這種緩存讀寫(xiě)策略小伙伴們應(yīng)該也發(fā)現(xiàn)了在平時(shí)在開(kāi)發(fā)過(guò)程中非常少見(jiàn)。拋去性能方面的影響,大概率是因?yàn)槲覀兘?jīng)常使用的分布式緩存 Redis 并沒(méi)有提供 cache 將數(shù)據(jù)寫(xiě)入 DB 的功能。
寫(xiě)(Write Through):
- 先查 cache,cache 中不存在,直接更新 DB。
- cache 中存在,則先更新 cache,然后 cache 服務(wù)自己更新 DB(同步更新 cache 和 DB)。
簡(jiǎn)單畫(huà)了一張圖幫助大家理解寫(xiě)的步驟。
讀(Read Through):
- 從 cache 中讀取數(shù)據(jù),讀取到就直接返回 。
- 讀取不到的話,先從 DB 加載,寫(xiě)入到 cache 后返回響應(yīng)。
簡(jiǎn)單畫(huà)了一張圖幫助大家理解讀的步驟。
Read-Through Pattern 實(shí)際只是在 Cache-Aside Pattern 之上進(jìn)行了封裝。在 Cache-Aside Pattern 下,發(fā)生讀請(qǐng)求的時(shí)候,如果 cache 中不存在對(duì)應(yīng)的數(shù)據(jù),是由客戶(hù)端自己負(fù)責(zé)把數(shù)據(jù)寫(xiě)入 cache,而 Read Through Pattern 則是 cache 服務(wù)自己來(lái)寫(xiě)入緩存的,這對(duì)客戶(hù)端是透明的。
和 Cache Aside Pattern 一樣, Read-Through Pattern 也有首次請(qǐng)求數(shù)據(jù)一定不在 cache 的問(wèn)題,對(duì)于熱點(diǎn)數(shù)據(jù)可以提前放入緩存中。
Write Behind Pattern(異步緩存寫(xiě)入)
Write Behind Pattern 和 Read/Write Through Pattern 很相似,兩者都是由 cache 服務(wù)來(lái)負(fù)責(zé) cache 和 DB 的讀寫(xiě)。
但是,兩個(gè)又有很大的不同:Read/Write Through 是同步更新 cache 和 DB,而 Write Behind Caching 則是只更新緩存,不直接更新 DB,而是改為異步批量的方式來(lái)更新 DB。
很明顯,這種方式對(duì)數(shù)據(jù)一致性帶來(lái)了更大的挑戰(zhàn),比如 cache 數(shù)據(jù)可能還沒(méi)異步更新 DB 的話,cache 服務(wù)可能就掛掉了。
這種策略在我們平時(shí)開(kāi)發(fā)過(guò)程中也非常少見(jiàn),但是不代表它的應(yīng)用場(chǎng)景少,比如消息隊(duì)列中消息的異步寫(xiě)入磁盤(pán)、MySQL 的 InnoDB Buffer Pool 機(jī)制都用到了這種策略。
原文鏈接:https://mp.weixin.qq.com/s/bWofuM5eS2Q8ylF-4AD0kA