免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
多級(jí)緩存設(shè)計(jì)詳解 | 給數(shù)據(jù)庫(kù)減負(fù),刻不容緩!

王梓晨:物流研發(fā)部架構(gòu)師,GIS技術(shù)部負(fù)責(zé)人,2012年加入京東,多年一線團(tuán)隊(duì)大促備戰(zhàn)經(jīng)驗(yàn),負(fù)責(zé)物流研發(fā)一些部門(mén)的架構(gòu)工作,專注于低延遲系統(tǒng)設(shè)計(jì)與海量數(shù)據(jù)處理。曾負(fù)責(zé)青龍配送分單團(tuán)隊(duì),主導(dǎo)重構(gòu)架構(gòu)設(shè)計(jì)與主要研發(fā)工作,短期內(nèi)提升了服務(wù)性能數(shù)十倍。還設(shè)計(jì)研發(fā)了地址配送網(wǎng)點(diǎn)分類模型,實(shí)現(xiàn)了配送到路區(qū)的精準(zhǔn)化分單,降本增效,大幅提升了自動(dòng)分單準(zhǔn)確率。目前負(fù)責(zé)物流GIS部門(mén),先后主導(dǎo)了國(guó)標(biāo)轉(zhuǎn)京標(biāo)、物流可視化等項(xiàng)目。



自古兵家多謀,《謀攻篇》,“故上兵伐謀,其次伐交,其次伐兵,其下攻城。攻城之法,為不得已”,可見(jiàn)攻城之計(jì)有很多種,而爬墻攻城是最不明智的做法,軍隊(duì)疲憊受損、錢(qián)糧損耗、百姓遭殃。故而我們有很多迂回之策,謀略、外交、軍事手段等等,每一種都比攻城的代價(jià)小,更輕量級(jí),緩存設(shè)計(jì)亦是如此。


為什么要設(shè)計(jì)緩存呢?

其實(shí)高并發(fā)應(yīng)對(duì)的解決方案不是互聯(lián)網(wǎng)獨(dú)創(chuàng)的,計(jì)算機(jī)先祖?zhèn)兒茉缇蛯?duì)類似的場(chǎng)景做了方案。比如《計(jì)算機(jī)組成原理》這樣提到的cpu緩存概念,它是一種高速緩存,容量比內(nèi)存小但是速度卻快很多,這種緩存的出現(xiàn)主要是為了解決cpu運(yùn)算速度遠(yuǎn)大于內(nèi)存讀寫(xiě)速度,甚至達(dá)到千萬(wàn)倍。


傳統(tǒng)的cpu通過(guò)fsb直連內(nèi)存的方式顯然就會(huì)因?yàn)閮?nèi)存訪問(wèn)的等待,導(dǎo)致cpu吞吐量下降,內(nèi)存成為性能瓶頸。同時(shí)又由于內(nèi)存訪問(wèn)的熱點(diǎn)數(shù)據(jù)集中性,所以需要在cpu與內(nèi)存之間做一層臨時(shí)的存儲(chǔ)器作為高速緩存。


隨著系統(tǒng)復(fù)雜性的提升,這種高速緩存和內(nèi)存之間的速度進(jìn)一步拉開(kāi),由于技術(shù)難度和成本等原因,所以有了更大的二級(jí)、三級(jí)緩存。根據(jù)讀取順序,絕大多數(shù)的請(qǐng)求首先落在一級(jí)緩存上,其次二級(jí)...

 

cpu  core1

cpu  core2

L1d

(一級(jí)數(shù)據(jù)緩存)

L1i

(一級(jí)指令緩存)

L1d

(一級(jí)數(shù)據(jù)緩存)

L1i

(一級(jí)指令緩存)

L2

L2

L3

L3

故而應(yīng)用于SOA甚至微服務(wù)的場(chǎng)景,內(nèi)存相當(dāng)于存儲(chǔ)業(yè)務(wù)數(shù)據(jù)的持久化數(shù)據(jù)庫(kù),其吞吐量肯定是遠(yuǎn)遠(yuǎn)小于緩存的,而對(duì)于java程序來(lái)講,本地的jvm緩存優(yōu)于集中式的redis緩存。


關(guān)系型數(shù)據(jù)庫(kù)操作方便、易于維護(hù)且訪問(wèn)數(shù)據(jù)靈活,但是隨著數(shù)據(jù)量的增加,其檢索、更新的效率會(huì)越來(lái)越低。所以在高并發(fā)低延遲要求復(fù)雜的場(chǎng)景,要給數(shù)據(jù)庫(kù)減負(fù),減少其壓力。

 

給數(shù)據(jù)庫(kù)減負(fù)

1、緩存分布式,做多級(jí)緩存

讀請(qǐng)求時(shí)寫(xiě)緩存

寫(xiě)緩存時(shí)一級(jí)一級(jí)寫(xiě),先寫(xiě)本地緩存,再寫(xiě)集中式緩存。具體些緩存的方法可以有很多種,但是需要注意幾項(xiàng)原則:

  1. 不要復(fù)制粘貼,避免重復(fù)代碼

  2. 切忌和業(yè)務(wù)耦合太緊,不利于后期維護(hù)

  3. 開(kāi)發(fā)初期剛剛上線階段,為了排查問(wèn)題,常常會(huì)給緩存設(shè)置開(kāi)關(guān),但是開(kāi)關(guān)設(shè)置多了則會(huì)同時(shí)升高系統(tǒng)的復(fù)雜度,需要結(jié)合一套統(tǒng)一配置管理系統(tǒng),京東物流有一套叫做UCC,且聽(tīng)下回分解......


綜上所述,高耦合帶來(lái)的痛,彌補(bǔ)的代價(jià)是很大的,所以可以借鑒Spring cache來(lái)實(shí)現(xiàn),實(shí)現(xiàn)也比較簡(jiǎn)單,使用時(shí)一個(gè)注解就搞定了。

 

寫(xiě)緩存失敗了怎么辦?應(yīng)該先寫(xiě)緩存還是數(shù)據(jù)庫(kù)呢?

既然是緩存的設(shè)計(jì),那么策略一定是保證最終一致性,那么我們只需要采用異步消息來(lái)補(bǔ)償就好了。


大部分緩存應(yīng)用的場(chǎng)景是讀寫(xiě)比差異很大的,讀遠(yuǎn)大于寫(xiě),在這種場(chǎng)景下,只需要以數(shù)據(jù)庫(kù)為主,先寫(xiě)數(shù)據(jù)庫(kù),再寫(xiě)緩存就好了。


最后補(bǔ)充一點(diǎn),數(shù)據(jù)庫(kù)出現(xiàn)異常時(shí),不要一股腦的catch RuntimeException,而是把具體關(guān)心的異常往外拋,然后進(jìn)行有針對(duì)性的異常處理。

 

關(guān)于其他性能方面

緩存設(shè)計(jì)都是占用越少越好,內(nèi)存資源昂貴以及太大不好維護(hù)都驅(qū)使我們這樣設(shè)計(jì)。所以要盡可能減少緩存不必要的數(shù)據(jù),有的同學(xué)圖省事把整個(gè)對(duì)象序列化存儲(chǔ)。另外,序列化與反序列化也是消耗性能的。

 

2、vs各種緩存同步方案

緩存同步方案有很多種,在考慮一致性、數(shù)據(jù)庫(kù)訪問(wèn)壓力、實(shí)時(shí)性等方面做權(quán)衡。總的來(lái)說(shuō)有以下幾種方式:


懶加載式

如上段提到的方式,讀時(shí)順便加載。為了更新緩存數(shù)據(jù),需要過(guò)期緩存。

                     


優(yōu)點(diǎn):簡(jiǎn)單直接

缺點(diǎn):

  • 會(huì)造成一次緩存不命中

  • 這樣當(dāng)用戶并發(fā)很大時(shí),恰好緩存中無(wú)數(shù)據(jù),數(shù)據(jù)庫(kù)承擔(dān)瞬時(shí)流量過(guò)大會(huì)造成風(fēng)險(xiǎn)。


懶加載式太簡(jiǎn)單了,沒(méi)有自動(dòng)加載,異步刷新等機(jī)制,為了彌補(bǔ)其缺陷,請(qǐng)參見(jiàn)接下來(lái)的兩種方法。


補(bǔ)充式

可以在緩存時(shí),把過(guò)期時(shí)間等信息寫(xiě)到一個(gè)異步隊(duì)列里,后臺(tái)起個(gè)線程池定期掃描這個(gè)隊(duì)列,在快過(guò)期時(shí)主動(dòng)reload緩存,使得數(shù)據(jù)會(huì)一直保持在緩存中,如果緩存沒(méi)有也沒(méi)有必要去數(shù)據(jù)庫(kù)查詢了。常見(jiàn)的處理方式有使用binlog加工成消息供增量處理。


  • 優(yōu)點(diǎn):刷新緩存變?yōu)楫惒降娜蝿?wù),對(duì)數(shù)據(jù)庫(kù)的壓力瞬間由于任務(wù)隊(duì)列的介入而降低了,削平并發(fā)的波峰。

  • 缺點(diǎn):消息一旦積壓會(huì)造成同步延遲,引入復(fù)雜度。

 

定時(shí)加載式

這就需要有個(gè)異步線程池定期把數(shù)據(jù)庫(kù)的數(shù)據(jù)刷到集中式緩存,如redis里。


  • 優(yōu)點(diǎn):保證所有數(shù)據(jù)最小時(shí)間差同步到緩存中,延遲很低。

  • 缺點(diǎn):如補(bǔ)充式,需要一個(gè)任務(wù)調(diào)度框架,復(fù)雜度提升,且要保證任務(wù)的順序。如果遞進(jìn)一步還想加載到本地緩存,就得本地應(yīng)用自己起線程抓取,方案維護(hù)成本高。可以考慮使用mq或者其他異步任務(wù)調(diào)度框架。

  • ps:為了防止隊(duì)列過(guò)大調(diào)度出現(xiàn)問(wèn)題,處理完的數(shù)據(jù)要盡快結(jié)轉(zhuǎn),且要對(duì)積壓數(shù)據(jù)以及寫(xiě)入情況做監(jiān)控。

 

3、防止緩存穿透

緩存穿透是指查詢的key壓根不存在,從而緩存查詢不到而查詢了數(shù)據(jù)庫(kù)。若是這樣的key恰好并發(fā)請(qǐng)求很大,那么就會(huì)對(duì)數(shù)據(jù)庫(kù)造成不必要的壓力。怎么解決呢?

  1. 把所有存在的key都存到另外一個(gè)存儲(chǔ)的Set集合里,查詢時(shí)可以先查詢key是否存在。

  2. 干脆簡(jiǎn)單一些,給查詢不到的key也加一個(gè)標(biāo)識(shí)空值的Value,這樣就不會(huì)去查詢數(shù)據(jù)庫(kù)了,比如場(chǎng)景為查詢省市區(qū)街道對(duì)應(yīng)的移動(dòng)營(yíng)業(yè)廳,若是某街道確實(shí)沒(méi)有移動(dòng)營(yíng)業(yè)廳,key規(guī)則不變,value可以設(shè)置為'0'等無(wú)意義的字符。當(dāng)然此種方案要保證緩存集群的高可用。

  3. 這些Key可能不是永遠(yuǎn)不存在,所以需要根據(jù)業(yè)務(wù)場(chǎng)景來(lái)設(shè)置過(guò)期時(shí)間。

 

4、熱點(diǎn)緩存與緩存淘汰策略

有一些場(chǎng)景,需要只保持一部分的熱點(diǎn)緩存,不需要全量緩存,比如熱賣的商品信息,購(gòu)買(mǎi)某類商品的熱門(mén)商圈信息等等。


綜合來(lái)講,緩存過(guò)期的策略有以下三種:


FIFO(First In,F(xiàn)irst Out)

先進(jìn)先出,淘汰最早進(jìn)來(lái)的緩存數(shù)據(jù),一個(gè)標(biāo)準(zhǔn)的隊(duì)列。

以隊(duì)列為基本數(shù)據(jù)結(jié)構(gòu),從隊(duì)首進(jìn)入新數(shù)據(jù),從隊(duì)尾淘汰。

 

LRU(Least RecentlyUsed)

最近最少使用,淘汰最近不使用的緩存數(shù)據(jù)。如果數(shù)據(jù)最近被訪問(wèn)過(guò),則不淘汰。

  1. 和FIFO不同的是,需要對(duì)鏈表做基本模型,讀寫(xiě)的時(shí)間復(fù)雜度是O(1),寫(xiě)入新數(shù)據(jù)進(jìn)入頭部,鏈表滿了數(shù)據(jù)從尾部淘汰;

  2. 最近時(shí)間被訪問(wèn)的數(shù)據(jù)移動(dòng)到頭部,實(shí)現(xiàn)算法有很多,如hashmap+雙向鏈表等等;

  3. 問(wèn)題在于若是偶發(fā)性某些key被最近頻繁訪問(wèn),而非常態(tài),則數(shù)據(jù)受到污染。

 

LFU(Least Frequently used)

最近使用次數(shù)最少的數(shù)據(jù)被淘汰,注意和LRU的區(qū)別在于LRU的淘汰規(guī)則是基于訪問(wèn)時(shí)間。

  1. LFU中的每個(gè)數(shù)據(jù)塊都有一個(gè)引用計(jì)數(shù),數(shù)據(jù)塊按照引用計(jì)數(shù)排序,若是恰好具有相同引用計(jì)數(shù)的數(shù)據(jù)塊則按照時(shí)間排序;

  2. 因?yàn)樾录尤氲臄?shù)據(jù)訪問(wèn)次數(shù)為1,所以插入到隊(duì)列尾部;

  3. 隊(duì)列中的數(shù)據(jù)被新訪問(wèn)后,引用計(jì)數(shù)增加,隊(duì)列重新排序;

  4. 當(dāng)需要淘汰數(shù)據(jù)時(shí),將已經(jīng)排序的列表最后的數(shù)據(jù)塊刪除;

  5. 有很明顯問(wèn)題是若短時(shí)間內(nèi)被頻繁訪問(wèn)多次,比如訪問(wèn)異?;蛘哐h(huán)沒(méi)有控制住,而后很長(zhǎng)時(shí)間未使用,則此數(shù)據(jù)會(huì)因?yàn)轭l率高而被錯(cuò)誤的保留下來(lái)沒(méi)有被淘汰。尤其對(duì)于新來(lái)的數(shù)據(jù),由于其起始的次數(shù)是1,所以即便被正常使用也會(huì)因?yàn)楸炔贿^(guò)老的數(shù)據(jù)而被淘汰。所以維基百科說(shuō)純粹的LFU算法不經(jīng)常單獨(dú)使用而是組合在其他策略中使用。


4、緩存使用的一些常見(jiàn)問(wèn)題 

Q:那么應(yīng)該選擇用本地緩存(local cache)還是集中式緩存(Cache cluster)呢?

A:首先看數(shù)據(jù)量,看緩存更新的成本,如果整體緩存數(shù)據(jù)量不是很大,而且變化的不頻繁,那么建議本地緩存。

 

Q:怎么批量更新一批緩存數(shù)據(jù)?

A:依次從數(shù)據(jù)庫(kù)讀取,然后批量寫(xiě)入緩存,批量更新,設(shè)置版本過(guò)期key或者主動(dòng)刪除。

 

Q:如果不知道有哪些key怎么定期刪除?

A:拿redis來(lái)說(shuō)keys * 太損耗性能,不推薦??梢灾付ㄒ粋€(gè)集合,把所有的key都存到這個(gè)集合里,然后對(duì)整個(gè)集合進(jìn)行刪除,這樣便能完全清理了。

 

Q:一個(gè)key包含的集合很大,redis無(wú)法做到內(nèi)存空間上的均勻Shard?

A:1、可以簡(jiǎn)單的設(shè)置key過(guò)期,這樣就要允許有緩存不命中的情況;2、給key設(shè)置版本,比如為兩天后的當(dāng)前時(shí)間,然后讀取緩存時(shí)用時(shí)間判斷一下是否需要重新加載緩存,作為版本過(guò)期的策略。




本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
系統(tǒng)性能測(cè)試及調(diào)優(yōu)
這10種神級(jí)性能優(yōu)化手段,你用過(guò)幾個(gè)?
Redis作為緩存自我總結(jié)(完全轉(zhuǎn)載)
深入理解CPU緩存一致性
帶你了解redis
架構(gòu)設(shè)計(jì)之性能設(shè)計(jì)經(jīng)驗(yàn)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服