分布式緩存的25個(gè)優(yōu)秀實(shí)踐與線上案例_第1頁(yè)
分布式緩存的25個(gè)優(yōu)秀實(shí)踐與線上案例_第2頁(yè)
分布式緩存的25個(gè)優(yōu)秀實(shí)踐與線上案例_第3頁(yè)
分布式緩存的25個(gè)優(yōu)秀實(shí)踐與線上案例_第4頁(yè)
分布式緩存的25個(gè)優(yōu)秀實(shí)踐與線上案例_第5頁(yè)
已閱讀5頁(yè),還剩9頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、 分布式緩存的25個(gè)優(yōu)秀實(shí)踐與線上案例 楊彪,螞蟻金服技術(shù)專家,分布式服務(wù)架構(gòu):原理、設(shè)計(jì)與實(shí)戰(zhàn)和可伸縮服務(wù)架構(gòu):框架與中間件作者。近10年互聯(lián)網(wǎng)和游戲行業(yè)工作經(jīng)驗(yàn)。本文節(jié)選自即將出版的可伸縮服務(wù)架構(gòu):框架與中間件一書,作者:李艷鵬、楊彪、李海亮、賈博巖、劉淏。本文主要介紹使用分布式緩存的優(yōu)秀實(shí)踐和線上案例。這些案例是筆者在多家互聯(lián)網(wǎng)公司里積累并形成的優(yōu)秀實(shí)踐,能夠幫助大家在生產(chǎn)實(shí)踐中避免很多不必要的生產(chǎn)事故。一、緩存設(shè)計(jì)的核心要素我們?cè)趹?yīng)用中決定使用緩存時(shí),通常需要進(jìn)行詳細(xì)的設(shè)計(jì),因?yàn)樵O(shè)計(jì)緩存架構(gòu)看似簡(jiǎn)單,實(shí)則不然,里面蘊(yùn)含了很多深?yuàn)W的原理,如果使用不當(dāng),則會(huì)造成很多生產(chǎn)事故甚至是服務(wù)雪崩之

2、類的嚴(yán)重問(wèn)題。筆者在做設(shè)計(jì)評(píng)審的過(guò)程中,總結(jié)了所有與緩存設(shè)計(jì)相關(guān)的設(shè)計(jì)點(diǎn),這里列出來(lái)供大家參考。1、容量規(guī)劃緩存內(nèi)容的大小緩存內(nèi)容的數(shù)量淘汰策略緩存的數(shù)據(jù)結(jié)構(gòu)每秒的讀峰值每秒的寫峰值2、性能優(yōu)化線程模型預(yù)熱方法緩存分片冷熱數(shù)據(jù)的比例3、高可用復(fù)制模型失效轉(zhuǎn)移持久策略緩存重建4、緩存監(jiān)控緩存服務(wù)監(jiān)控緩存容量監(jiān)控緩存請(qǐng)求監(jiān)控緩存響應(yīng)時(shí)間監(jiān)控5、注意事項(xiàng)是否有可能發(fā)生緩存穿透是否有大對(duì)象是否使用緩存實(shí)現(xiàn)分布式鎖是否使用緩存支持的腳本(Lua)是否避免了Race Condition筆者在這里把這些設(shè)計(jì)點(diǎn)提供給讀者,請(qǐng)讀者在做緩存設(shè)計(jì)時(shí)把每一項(xiàng)作為一個(gè)思考的起點(diǎn),思考我們?cè)谠O(shè)計(jì)緩存時(shí)是否想到了這些點(diǎn),以

3、避免在設(shè)計(jì)的過(guò)程中因忽略某一項(xiàng)而導(dǎo)致嚴(yán)重的線上事故發(fā)生。二、緩存設(shè)計(jì)的優(yōu)秀實(shí)踐筆者在做設(shè)計(jì)評(píng)審的過(guò)程中,總結(jié)了一些開(kāi)發(fā)人員在設(shè)計(jì)緩存系統(tǒng)時(shí)的優(yōu)秀實(shí)踐,如下所述:優(yōu)秀實(shí)踐1緩存系統(tǒng)主要消耗的是服務(wù)器的內(nèi)存,因此,在使用緩存時(shí)必須先對(duì)應(yīng)用需要緩存的數(shù)據(jù)大小進(jìn)行評(píng)估,包括緩存的數(shù)據(jù)結(jié)構(gòu)、緩存大小、緩存數(shù)量、緩存的失效時(shí)間,然后根據(jù)業(yè)務(wù)情況自行推算在未來(lái)一定時(shí)間內(nèi)的容量的使用情況,根據(jù)容量評(píng)估的結(jié)果來(lái)申請(qǐng)和分配緩存資源,否則會(huì)造成資源浪費(fèi)或者緩存空間不夠。優(yōu)秀實(shí)踐2建議將使用緩存的業(yè)務(wù)進(jìn)行分離,核心業(yè)務(wù)和非核心業(yè)務(wù)使用不同的緩存實(shí)例,從物理上進(jìn)行隔離,如果有條件,則請(qǐng)對(duì)每個(gè)業(yè)務(wù)使用單獨(dú)的實(shí)例或者集群,

4、以減小應(yīng)用之間互相影響的可能性。筆者就經(jīng)常聽(tīng)說(shuō)有的公司應(yīng)用了共享緩存,造成緩存數(shù)據(jù)被覆蓋以及緩存數(shù)據(jù)錯(cuò)亂的線上事故。優(yōu)秀實(shí)踐3根據(jù)緩存實(shí)例提供的內(nèi)存大小推算應(yīng)用需要使用的緩存實(shí)例數(shù)量,一般在公司里會(huì)成立一個(gè)緩存管理的運(yùn)維團(tuán)隊(duì),這個(gè)團(tuán)隊(duì)會(huì)將緩存資源虛擬成多個(gè)相同內(nèi)存大小的緩存實(shí)例。例如一個(gè)實(shí)例有4GB內(nèi)存,在應(yīng)用申請(qǐng)時(shí)可以按需申請(qǐng)足夠的實(shí)例數(shù)量來(lái)使用,對(duì)這樣的應(yīng)用需要進(jìn)行分片,詳情請(qǐng)參考可伸縮服務(wù)架構(gòu):框架與中間件中4.4.3的內(nèi)容。這里需要注意,如果我們使用了RDB備份機(jī)制,每個(gè)實(shí)例使用4GB內(nèi)存,則我們的系統(tǒng)需要大于8GB內(nèi)存,因?yàn)镽DB備份時(shí)使用了 copy-on-write 機(jī)制,需要f

5、ork出一個(gè)子進(jìn)程,并且復(fù)制一份內(nèi)存,因此需要雙份的內(nèi)存存儲(chǔ)大小。優(yōu)秀實(shí)踐4緩存一般是用來(lái)加速數(shù)據(jù)庫(kù)的讀操作的,一般先訪問(wèn)緩存后訪問(wèn)數(shù)據(jù)庫(kù),所以緩存的超時(shí)時(shí)間的設(shè)置是很重要的。筆者曾經(jīng)在一家互聯(lián)網(wǎng)公司遇到過(guò)由于運(yùn)維操作失誤導(dǎo)致緩存超時(shí)設(shè)置得較長(zhǎng),從而拖垮服務(wù)的線程池,最終導(dǎo)致服務(wù)雪崩的情況。優(yōu)秀實(shí)踐5所有的緩存實(shí)例都需要添加監(jiān)控,這是非常重要的,我們需要對(duì)慢查詢、大對(duì)象、內(nèi)存使用情況做可靠的監(jiān)控。優(yōu)秀實(shí)踐6我們不推薦多個(gè)業(yè)務(wù)共享一個(gè)緩存實(shí)例,但是由于成本控制的原因,這種情況經(jīng)常出現(xiàn),我們需要通過(guò)規(guī)范來(lái)限制各個(gè)應(yīng)用使用的key有唯一的前綴,并進(jìn)行隔離設(shè)計(jì),避免產(chǎn)生緩存互相覆蓋的問(wèn)題。優(yōu)秀實(shí)踐7任

6、何緩存的key都必須設(shè)定緩存失效時(shí)間,且失效時(shí)間不能集中在某一點(diǎn),否則會(huì)導(dǎo)致緩存占滿內(nèi)存或者緩存雪崩。優(yōu)秀實(shí)踐8低頻訪問(wèn)的數(shù)據(jù)不要放在緩存中,如我們前面所說(shuō)的,我們使用緩存的主要目的是提高讀取性能。曾經(jīng)有個(gè)小伙伴設(shè)計(jì)了一套定時(shí)的批處理系統(tǒng),由于批處理系統(tǒng)需要對(duì)一個(gè)大的數(shù)據(jù)模型進(jìn)行計(jì)算,所以該小伙伴把這個(gè)數(shù)據(jù)模型保存在每個(gè)節(jié)點(diǎn)的本地緩存中,并通過(guò)消息隊(duì)列接收更新的消息來(lái)維護(hù)本地緩存中模型的實(shí)時(shí)性,但是這個(gè)模型每個(gè)月只用了一次,所以這樣使用緩存是很浪費(fèi)的。既然是批處理任務(wù),就需要把任務(wù)進(jìn)行分割,進(jìn)行批量處理,采用分而治之、逐步計(jì)算的方法,得出最終的結(jié)果即可。優(yōu)秀實(shí)踐9緩存的數(shù)據(jù)不易過(guò)大,尤其是Re

7、dis,因?yàn)镽edis使用的是單線程模型,在單個(gè)緩存key的數(shù)據(jù)過(guò)大時(shí),會(huì)阻塞其他請(qǐng)求的處理。優(yōu)秀實(shí)踐10對(duì)于存儲(chǔ)較多value的key,盡量不要使用HGETALL等集合操作,該操作會(huì)造成請(qǐng)求阻塞,影響其他應(yīng)用的訪問(wèn)。優(yōu)秀實(shí)踐11緩存一般用于在交易系統(tǒng)中加速查詢的場(chǎng)景,有大量的更新數(shù)據(jù)時(shí),尤其是批量處理時(shí),請(qǐng)使用批量模式,但是這種場(chǎng)景較少。優(yōu)秀實(shí)踐12如果對(duì)性能的要求不是非常高,則盡量使用分布式緩存,而不要使用本地緩存,因?yàn)楸镜鼐彺嬖诜?wù)的各個(gè)節(jié)點(diǎn)之間復(fù)制,在某一時(shí)刻副本之間是不一致的,如果這個(gè)緩存代表的是開(kāi)關(guān),而且分布式系統(tǒng)中的請(qǐng)求有可能會(huì)重復(fù),就會(huì)導(dǎo)致重復(fù)的請(qǐng)求走到兩個(gè)節(jié)點(diǎn),一個(gè)節(jié)點(diǎn)的開(kāi)關(guān)

8、是開(kāi),一個(gè)節(jié)點(diǎn)的開(kāi)關(guān)是關(guān),如果請(qǐng)求處理沒(méi)有做到冪等,就會(huì)造成處理重復(fù),在嚴(yán)重情況下會(huì)造成資金損失。優(yōu)秀實(shí)踐13在寫緩存時(shí)一定要寫入完全正確的數(shù)據(jù),如果緩存數(shù)據(jù)的一部分有效、一部分無(wú)效,則寧可放棄緩存,也不要把部分?jǐn)?shù)據(jù)寫入緩存,否則會(huì)造成空指針、程序異常等。優(yōu)秀實(shí)踐14在通常情況下,讀的順序是先緩存,后數(shù)據(jù)庫(kù);寫的順序是先數(shù)據(jù)庫(kù),后緩存。優(yōu)秀實(shí)踐15在使用本地緩存(如Ehcache)時(shí),一定要嚴(yán)格控制緩存對(duì)象的個(gè)數(shù)及聲明周期。由于JVM的特性,過(guò)多的緩存對(duì)象會(huì)極大影響JVM的性能,甚至導(dǎo)致內(nèi)存溢出等。優(yōu)秀實(shí)踐16在使用緩存時(shí),一定要有降級(jí)處理,尤其是對(duì)關(guān)鍵的業(yè)務(wù)環(huán)節(jié),緩存有問(wèn)題或者失效時(shí)也要能回

9、源到數(shù)據(jù)庫(kù)進(jìn)行處理。三、關(guān)于常見(jiàn)的緩存問(wèn)題的線上案例筆者在多家互聯(lián)網(wǎng)公司負(fù)責(zé)架構(gòu)方案評(píng)審和線上事故復(fù)盤,這里列舉其中的一些典型案例,供大家參考和借鑒。案例1現(xiàn)象:某應(yīng)用程序的數(shù)據(jù)庫(kù)負(fù)載瞬時(shí)升高。原因:在應(yīng)用程序中對(duì)使用的大量緩存key設(shè)置了同一個(gè)固定的失效時(shí)間,當(dāng)緩存失效時(shí),會(huì)造成在一段時(shí)間內(nèi)同時(shí)訪問(wèn)數(shù)據(jù)庫(kù),造成數(shù)據(jù)庫(kù)的壓力較大。總結(jié):在使用緩存時(shí)需要進(jìn)行緩存設(shè)計(jì),要充分考慮如何避免常見(jiàn)的緩存穿透、緩存雪崩、緩存并發(fā)等問(wèn)題,尤其是對(duì)于高并發(fā)的緩存使用,需要對(duì)key的過(guò)期時(shí)間進(jìn)行隨機(jī)設(shè)置,例如,將過(guò)期時(shí)間設(shè)置為10秒+random(2),也就是將過(guò)期時(shí)間隨機(jī)設(shè)置成1012秒。案例2現(xiàn)象:導(dǎo)致遷移

10、前后兩個(gè)系統(tǒng)的核心操作重復(fù)。原因:在遷移的過(guò)程中,重復(fù)的流量進(jìn)入了不同的節(jié)點(diǎn),由于使用了本地緩存存儲(chǔ)遷移開(kāi)關(guān),而遷移開(kāi)關(guān)在開(kāi)關(guān)打開(kāi)的瞬間導(dǎo)致各個(gè)節(jié)點(diǎn)的開(kāi)關(guān)狀態(tài)不一致,有的是開(kāi)、有的是關(guān),所以對(duì)于不同節(jié)點(diǎn)的流量的處理重復(fù),一個(gè)走了開(kāi)關(guān)開(kāi)的邏輯,一個(gè)走了開(kāi)關(guān)關(guān)的邏輯??偨Y(jié):避免使用本地緩存來(lái)存儲(chǔ)遷移開(kāi)關(guān),遷移開(kāi)關(guān)應(yīng)該在有狀態(tài)的訂單上標(biāo)記。案例3現(xiàn)象:某模塊設(shè)計(jì)使用了緩存加速數(shù)據(jù)庫(kù)的讀操作的性能,但發(fā)現(xiàn)數(shù)據(jù)庫(kù)負(fù)載并沒(méi)有明顯下降。原因:由于這個(gè)模塊的使用方查詢請(qǐng)求的數(shù)據(jù)在數(shù)據(jù)庫(kù)中不存在,是非法的數(shù)據(jù),所以導(dǎo)致緩存沒(méi)有命中,每次都穿透到數(shù)據(jù)庫(kù),且量級(jí)較大??偨Y(jié):在使用緩存時(shí)需要進(jìn)行緩存設(shè)計(jì),要充分考慮如

11、何避免常見(jiàn)的緩存穿透、緩存雪崩、緩存并發(fā)等問(wèn)題,尤其是對(duì)高并發(fā)的緩存使用,需要對(duì)無(wú)效的key進(jìn)行緩存,以抵擋惡意的或者無(wú)意的對(duì)無(wú)效緩存查詢的攻擊或影響。案例4現(xiàn)象:監(jiān)控系統(tǒng)報(bào)警,Redis中單個(gè)哈希鍵占用的空間巨大。原因:應(yīng)用系統(tǒng)使用了哈希鍵,哈希鍵本身有過(guò)期時(shí)間,但是哈希鍵里面的每個(gè)鍵值對(duì)沒(méi)有過(guò)期時(shí)間。總結(jié):在設(shè)計(jì)Redis的過(guò)程中,如果有大量的鍵值對(duì)要保存,則請(qǐng)使用字符串鍵的數(shù)據(jù)庫(kù)類型,并對(duì)每個(gè)鍵都設(shè)置過(guò)期時(shí)間,請(qǐng)不要在哈希鍵內(nèi)部存儲(chǔ)一個(gè)沒(méi)有邊界的集合數(shù)據(jù)。實(shí)際上,無(wú)論是對(duì)緩存、內(nèi)存還是對(duì)數(shù)據(jù)庫(kù)的設(shè)計(jì),如果使用任意一個(gè)集合的數(shù)據(jù)結(jié)構(gòu),則都要考慮為它設(shè)置最大限制,避免內(nèi)存用光,最常見(jiàn)的是集合

12、溢出導(dǎo)致的內(nèi)存溢出的問(wèn)題。案例5現(xiàn)象:某業(yè)務(wù)項(xiàng)目由于緩存宕機(jī)導(dǎo)致業(yè)務(wù)邏輯中斷,數(shù)據(jù)不一致。原因:Redis進(jìn)行主備切換,導(dǎo)致瞬間內(nèi)應(yīng)用連接Redis異常,應(yīng)用并沒(méi)有對(duì)緩存做降級(jí)處理??偨Y(jié):對(duì)于核心業(yè)務(wù),在使用緩存時(shí)一定要有降級(jí)方案。常見(jiàn)的降級(jí)方案是在數(shù)據(jù)庫(kù)層次預(yù)留足夠的容量,在某一部分緩存出現(xiàn)問(wèn)題時(shí),可以讓應(yīng)用暫時(shí)回源到數(shù)據(jù)庫(kù)繼續(xù)業(yè)務(wù)邏輯,而不應(yīng)該中斷業(yè)務(wù)邏輯,但是這需要嚴(yán)格的容量評(píng)估,請(qǐng)參考分布式服務(wù)架構(gòu):原理設(shè)計(jì)與實(shí)戰(zhàn)第3章的內(nèi)容。案例6現(xiàn)象:某應(yīng)用系統(tǒng)負(fù)載升高,響應(yīng)變慢,發(fā)現(xiàn)應(yīng)用進(jìn)行頻繁GC,甚至出現(xiàn)OutOfMemroyError: GC overhead limt exceed的錯(cuò)誤

13、日志。原因:因?yàn)檫@個(gè)項(xiàng)目是個(gè)歷史項(xiàng)目,使用了Hibernate ORM框架,在Hibernate中開(kāi)啟了二級(jí)緩存,使用了Ehcache;但是在Ehcache中沒(méi)有控制緩存對(duì)象的個(gè)數(shù),緩存對(duì)象增多,導(dǎo)致內(nèi)存緊張,所以進(jìn)行了頻繁的GC操作??偨Y(jié):使用本地緩存(如Ehcache、OSCache、應(yīng)用內(nèi)存)時(shí),一定要嚴(yán)格控制緩存對(duì)象的個(gè)數(shù)及聲明周期。案例7現(xiàn)象:某個(gè)正常運(yùn)行的應(yīng)用突然報(bào)警線程數(shù)過(guò)高,之后很快就出現(xiàn)了內(nèi)存溢出。原因:由于緩存連接數(shù)達(dá)到最大限制,應(yīng)用無(wú)法連接緩存,并且超時(shí)時(shí)間設(shè)置得較大,導(dǎo)致訪問(wèn)緩存的服務(wù)都在等待緩存操作返回,由于緩存負(fù)載較高,處理不完所有的請(qǐng)求,但是這些服務(wù)都在等待緩存操

14、作返回,服務(wù)這時(shí)在等待,并沒(méi)有超時(shí),就不能降級(jí)并繼續(xù)訪問(wèn)數(shù)據(jù)庫(kù)。這在BIO模式下線程池就會(huì)撐滿,使用方的線程池也都撐滿;在NIO模式下一樣會(huì)使服務(wù)的負(fù)載增加,服務(wù)響應(yīng)變慢,甚至使服務(wù)被壓垮??偨Y(jié):在使用遠(yuǎn)程緩存(如Redis、Memcached)時(shí),一定要對(duì)操作超時(shí)時(shí)間進(jìn)行設(shè)置,這是非常關(guān)鍵的,一般我們?cè)O(shè)計(jì)緩存作為加速數(shù)據(jù)庫(kù)讀取的手段,也會(huì)對(duì)緩存操作做降級(jí)處理,因此推薦使用更短的緩存超時(shí)時(shí)間,如果一定要給出一個(gè)數(shù)字,則希望是100毫秒以內(nèi)。案例8現(xiàn)象:某項(xiàng)目使用緩存存儲(chǔ)業(yè)務(wù)數(shù)據(jù),上線后出現(xiàn)錯(cuò)誤問(wèn)題,開(kāi)發(fā)人員束手無(wú)策。原因:開(kāi)發(fā)人員不知道如何發(fā)現(xiàn)、排查、定位和解決緩存問(wèn)題??偨Y(jié):在設(shè)計(jì)緩存時(shí)要有降級(jí)方案,在遇到問(wèn)題時(shí)首先使用降級(jí)方法,還要設(shè)計(jì)完善的監(jiān)控和報(bào)警功能,幫助開(kāi)發(fā)人員快速發(fā)現(xiàn)緩存問(wèn)題,進(jìn)而來(lái)定位和解決問(wèn)題。案例9現(xiàn)象:某項(xiàng)目在使用緩存后,開(kāi)發(fā)測(cè)試通過(guò),到生產(chǎn)環(huán)境后,服務(wù)卻出現(xiàn)了不可預(yù)知的問(wèn)題。原因:該應(yīng)用的緩存key與其他應(yīng)用緩存

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論