微服務(wù)實(shí)踐目錄,可以參見(jiàn)連接浪感。
緩存系列包括:
1.微服務(wù)管理-11.緩存概述
1.微服務(wù)管理-11.緩存-0.技術(shù)
1.微服務(wù)管理-11.緩存-1.多級(jí)緩存設(shè)計(jì)
1.微服務(wù)管理-11.緩存-2.典型緩存架構(gòu)設(shè)計(jì)
1.微服務(wù)管理-11.緩存-3.實(shí)踐
1.微服務(wù)管理-11.緩存-4.總結(jié)
背景
前面介紹了緩存的設(shè)計(jì)方法昔头,緩存技術(shù),緩存方法等內(nèi)容影兽。本著本系列文章的一貫宗旨:理論結(jié)合實(shí)踐揭斧,所以需要將理論知識(shí)真正的落地到實(shí)踐中。本文主要說(shuō)明在緩存實(shí)踐中會(huì)遇到的問(wèn)題以及這些問(wèn)題的解決辦法峻堰。
典型緩存架構(gòu)(緩存設(shè)計(jì)模式)
對(duì)于緩存來(lái)說(shuō)數(shù)據(jù)應(yīng)該被怎樣初始化讹开、更新、失效茧妒、持久化都是問(wèn)題萧吠,對(duì)于解決這些問(wèn)題有前人總結(jié)出的架構(gòu)模式幫我們解決。
-
緩存設(shè)計(jì)模式
緩存設(shè)計(jì)模式中分為兩類(lèi):Cache-Aside桐筏、Cache-As-SoR兩類(lèi)纸型。這兩類(lèi)代表著對(duì)緩存使用方式的不同的認(rèn)知。Cache-Aside代表緩存就是進(jìn)行快速訪(fǎng)問(wèn)數(shù)據(jù)的過(guò)程梅忌。Cache-As-SoR代表緩存是一個(gè)數(shù)據(jù)存儲(chǔ)系統(tǒng)狰腌,以數(shù)據(jù)存儲(chǔ)系統(tǒng)的使用方式使用緩存技術(shù)。
Cache-Aside即業(yè)務(wù)代碼圍繞著Cache寫(xiě)牧氮,是由業(yè)務(wù)代碼維護(hù)緩存琼腔。業(yè)務(wù)代碼進(jìn)行緩存的讀寫(xiě)工作,讀時(shí)使用擊穿讀踱葛,寫(xiě)使用雙寫(xiě)方式完成丹莲。
Cache-As-SoR即把Cache看作為SoR光坝,所有操作都是對(duì)Cache進(jìn)行,然后Cache再委托給SoR進(jìn)行真實(shí)的讀/寫(xiě)甥材。即業(yè)務(wù)代碼中只看到Cache的操作盯另,看不到關(guān)于SoR相關(guān)的代碼。有是那種實(shí)現(xiàn):Read Through, Write Through, Write Behind Caching洲赵。
在緩存系統(tǒng)內(nèi)中有三個(gè)概念:
- SoR(system-of-recode):記錄系統(tǒng)鸳惯,或者叫數(shù)據(jù)源,即實(shí)際存儲(chǔ)原始數(shù)據(jù)的系統(tǒng)
- Cache:緩存叠萍,是SoR的快照數(shù)據(jù)芝发,Cache的訪(fǎng)問(wèn)速度比SoR要快,放入Cache的目的是提升訪(fǎng)問(wèn)速度苛谷,減少回溯的次數(shù)辅鲸。
- 回溯:即回到數(shù)據(jù)源頭獲取數(shù)據(jù),Cache沒(méi)命中時(shí)需要從SoR讀取數(shù)據(jù)抄腔。
Cache-As-SoR的三種實(shí)現(xiàn)方式:
Read Through, 業(yè)務(wù)代碼首先調(diào)用Cache瓢湃,如果Cache不明中有Cache回溯到SoR,而不是業(yè)務(wù)代碼(即由Cache讀SoR)赫蛇。Read Through的特點(diǎn)是業(yè)務(wù)代碼與更新緩存代碼分離绵患,不像Cache-Aside模式那樣更新緩存代碼和SoR代碼角質(zhì)在一起。更利于緩存代碼的統(tǒng)一維護(hù)悟耘。
Write Through, 被成為穿透寫(xiě)/直寫(xiě)模式--業(yè)務(wù)代碼首先調(diào)用Cache寫(xiě)(新增/修改)數(shù)據(jù)落蝙,然后有Cache負(fù)責(zé)寫(xiě)緩存和寫(xiě)SoR,不用業(yè)務(wù)代碼去寫(xiě)暂幼。Write Through的特點(diǎn)和Read Through相仿筏勒,不過(guò)從查詢(xún)時(shí)發(fā)生變?yōu)樵诟聰?shù)據(jù)時(shí)發(fā)生。
Write Behind Caching旺嬉,又叫Write Back管行。一些了解Linux操作系統(tǒng)內(nèi)核的同學(xué)對(duì)Write Back應(yīng)該非常熟悉,這不就是Linux文件系統(tǒng)的Page Cache的算法嗎邪媳?是的捐顷,你看基礎(chǔ)這玩意全都是相通的。Write Back與Write Through不同之處在于Write Back是異步寫(xiě)的雨效。說(shuō)明白點(diǎn)就是在更新數(shù)據(jù)的時(shí)候迅涮,只更新緩存,不更新數(shù)據(jù)庫(kù)徽龟,而我們的緩存會(huì)異步地批量更新數(shù)據(jù)庫(kù)叮姑。Write Back的特點(diǎn)是讓數(shù)據(jù)的I/O操作飛快無(wú)比(因?yàn)橹苯硬僮鲀?nèi)存嘛 ),因?yàn)楫惒骄莼冢瑆rite backg還可以合并對(duì)同一個(gè)數(shù)據(jù)的多次操作传透,所以性能的提高是相當(dāng)可觀(guān)的耘沼。
-
技術(shù)選型
技術(shù) | Jetedis | Guava Cache | Ehcache3.x |
---|---|---|---|
Cache-Aside | 支持 | 支持 | 支持 |
Read Through | 不支持 | 支持 | 支持 |
Write Through | 不支持 | 不支持 | 支持 |
Write Behind Caching | 不支持 | 不支持 | 支持 |
對(duì)于Cache-Aside,可能存在并發(fā)更新情況旷祸,即如果多個(gè)應(yīng)用實(shí)例同時(shí)更新那么緩存怎么辦耕拷?下一節(jié)就說(shuō)明相關(guān)的關(guān)注點(diǎn)。
緩存架構(gòu)關(guān)注點(diǎn)
在緩存真正落地時(shí)可能會(huì)遇到的問(wèn)題托享、以及這些問(wèn)題的解決方法與理論有一定的隔閡,不過(guò)這種隔閡可以考驗(yàn)我們的設(shè)計(jì)與架構(gòu)能力浸赫。也考驗(yàn)我們深度思考的能力闰围。
-
Dog Pile Effect
在緩存系統(tǒng)中,緩存總有失效的時(shí)候既峡,比如我們經(jīng)常使用的 Memcache 和 Redis 羡榴,都會(huì)設(shè)置超時(shí)時(shí)間;而一旦緩存到了超時(shí)時(shí)間失效之后运敢,如果此時(shí)再有大量的并發(fā)向數(shù)據(jù)庫(kù)發(fā)起請(qǐng)求校仑,就會(huì)造成服務(wù)器卡頓甚至是系統(tǒng)當(dāng)機(jī)。這就是 Dog Pile Effect 传惠∑可以使用Read Though模式進(jìn)行解決。
-
擊穿
當(dāng)請(qǐng)求了緩存中沒(méi)有的數(shù)據(jù)時(shí)或當(dāng)緩存服務(wù)掛掉時(shí)卦方,這時(shí)候就會(huì)回源到DB里面羊瘩。此時(shí)如果黑客故意對(duì)上面數(shù)據(jù)發(fā)起大量請(qǐng)求,則DB有可能會(huì)掛掉盼砍,這就是緩存擊穿尘吗。當(dāng)然緩存掛掉的話(huà),正常的用戶(hù)請(qǐng)求也有可能造成緩存擊穿的效果浇坐。
最簡(jiǎn)單的方式處理緩存擊穿問(wèn)題:緩存永不過(guò)期睬捶。真正的緩存過(guò)期時(shí)間不有Redis控制,而是由程序代碼控制近刘。當(dāng)獲取數(shù)據(jù)時(shí)發(fā)現(xiàn)數(shù)據(jù)超時(shí)時(shí)擒贸,就需要發(fā)起一個(gè)異步請(qǐng)求去加載數(shù)據(jù)。符合Write Back模式跌宛。
-
可靠性
在緩存宕機(jī)的情況下酗宋,為了保證服務(wù)能夠正常的提供服務(wù)最好的方式是使用多級(jí)緩存的本地緩存進(jìn)行暫時(shí)數(shù)據(jù)保存。在這其中有兩種方式選擇:白名單疆拘、布隆過(guò)濾器(Bloom Filter)蜕猫。
白名單顧名思義就是:在緩存宕機(jī)之前的一段時(shí)間里,會(huì)將請(qǐng)求的數(shù)據(jù)在系統(tǒng)中的有無(wú)哎迄,記錄在一個(gè)Map中回右。當(dāng)緩存宕機(jī)后隆圆,首先在Map中判斷是否含有數(shù)據(jù),有則回源DB翔烁,沒(méi)有的話(huà)就直接返回結(jié)果渺氧。
Bloom Filter實(shí)際上是一個(gè)很長(zhǎng)的二進(jìn)制向量和一系列隨機(jī)映射函數(shù)。布隆過(guò)濾器可以用于檢索一個(gè)元素是否在一個(gè)集合中蹬屹。它的優(yōu)點(diǎn)是空間效率和查詢(xún)時(shí)間都遠(yuǎn)遠(yuǎn)超過(guò)一般的算法侣背,缺點(diǎn)是有一定的誤識(shí)別率和刪除困難。
-
線(xiàn)程安全
保證線(xiàn)程安全的模式Copy Pattern慨默。Copy Pattern包括兩種Copy-On-Read(在讀時(shí)復(fù)制)和Copy-On-Write(在寫(xiě)實(shí)復(fù)制)贩耐,很多本地緩存技術(shù)都是基于堆緩存中對(duì)象飲用方式。這樣就會(huì)導(dǎo)致如果有一個(gè)請(qǐng)求獲取了緩存數(shù)據(jù)并修改它厦取,則可能發(fā)生不可預(yù)測(cè)的問(wèn)題潮太。所以,就需要使用COR或COW進(jìn)行虾攻。
解決方案
對(duì)于緩存系統(tǒng)來(lái)說(shuō)就是為了提高系統(tǒng)的并發(fā)能力铡买。在前面幾篇文章過(guò)后大家也對(duì)緩存系統(tǒng)有了深入的認(rèn)知,在此基礎(chǔ)上提出一個(gè)終極緩存架構(gòu)設(shè)計(jì)方案:
在上面的架構(gòu)中將OpenResty和Redis推到最前端霎箍,將服務(wù)押后到Redis之后奇钞。對(duì)于分布式緩存,我們需要在OpenResty應(yīng)用中盡享應(yīng)用混存來(lái)減少Redis集群的訪(fǎng)問(wèn)沖擊朋沮,即首先查詢(xún)OpenResty本地緩存蛇券,如果命中則直接返回,如果沒(méi)有則接著查詢(xún)Redis集群樊拓,如果在沒(méi)有則進(jìn)行回溯查詢(xún)纠亚。
架構(gòu)中將Redis視為存儲(chǔ),而非緩存筋夏。使用幾乎全量緩存的方式蒂胞,將數(shù)據(jù)加入到緩存系統(tǒng)中。每個(gè)請(qǐng)求直接使用Nginx緩存或Redis緩存進(jìn)行返回条篷,不需要通過(guò)任何后臺(tái)服務(wù)骗随、數(shù)據(jù)庫(kù)即可完成請(qǐng)求的處理。這樣最大限度的降低請(qǐng)求處理時(shí)間赴叹,最大限度的加大并發(fā)數(shù)鸿染。
-
CQRS
綜上所有的幾乎就是一個(gè)CQRS系統(tǒng)。將該隔離的隔離開(kāi)乞巧,將該耦合的耦合上去涨椒。這樣就能更好的幫助我們形成一個(gè)完善的緩存架構(gòu)。
總結(jié)
緩存是支持高并發(fā)的已經(jīng)很好的處理方式。不過(guò)要使用好緩存還是很考驗(yàn)研發(fā)人員能力的蚕冬。從使用Redis免猾、Memcache作為存儲(chǔ)使用,還是作為緩存使用就是可以區(qū)分出一個(gè)人對(duì)于緩存的認(rèn)知囤热。所以猎提,不要對(duì)任何一門(mén)技術(shù)設(shè)限,他不應(yīng)該只是它本來(lái)擅長(zhǎng)的位置體現(xiàn)作用旁蔼。應(yīng)該將技術(shù)擴(kuò)展到其他可以滿(mǎn)足技術(shù)特性的場(chǎng)景中去锨苏。
參考
緩存雙寫(xiě)不一致問(wèn)題
分布式緩存擊穿(布隆過(guò)濾器 Bloom Filter)
緩存更新的套路
不懂多級(jí)緩存的分層架構(gòu)?那就看看這個(gè)吧棺聊!
CDN的本質(zhì)—大規(guī)模分布式多級(jí)緩存系統(tǒng)
如何處理 Dog Pile Effect
CQRS實(shí)踐(1): 什么是CQRS
OpenResty? - 中文官方站