亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

目錄
一、快取案例
1、TLB
2、抖音
3、HTTP協(xié)定快取
二、快取分類(lèi)
1、靜態(tài)快取
2、分佈式緩存
3、本地快取
三、快取的讀寫(xiě)策略
1、Cache Aside策略
2、Read/Write Through
3、Write Back
四、快取高可用
1、客戶端方案
2、中間代理層
3、服務(wù)端方案
五、快取穿透
1、帕累托
2、回種空值
3、布隆過(guò)濾器
4、狗樁效應(yīng)
六、CDN
拓展
首頁(yè) Java Java基礎(chǔ) java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇

java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇

Oct 10, 2020 pm 05:24 PM
java高並發(fā)

java基礎(chǔ)專(zhuān)欄今天介紹java高並發(fā)系統(tǒng)設(shè)計(jì)的快取篇。

java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇

常見(jiàn)硬體元件的延時(shí)情況如下圖:java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇

從這些資料中,你可以看到,做一次內(nèi)存尋址大概需要100ns,而做一次磁碟的查找則需要10ms??梢?jiàn),我們使用記憶體作為快取的儲(chǔ)存媒體相比於以磁碟作為主要儲(chǔ)存媒體的資料庫(kù)來(lái)說(shuō),效能上會(huì)提高多個(gè)數(shù)量級(jí)。所以,記憶體是最常見(jiàn)的一種快取資料的媒體。

一、快取案例

1、TLB

Linux 記憶體管理是透過(guò)一個(gè)叫做MMU(Memory Management Unit)的硬件,來(lái)實(shí)現(xiàn)從虛擬位址到物理位址的轉(zhuǎn)換的,但是如果每次轉(zhuǎn)換都要做這麼複雜計(jì)算的話,無(wú)疑會(huì)造成性能的損耗,所以我們會(huì)藉助一個(gè)叫做TLB(Translation Lookaside Buffer)的組件來(lái)緩存最近轉(zhuǎn)換過(guò)的虛擬地址,和物理地址的映射。 TLB 就是一種快取元件。

2、抖音

平臺(tái)上的短影片其實(shí)是使用內(nèi)建的網(wǎng)路播放器來(lái)完成的。網(wǎng)路播放器接收的是資料流,將資料下載下來(lái)之後經(jīng)過(guò)分離音視訊串流,解碼等流程後輸出到週邊設(shè)備上播放。播放器中通常會(huì)設(shè)計(jì)一些快取的組件,在未打開(kāi)視頻時(shí)緩存一部分視頻數(shù)據(jù),比如我們打開(kāi)抖音,服務(wù)端可能一次會(huì)返回三個(gè)視頻信息,我們?cè)诓シ诺谝粋€(gè)視頻的時(shí)候,播放器已經(jīng)幫我們快取了第二、三個(gè)影片的部分?jǐn)?shù)據(jù),這樣在看第二個(gè)影片的時(shí)候就可以給用戶「秒開(kāi)」的感覺(jué)。

3、HTTP協(xié)定快取

當(dāng)我們第一次要求靜態(tài)的資源時(shí),例如一張圖片,服務(wù)端除了回傳圖片訊息,在回應(yīng)頭裡面還有一個(gè)「Etag”的字段。瀏覽器會(huì)快取圖片資訊以及這個(gè)欄位的值。當(dāng)下次再要求這個(gè)圖片的時(shí)候,瀏覽器發(fā)起的請(qǐng)求頭裡面會(huì)有一個(gè)「If-None-Match」的字段,並且把快取的「Etag」的值寫(xiě)進(jìn)去發(fā)給服務(wù)端。服務(wù)端比對(duì)圖片資訊是否有變化,如果沒(méi)有,則傳回瀏覽器一個(gè) 304 的狀態(tài)碼,瀏覽器會(huì)繼續(xù)使用快取的圖片資訊。透過(guò)這種快取協(xié)商的方式,可以減少網(wǎng)路傳輸?shù)馁Y料大小,進(jìn)而提升頁(yè)面展示效能。 java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇

二、快取分類(lèi)

1、靜態(tài)快取

靜態(tài)快取在Web 1.0 時(shí)期是非常著名的,它一般透過(guò)產(chǎn)生Velocity 範(fàn)本或靜態(tài)HTML 文件來(lái)實(shí)現(xiàn)靜態(tài)緩存,在Nginx 上部署靜態(tài)緩存可以減少對(duì)於後臺(tái)應(yīng)用伺服器的壓力

2、分佈式緩存

分佈式緩存的大名可謂是如雷貫耳了,我們平時(shí)耳熟能詳?shù)腗emcached、Redis 就是分散式快取的典型例子。它們性能強(qiáng)勁,透過(guò)一些分散式的方案組成集群可以突破單機(jī)的限制。所以在整體架構(gòu)中,分散式快取承擔(dān)著非常重要的角色

3、本地快取

Guava Cache 或者是Ehcache 等,它們和應(yīng)用程式部署在同一個(gè)進(jìn)程中,優(yōu)勢(shì)是不需要跨網(wǎng)路調(diào)度,速度極快,所以可以用來(lái)阻擋短時(shí)間內(nèi)的熱點(diǎn)查詢。

三、快取的讀寫(xiě)策略

1、Cache Aside策略

#在更新資料時(shí)不更新緩存,而是刪除快取中的數(shù)據(jù),在讀取數(shù)據(jù)時(shí),發(fā)現(xiàn)快取中沒(méi)了數(shù)據(jù)之後,再?gòu)馁Y料庫(kù)讀取數(shù)據(jù),更新到快取中。 java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇

這個(gè)策略就是我們使用快取最常見(jiàn)的策略,Cache Aside 策略(也叫旁路快取策略),這個(gè)策略資料以資料庫(kù)中的資料為準(zhǔn),快取中的資料是按需加載的。

Cache Aside 策略是我們?nèi)粘i_(kāi)發(fā)中最常使用的快取策略,不過(guò)我們?cè)谑褂脮r(shí)也要學(xué)會(huì)依情況而變,並不是一成不變的。 Cache Aside 存在的最大的問(wèn)題是當(dāng)寫(xiě)入比較頻繁時(shí),快取中的資料會(huì)被頻繁地清理,這會(huì)對(duì)快取的命中率有一些影響。如果你的業(yè)務(wù)對(duì)快取命中率有嚴(yán)格的要求,那麼可以考慮兩個(gè)解決方案:

一種做法是在更新資料時(shí)也更新緩存,只是在更新緩存前先加一個(gè)分散式鎖,因?yàn)檫@樣在同一時(shí)間只允許一個(gè)執(zhí)行緒更新緩存,就不會(huì)產(chǎn)生並發(fā)問(wèn)題了。當(dāng)然這麼做對(duì)於寫(xiě)入的性能會(huì)有一些影響(推薦);

另一種做法同樣也是在更新數(shù)據(jù)時(shí)更新緩存,只是給緩存加一個(gè)較短的過(guò)期時(shí)間,這樣即使出現(xiàn)緩存不一致的情況,快取的資料也會(huì)很快過(guò)期,對(duì)業(yè)務(wù)的影響也可以接受。

2、Read/Write Through

這個(gè)策略的核心原則是使用者只與快取打交道,由快取和資料庫(kù)通信,寫(xiě)入或讀取資料。 java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇

Write Through

的策略是這樣的:先查詢要寫(xiě)入的資料在快取中是否已經(jīng)存在,如果已經(jīng)存在,則更新緩存中的數(shù)據(jù),並且由快取元件同步更新到資料庫(kù)中,如果快取中資料不存在,我們把這種情況叫做「Write Miss(寫(xiě)失效)」。一般來(lái)說(shuō),我們可以選擇兩種“Write Miss”方式:一個(gè)是“Write Allocate(按寫(xiě)分配)”,做法是寫(xiě)入快取對(duì)應(yīng)位置,再由快取元件同步更新到資料庫(kù)中;另一個(gè)是“No -write allocate(不按寫(xiě)分配)”,做法是不寫(xiě)入快取中,而是直接更新到資料庫(kù)中。 我們看到 Write Through 策略中寫(xiě)入資料庫(kù)是同步的,這對(duì)於效能來(lái)說(shuō)會(huì)有比較大的影響,因?yàn)橄噍^於寫(xiě)入緩存,同步寫(xiě)入資料庫(kù)的延遲就要高很多了。透過(guò)Write Back策略異步的更新資料庫(kù)。

Read Through

策略就簡(jiǎn)單一些,它的步驟是這樣的:先查詢快取中資料是否存在,如果存在則直接傳回,如果不存在,則由快取元件負(fù)責(zé)從資料庫(kù)同步載入資料。

3、Write Back

這個(gè)策略的核心思想是在寫(xiě)入資料時(shí)只寫(xiě)入緩存,並且把快取區(qū)塊兒標(biāo)記為「髒」的。而髒塊兒只有在再次使用時(shí)才會(huì)將其中的資料寫(xiě)入後端儲(chǔ)存。 在「Write Miss」的情況下,我們採(cǎi)用的是「Write Allocate」的方式,也就是在寫(xiě)入後端儲(chǔ)存的同時(shí)要寫(xiě)入緩存,這樣我們?cè)谥岬膶?xiě)入請(qǐng)求中都只需要更新快取即可,而無(wú)需更新後端儲(chǔ)存了。注意與上面的write through策略作區(qū)分。 java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇

我們?cè)谧x取快取時(shí)如果發(fā)現(xiàn)快取命中則直接傳回快取資料。如果快取不命中則尋找一個(gè)可用的快取區(qū)塊兒,如果這個(gè)快取區(qū)塊兒是「髒」的,就把快取區(qū)塊兒中之前的資料寫(xiě)入到後端儲(chǔ)存中,並且從後端儲(chǔ)存載入資料到快取塊兒,如果不是髒的,則由快取元件將後端儲(chǔ)存中的資料載入到快取中,最後我們將快取設(shè)定為不是髒的,回傳資料就好了。 java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇

write back策略多用於向磁碟中寫(xiě)入資料。例如:作業(yè)系統(tǒng)層面的 Page Cache、日誌的非同步刷盤(pán)、訊息佇列中訊息的非同步寫(xiě)入磁碟等。因?yàn)檫@個(gè)策略在效能上的優(yōu)勢(shì)毋庸置疑,它避免了直接寫(xiě)磁碟造成的隨機(jī)寫(xiě)入問(wèn)題,畢竟寫(xiě)記憶體和寫(xiě)入磁碟的隨機(jī) I/O 的延遲相差了幾個(gè)數(shù)量級(jí)呢。

四、快取高可用

快取的命中率是快取需要監(jiān)控的資料指標(biāo),快取的高可用可以一定程度上減少快取穿透的機(jī)率,提升系統(tǒng)的穩(wěn)定性??烊〉母呖捎梅桨钢饕蛻舳朔桨?、中間代理層方案和服務(wù)端方案三大類(lèi):

1、客戶端方案

在客戶端方案中,你需要專(zhuān)注於緩存的寫(xiě)和讀兩方面: 寫(xiě)入資料時(shí),需要把寫(xiě)入快取的資料分散到多個(gè)節(jié)點(diǎn)中,即進(jìn)行資料分片; 讀取資料時(shí),可以利用多組的快取來(lái)做容錯(cuò),提升快取系統(tǒng)的可用性。關(guān)於讀取數(shù)據(jù),這裡可以使用主從和多副本兩種策略,兩種策略是為了解決不同的問(wèn)題而提出的。 具體的實(shí)作細(xì)節(jié)包括:資料分片、主從、多副本

資料分片

一致性Hash演算法。在這個(gè)演算法中,我們將整個(gè) Hash 值空間組織成一個(gè)虛擬的圓環(huán),然後將快取節(jié)點(diǎn)的 IP 位址或主機(jī)名稱做 Hash 取值後,就放置在這個(gè)圓環(huán)上。當(dāng)我們需要確定某一個(gè)Key 需要訪問(wèn)到哪個(gè)節(jié)點(diǎn)上的時(shí)候,先對(duì)這個(gè)Key 做同樣的Hash 取值,確定在環(huán)上的位置,然後按照順時(shí)針?lè)较蛟诃h(huán)上“行走”,遇到的第一個(gè)快取節(jié)點(diǎn)就是要存取的節(jié)點(diǎn)。 java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇

這時(shí)如果在Node 1 和Node 2 之間增加一個(gè)Node 5,你可以看到原本命中Node 2 的Key 3 現(xiàn)在命中到Node 5,而其它的Key 都沒(méi)有變化;同樣的道理,如果我們把Node 3 從叢集中移除,只會(huì)影響到Key 5 。所以你看,在增加和刪除節(jié)點(diǎn)時(shí),只有少量的 Key 會(huì)「漂移」到其它節(jié)點(diǎn)上,而大部分的 Key 命中的節(jié)點(diǎn)還是會(huì)保持不變,從而可以保證命中率不會(huì)大幅下降。 【提示】一致性hash出現(xiàn)的快取雪崩現(xiàn)象使用虛擬節(jié)點(diǎn)解決。一致性hash分片與hash分片的差別在於,快取命中率的問(wèn)題,hash分片在存在機(jī)器加入或是減少的情況時(shí)候,會(huì)導(dǎo)致快取失效,快取命中率下降。

主從

Redis 本身支援主從的部署方式,但是 Memcached 並不支持,Memcached 的主從機(jī)制是如何在客戶端實(shí)現(xiàn)的。為每一組 Master 設(shè)定一組 Slave,更新資料時(shí)主從同步更新。讀取時(shí),優(yōu)先從 Slave 中讀數(shù)據(jù),如果讀取不到數(shù)據(jù)就穿透到 Master 讀取,並且將數(shù)據(jù)回種到 Slave 中以保持 Slave 數(shù)據(jù)的熱度。主從機(jī)制最大的優(yōu)點(diǎn)就是當(dāng)某一個(gè) Slave 宕機(jī)時(shí),還會(huì)有 Master 作為兜底,不會(huì)有大量請(qǐng)求穿透到資料庫(kù)的情況發(fā)生,提升了快取系統(tǒng)的高可用性。

多重複製

主從方式已經(jīng)能夠解決大部分場(chǎng)景的問(wèn)題,但是對(duì)於極端流量的場(chǎng)景下,一組Slave 通常來(lái)說(shuō)並不能完全承擔(dān)所有流量,Slave 網(wǎng)路卡頻寬可能成為瓶頸。為了解決這個(gè)問(wèn)題,我們考慮在Master/Slave 之前增加一層副本層,整體架構(gòu)是這樣的:java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇

這個(gè)方案中,當(dāng)客戶端發(fā)起查詢請(qǐng)求時(shí),請(qǐng)求首先會(huì)先從在多個(gè)副本群組中選取一個(gè)副本群組發(fā)起查詢,如果查詢失敗,就繼續(xù)查詢Master/Slave,並且將查詢的結(jié)果回種到所有副本群組中,避免副本群組中髒資料的存在?;冻杀镜目紤],每個(gè)副本組容量比 Master 和 Slave 要小,因此它只儲(chǔ)存了更加熱的資料。在這套架構(gòu)中,Master 和 Slave 的請(qǐng)求量會(huì)大幅減少,為了確保它們儲(chǔ)存資料的熱度,在實(shí)務(wù)上我們會(huì)把 Master 和 Slave 作為一組副本組使用。

2、中間代理層

業(yè)界也有很多中間代理層方案,像是 Facebook 的Mcrouter,Twitter 的Twemproxy,豌豆莢的Codis。它們的原理基本上可以由一張圖來(lái)概括:java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇

3、服務(wù)端方案

Redis 在2.4 版本中提出了Redis Sentinel 模式來(lái)解決主從Redis 部署時(shí)的高可用問(wèn)題,它可以在主節(jié)點(diǎn)掛了以後自動(dòng)將從節(jié)點(diǎn)提升為主節(jié)點(diǎn),保證整體叢集的可用性,整體的架構(gòu)如下圖所示:java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇

redis Sentinel 也是叢集部署的,這樣可以避免Sentinel 節(jié)點(diǎn)掛掉造成無(wú)法自動(dòng)故障復(fù)原的問(wèn)題,每一個(gè)Sentinel 節(jié)點(diǎn)都是無(wú)狀態(tài)的。在Sentinel 中會(huì)配置Master 的位址,Sentinel 會(huì)時(shí)時(shí)刻刻監(jiān)控Master 的狀態(tài),當(dāng)發(fā)現(xiàn)Master 在設(shè)定的時(shí)間間隔內(nèi)無(wú)回應(yīng),就認(rèn)為Master 已經(jīng)掛了,Sentinel 會(huì)從從節(jié)點(diǎn)中選取一個(gè)提升為主節(jié)點(diǎn),並且把所有其他的從節(jié)點(diǎn)作為新主的從節(jié)點(diǎn)。 Sentinel 叢集內(nèi)部在仲裁的時(shí)候,會(huì)根據(jù)配置的值來(lái)決定當(dāng)有幾個(gè) Sentinel 節(jié)點(diǎn)認(rèn)為主掛掉可以做主從切換的操作,也就是叢集內(nèi)部需要對(duì)快取節(jié)點(diǎn)的狀態(tài)達(dá)成一致才行。

【提示】上述客戶端到sentinel叢集的連線是虛線,因?yàn)閷?duì)於快取的寫(xiě)入和讀取請(qǐng)求不會(huì)經(jīng)過(guò) Sentinel 節(jié)點(diǎn)。

五、快取穿透

1、帕累托

網(wǎng)路系統(tǒng)的資料存取模型一般會(huì)遵從「80/20 原則」。 「80/20 原則」又稱為帕累託法則,是義大利經(jīng)濟(jì)學(xué)家帕累托提出的經(jīng)濟(jì)學(xué)的理論。簡(jiǎn)單來(lái)說(shuō),它是指在一組事物中,最重要的部分通常只佔(zhàn) 20%,而其他的 80% 並沒(méi)有那麼重要。把它應(yīng)用到數(shù)據(jù)存取的領(lǐng)域,就是我們會(huì)經(jīng)常存取 20% 的熱點(diǎn)數(shù)據(jù),而另外的 80% 的數(shù)據(jù)則不會(huì)被經(jīng)常存取。既然快取的容量有限,而且大部分的存取只會(huì)請(qǐng)求20% 的熱點(diǎn)數(shù)據(jù),那麼理論上說(shuō),我們只需要在有限的快取空間裡儲(chǔ)存20% 的熱點(diǎn)資料就可以有效地保護(hù)脆弱的後端系統(tǒng)了,也就可以放棄快取另外80% 的非熱點(diǎn)資料了。所以這種少量的緩存穿透是不可避免的,但是對(duì)系統(tǒng)是沒(méi)有損害的。

2、回種空值

當(dāng)我們從資料庫(kù)中查詢到空值或發(fā)生異常時(shí),我們可以向快取中回種一個(gè)空值。但是因?yàn)榭罩祦K不是準(zhǔn)確的業(yè)務(wù)數(shù)據(jù),並且會(huì)佔(zhàn)用快取的空間,所以我們會(huì)為這個(gè)空值加一個(gè)比較短的過(guò)期時(shí)間,讓空值在短時(shí)間內(nèi)能夠快速過(guò)期淘汰。回種空值雖然能夠阻擋大量穿透的請(qǐng)求,但如果有大量的空值緩存,也會(huì)浪費(fèi)緩存的存儲(chǔ)空間,如果緩存空間被佔(zhàn)滿了,還會(huì)剔除掉一些已經(jīng)被緩存的用戶信息反而會(huì)造成快取命中率的下降。所以這個(gè)方案,我建議你在使用的時(shí)候應(yīng)該評(píng)估緩存容量是否能夠支撐。如果需要大量的快取節(jié)點(diǎn)來(lái)支持,那麼就無(wú)法透過(guò)回種空值的方式來(lái)解決,這時(shí)你可以考慮使用布隆過(guò)濾器。

3、布隆過(guò)濾器

1970 年布隆提出了一個(gè)布林過(guò)濾器的演算法,用來(lái)判斷一個(gè)元素是否在一個(gè)集合中。這種演算法由一個(gè)二進(jìn)制數(shù)組和一個(gè) Hash 演算法組成。它的基本想法如下:我們把集合中的每一個(gè)值按照提供的Hash 演算法算出對(duì)應(yīng)的Hash 值,然後將Hash 值對(duì)數(shù)組長(zhǎng)度取模後得到需要計(jì)入數(shù)組的索引值,並且將數(shù)組這個(gè)位置的值從0 改成1。在判斷一個(gè)元素是否存在於這個(gè)集合中時(shí),你只需要將這個(gè)元素依照相同的演算法計(jì)算出索引值,如果這個(gè)位置的值為 1 就認(rèn)為這個(gè)元素在集合中,否則則認(rèn)為不在集合中。 java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇

如何使用布隆過(guò)濾器解決快取穿透呢?

以儲(chǔ)存使用者資訊的表格為例進(jìn)行講解。首先我們初始化一個(gè)很大的數(shù)組,比方說(shuō)長(zhǎng)度為20 億的數(shù)組,接下來(lái)我們選擇一個(gè)Hash 演算法,然後我們將目前現(xiàn)有的所有用戶的ID 計(jì)算出Hash 值並且映射到這個(gè)大數(shù)組中,映射位置的值設(shè)定為1,其它值設(shè)定為0。新註冊(cè)的用戶除了需要寫(xiě)入資料庫(kù)之外,它也需要依照相同的演算法更新布隆過(guò)濾器的陣列中對(duì)應(yīng)位置的值。那麼當(dāng)我們需要查詢某一個(gè)用戶的資訊時(shí),先查詢這個(gè)ID 在布隆過(guò)濾器中是否存在,如果不存在就直接返回空值,而不需要繼續(xù)查詢資料庫(kù)和緩存,這樣就可以大大減少異常查詢帶來(lái)的快取穿透。 java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇

布隆過(guò)濾器優(yōu)點(diǎn):

(1)效能高。無(wú)論是寫(xiě)入操作還是讀取操作,時(shí)間複雜度都是 O(1) 是常數(shù)值

(2)節(jié)省空間。例如,20 億的數(shù)組需要2000000000/8/1024/1024 = 238M 的空間,而如果使用數(shù)組來(lái)存儲(chǔ),假設(shè)每個(gè)用戶ID 佔(zhàn)用4 個(gè)字節(jié)的空間,那麼存儲(chǔ)20 億用戶需要2000000000 * 4 / 1024 / 1024 = 7600M 的空間,是布隆過(guò)濾器的32 倍。

布隆過(guò)濾器缺點(diǎn):

(1)它在判斷元素是否在集合中時(shí)是有一定錯(cuò)誤幾率的,例如它會(huì)把不是集合中的元素判斷為處在集合中。

原因:Hash演算法本身的缺陷。

解決方案:使用多個(gè) Hash 演算法為元素計(jì)算出多個(gè) Hash 值,只有所有 Hash 值對(duì)應(yīng)的陣列中的值都為 1 時(shí),才會(huì)認(rèn)為這個(gè)元素在集合中。

(2)不支援刪除元素。布隆過(guò)濾器不支援刪除元素的缺陷也和 Hash 碰撞有關(guān)。舉一個(gè)例子,假如兩個(gè)元素 A 和 B 都是集合中的元素,它們有相同的 Hash 值,它們就會(huì)對(duì)應(yīng)到陣列的同一個(gè)位置。這時(shí)我們刪除了 A,陣列中對(duì)應(yīng)位置的值也從 1 變成 0,那麼在判斷 B 的時(shí)候發(fā)現(xiàn)值是 0,也會(huì)判斷 B 是不在集合中的元素,就會(huì)得到錯(cuò)誤的結(jié)論。

解決方案:我會(huì)讓陣列中不再只有 0 和 1 兩個(gè)值,而是儲(chǔ)存一個(gè)計(jì)數(shù)。例如如果 A 和 B 同時(shí)命中了一個(gè)陣列的索引,那麼這個(gè)位置的值就是 2,如果 A 被刪除了就把這個(gè)值從 2 改為 1。這個(gè)方案中的陣列不再儲(chǔ)存 bit 位,而是儲(chǔ)存數(shù)值,也會(huì)增加空間的消耗。

4、狗樁效應(yīng)

比方說(shuō)當(dāng)有一個(gè)極熱點(diǎn)的緩存項(xiàng),它一旦失效會(huì)有大量請(qǐng)求穿透到資料庫(kù),這會(huì)對(duì)資料庫(kù)造成瞬時(shí)極大的壓力,我們把這個(gè)場(chǎng)景叫做「dog-pile effect」(狗樁效應(yīng))。解決狗樁效應(yīng)的想法是盡量減少緩存穿透後的並發(fā),方案也比較簡(jiǎn)單:

(1)在程式碼中控制在某一個(gè)熱點(diǎn)緩存項(xiàng)目失效之後啟動(dòng)一個(gè)後臺(tái)線程,穿透到資料庫(kù),將資料載入到快取中,在快取未載入之前,所有存取這個(gè)快取的請(qǐng)求都不再穿透而直接返回。

(2)透過(guò)在Memcached 或Redis 中設(shè)定分散式鎖,只有取得到鎖的請(qǐng)求才能夠穿透到資料庫(kù)

六、CDN

##1、靜態(tài)資源加速的原因

在我們的系統(tǒng)中存在著大量的靜態(tài)資源請(qǐng)求:對(duì)於行動(dòng)APP 來(lái)說(shuō),這些靜態(tài)資源主要是圖片、影片和串流媒體資訊;對(duì)於Web 網(wǎng)站來(lái)說(shuō),則包括了JavaScript 檔案、CSS 檔案、靜態(tài)HTML 檔案等等。它們的讀取請(qǐng)求量極大並且對(duì)訪問(wèn)速度的要求很高還佔(zhàn)據(jù)了很高的頻寬,這時(shí)會(huì)出現(xiàn)訪問(wèn)速度慢頻寬被佔(zhàn)滿影響動(dòng)態(tài)請(qǐng)求的問(wèn)題,那麼你就需要考慮如何針對(duì)這些靜態(tài)資源進(jìn)行讀加速了。

2、CDN

靜態(tài)資源存取的關(guān)鍵點(diǎn)是就近訪問(wèn),即北京用戶訪問(wèn)北京的數(shù)據(jù),杭州用戶訪問(wèn)杭州的數(shù)據(jù),這樣才可以達(dá)到性能的最優(yōu)。我們考慮在業(yè)務(wù)伺服器的上層增加一層特殊的緩存,用來(lái)承擔(dān)絕大部分對(duì)於靜態(tài)資源的訪問(wèn),這一層特殊緩存的節(jié)點(diǎn)需要遍布在全國(guó)各地,這樣可以讓用戶選擇最近的節(jié)點(diǎn)訪問(wèn)??烊〉拿新室残枰欢ǖ谋WC,盡量減少存取資源儲(chǔ)存源站的請(qǐng)求數(shù)量(回源請(qǐng)求)。這一層快取就是CDN。

CDN(Content Delivery Network/Content Distribution Network,內(nèi)容傳遞網(wǎng)路)。簡(jiǎn)單來(lái)說(shuō),CDN 是將靜態(tài)的資源分發(fā)到位於多個(gè)地理位置機(jī)房中的伺服器上,因此它能很好地解決資料就近存取的問(wèn)題,也就加快了靜態(tài)資源的存取速度。

3、建構(gòu)CDN系統(tǒng)

建構(gòu)一個(gè)CDN 系統(tǒng)需要考慮哪兩點(diǎn):

(1)如何將使用者的請(qǐng)求對(duì)應(yīng)到CDN 節(jié)點(diǎn)上

你可能會(huì)覺(jué)得這很簡(jiǎn)單啊,只需要告訴用戶CDN 節(jié)點(diǎn)的IP 位址,然後請(qǐng)求這個(gè)IP 位址上面部署的CDN 服務(wù)就可以了啊。但是,並不是這樣,需要把ip替換為對(duì)應(yīng)的網(wǎng)域。那麼如何做到這一點(diǎn)呢?這就需要依賴 DNS 來(lái)幫我們解決網(wǎng)域?qū)τ车膯?wèn)題了。 DNS(Domain Name System,網(wǎng)域名稱系統(tǒng))其實(shí)就是一個(gè)儲(chǔ)存網(wǎng)域名稱和 IP 位址對(duì)應(yīng)關(guān)係的分散式資料庫(kù)。而域名解析的結(jié)果一般有兩種,一種叫做“A 記錄”,返回的是域名對(duì)應(yīng)的IP 位址;另一種是“CNAME 記錄”,返回的是另一個(gè)域名,也就是說(shuō)當(dāng)前域名的解析要跳到另一個(gè)網(wǎng)域的解析上。

舉個(gè)例子:例如你的公司的一級(jí)網(wǎng)域叫做example.com,那麼你可以把你的圖片服務(wù)的網(wǎng)域定義為“img.example.com”,然後將這個(gè)網(wǎng)域的解析結(jié)果的CNAME 配置到CDN 提供的網(wǎng)域上,例如uclound 可能會(huì)提供一個(gè)網(wǎng)域是「80f21f91.cdn.ucloud.com.cn」這個(gè)網(wǎng)域。這樣你的電商系統(tǒng)使用的圖片位址可以是「img.example.com/1.jpg」。

使用者在要求這個(gè)位址時(shí),DNS 伺服器會(huì)將網(wǎng)域名稱解析到80f21f91.cdn.ucloud.com.cn 網(wǎng)域上,然後再將這個(gè)網(wǎng)域解析為CDN 的節(jié)點(diǎn)IP,這樣就可以得到CDN 上面的資源數(shù)據(jù)了。

網(wǎng)域?qū)蛹?jí)解析最佳化

因?yàn)榫W(wǎng)域解析過(guò)程是分級(jí)的,每一層有專(zhuān)門(mén)的網(wǎng)域名稱伺服器承擔(dān)解析的職責(zé),所以網(wǎng)域的解析過(guò)程有可能需要跨越公網(wǎng)做多次DNS 查詢,在效能上是比較差的。一個(gè)解決的想法是:在 APP 啟動(dòng)時(shí)對(duì)需要解析的網(wǎng)域做預(yù)先解析,然後把解析的結(jié)果快取到本地的一個(gè) LRU 快取裡面。這樣當(dāng)我們要使用這個(gè)網(wǎng)域的時(shí)候,只需要從快取直接拿到所需要的 IP 位址就好了,如果快取中不存在才會(huì)走整個(gè) DNS 查詢的過(guò)程。同時(shí)為了避免 DNS 解析結(jié)果的變更造成快取內(nèi)資料失效,我們可以啟動(dòng)計(jì)時(shí)器定期更新快取中的資料。

(2)如何根據(jù)使用者的地理位置資訊選擇到比較近的節(jié)點(diǎn)。

GSLB(Global Server Load Balance,全域負(fù)載平衡)的意思是對(duì)於部署在不同地域的伺服器之間做負(fù)載平衡,下面可能管理了很多的本地負(fù)載平衡元件。它有兩方面的作用:一方面,它是一種負(fù)載平衡伺服器,負(fù)載平衡,顧名思義嘛,指的是讓流量平均分配使得下面管理的伺服器的負(fù)載更平均;另一方面,它還需要保證流量流經(jīng)的伺服器與流量源頭在地緣上是比較接近的。

GSLB 可以透過(guò)多種策略來(lái)保證傳回的CDN 節(jié)點(diǎn)和使用者盡量保證在同一地緣區(qū)域,比如說(shuō)可以將使用者的IP 位址依照地理位置劃分為若干個(gè)區(qū)域,然後將CDN 節(jié)點(diǎn)對(duì)應(yīng)到在一個(gè)區(qū)域上,根據(jù)使用者所在區(qū)域來(lái)傳回適當(dāng)?shù)墓?jié)點(diǎn);也可以透過(guò)發(fā)送資料包測(cè)量RTT 的方式來(lái)決定傳回哪一個(gè)節(jié)點(diǎn)。

總結(jié):DNS 技術(shù)是CDN 實(shí)作中使用的核心技術(shù),可以將使用者的請(qǐng)求映射到CDN 節(jié)點(diǎn)上;DNS 解析結(jié)果需要做本地緩存,降低DNS 解析過(guò)程的回應(yīng)時(shí)間;GSLB 可以給用戶回傳一個(gè)離他更近的節(jié)點(diǎn),加快靜態(tài)資源的存取速度。

拓展

(1)百度網(wǎng)域的解析過(guò)程

一開(kāi)始,網(wǎng)域解析請(qǐng)求先會(huì)檢查本機(jī)的hosts 文件,查看是否有www.baidu.com 對(duì)應(yīng)的IP;如果沒(méi)有的話,就請(qǐng)求Local DNS 是否有域名解析結(jié)果的緩存,如果有就返回標(biāo)識(shí)是從非權(quán)威DNS 返回的結(jié)果;如果沒(méi)有就開(kāi)始DNS 的迭代查詢。先請(qǐng)求根DNS,根DNS 回傳頂級(jí)DNS(.com)的位址;再請(qǐng)求.com 頂級(jí)DNS 得到baidu.com 的網(wǎng)域名稱伺服器位址;再?gòu)腷aidu.com 的網(wǎng)域伺服器查詢到www.baidu.com 對(duì)應(yīng)的IP 位址,傳回這個(gè)IP 位址的同時(shí)標(biāo)記這個(gè)結(jié)果是來(lái)自於權(quán)威DNS 的結(jié)果,同時(shí)寫(xiě)入Local DNS 的解析結(jié)果緩存,這樣下一次的解析同一個(gè)網(wǎng)域就不需要做DNS 的迭代查詢了。

(2)CDN延時(shí)

一般我們會(huì)透過(guò)CDN 廠商的介面將靜態(tài)的資源寫(xiě)入到某一個(gè)CDN 節(jié)點(diǎn)上,再由CDN 內(nèi)部的同步機(jī)制將資源分散同步到每個(gè)CDN 節(jié)點(diǎn),即使CDN 內(nèi)部網(wǎng)路經(jīng)過(guò)了最佳化,這個(gè)同步的過(guò)程是有延時(shí)的,一旦我們無(wú)法從選定的CDN 節(jié)點(diǎn)上獲取到數(shù)據(jù),我們就不得不從來(lái)源站獲取數(shù)據(jù),而用戶網(wǎng)路到源站的網(wǎng)路可能會(huì)跨越多個(gè)主幹網(wǎng),這樣不僅性能上有損耗也會(huì)消耗源站的頻寬,帶來(lái)更高的研發(fā)成本。所以我們?cè)谑褂?CDN 的時(shí)候需要注意 CDN 的命中率和源站的頻寬情況。

相關(guān)學(xué)習(xí)推薦:java基礎(chǔ)

以上是java高並發(fā)系統(tǒng)設(shè)計(jì)之緩存篇的詳細(xì)內(nèi)容。更多資訊請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願(yuàn)投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請(qǐng)聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開(kāi)發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺(jué)化網(wǎng)頁(yè)開(kāi)發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)程式碼編輯軟體(SublimeText3)

熱門(mén)話題

Laravel 教程
1597
29
PHP教程
1488
72