成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

沒看這篇干貨,別說你會使用“緩存”

2021-02-02    分類: 網(wǎng)站建設(shè)

在互聯(lián)網(wǎng)高速發(fā)展的今天,緩存技術(shù)被廣泛地應(yīng)用。無論業(yè)內(nèi)還是業(yè)外,只要是提到性能問題,大家都會脫口而出“用緩存解決”。

圖片來自 Unsplash

這種說法帶有片面性,甚至是一知半解,但是作為專業(yè)人士的我們,需要對緩存有更深、更廣的了解。

緩存技術(shù)存在于應(yīng)用場景的方方面面。從瀏覽器請求,到反向代理服務(wù)器,從進(jìn)程內(nèi)緩存到分布式緩存。其中緩存策略,算法也是層出不窮,今天就帶大家走進(jìn)緩存。

處處皆緩存

緩存對于每個開發(fā)者來說是相當(dāng)熟悉了,為了提高程序的性能我們會去加緩存,但是在什么地方加緩存,如何加緩存呢?

假設(shè)一個網(wǎng)站,需要提高性能,緩存可以放在瀏覽器,可以放在反向代理服務(wù)器,還可以放在應(yīng)用程序進(jìn)程內(nèi),同時(shí)可以放在分布式緩存系統(tǒng)中。

負(fù)載均衡緩存工作簡圖

以 Nginx 為例,我們看看它是如何工作的:

  • 用戶請求在達(dá)到應(yīng)用服務(wù)器之前,會先訪問 Nginx 負(fù)載均衡器,如果發(fā)現(xiàn)有緩存信息,直接返回給用戶。
  • 如果沒有發(fā)現(xiàn)緩存信息,Nginx 回源到應(yīng)用服務(wù)器獲取信息。
  • 另外,有一個緩存更新服務(wù),定期把應(yīng)用服務(wù)器中相對穩(wěn)定的信息更新到 Nginx 本地緩存中。

進(jìn)程內(nèi)緩存

通過了客戶端,

消息隊(duì)列修改方案簡圖

Timer 修改方案

為了避免耦合,降低復(fù)雜性,對“實(shí)時(shí)一致性”不敏感的情況下。每個應(yīng)用都會啟動一個 Timer,定時(shí)從數(shù)據(jù)庫拉取最新的數(shù)據(jù),更新緩存。

不過在有的應(yīng)用更新數(shù)據(jù)庫后,其他節(jié)點(diǎn)通過 Timer 獲取數(shù)據(jù)之間,會讀到臟數(shù)據(jù)。這里需要控制好 Timer 的頻率,以及應(yīng)用與對實(shí)時(shí)性要求不高的場景。

Timer 修改方案簡圖

進(jìn)程內(nèi)緩存有哪些使用場景呢?

  • 場景一:只讀數(shù)據(jù),可以考慮在進(jìn)程啟動時(shí)加載到內(nèi)存。當(dāng)然,把數(shù)據(jù)加載到類似 Redis 這樣的進(jìn)程外緩存服務(wù)也能解決這類問題。
  • 場景二:高并發(fā),可以考慮使用進(jìn)程內(nèi)緩存,例如:秒殺。

分布式緩存

說完進(jìn)程內(nèi)緩存,自然就過度到進(jìn)程外緩存了。與進(jìn)程內(nèi)緩存不同,進(jìn)程外緩存在應(yīng)用運(yùn)行的進(jìn)程之外,它擁有更大的緩存容量,并且可以部署到不同的物理節(jié)點(diǎn),通常會用分布式緩存的方式實(shí)現(xiàn)。

分布式緩存是與應(yīng)用分離的緩存服務(wù),大的特點(diǎn)是,自身是一個獨(dú)立的應(yīng)用/服務(wù),與本地應(yīng)用隔離,多個應(yīng)用可直接共享一個或者多個緩存應(yīng)用/服務(wù)。

分布式緩存簡圖

既然是分布式緩存,緩存的數(shù)據(jù)會分布到不同的緩存節(jié)點(diǎn)上,每個緩存節(jié)點(diǎn)緩存的數(shù)據(jù)大小通常也是有限制的。

數(shù)據(jù)被緩存到不同的節(jié)點(diǎn),為了能方便的訪問這些節(jié)點(diǎn),需要引入緩存代理,類似 Twemproxy。他會幫助請求找到對應(yīng)的緩存節(jié)點(diǎn)。

同時(shí)如果緩存節(jié)點(diǎn)增加了,這個代理也會只能識別并且把新的緩存數(shù)據(jù)分片到新的節(jié)點(diǎn),做橫向的擴(kuò)展。

為了提高緩存的可用性,會在原有的緩存節(jié)點(diǎn)上加入 Master/Slave 的設(shè)計(jì)。當(dāng)緩存數(shù)據(jù)寫入 Master 節(jié)點(diǎn)的時(shí)候,會同時(shí)同步一份到 Slave 節(jié)點(diǎn)。

一旦 Master 節(jié)點(diǎn)失效,可以通過代理直接切換到 Slave 節(jié)點(diǎn),這時(shí) Slave 節(jié)點(diǎn)就變成了 Master 節(jié)點(diǎn),保證緩存的正常工作。

每個緩存節(jié)點(diǎn)還會提供緩存過期的機(jī)制,并且會把緩存內(nèi)容定期以快照的方式保存到文件上,方便緩存崩潰之后啟動預(yù)熱加載。

高性能

當(dāng)緩存做成分布式的時(shí)候,數(shù)據(jù)會根據(jù)一定的規(guī)律分配到每個緩存應(yīng)用/服務(wù)上。

如果我們把這些緩存應(yīng)用/服務(wù)叫做緩存節(jié)點(diǎn),每個節(jié)點(diǎn)一般都可以緩存一定容量的數(shù)據(jù),例如:Redis 一個節(jié)點(diǎn)可以緩存 2G 的數(shù)據(jù)。

如果需要緩存的數(shù)據(jù)量比較大就需要擴(kuò)展多個緩存節(jié)點(diǎn)來實(shí)現(xiàn),這么多的緩存節(jié)點(diǎn),客戶端的請求不知道訪問哪個節(jié)點(diǎn)怎么辦?緩存的數(shù)據(jù)又如何放到這些節(jié)點(diǎn)上?

緩存代理服務(wù)已經(jīng)幫我們解決這些問題了,例如:Twemproxy 不但可以幫助緩存路由,同時(shí)可以管理緩存節(jié)點(diǎn)。

這里有介紹三種緩存數(shù)據(jù)分片的算法,有了這些算法緩存代理就可以方便的找到分片的數(shù)據(jù)了。

①哈希算法

Hash 表是最常見的數(shù)據(jù)結(jié)構(gòu),實(shí)現(xiàn)方式是,對數(shù)據(jù)記錄的關(guān)鍵值進(jìn)行 Hash,然后再對需要分片的緩存節(jié)點(diǎn)個數(shù)進(jìn)行取模得到的余數(shù)進(jìn)行數(shù)據(jù)分配。

例如:有三條記錄數(shù)據(jù)分別是 R1,R2,R3。他們的 ID 分別是 01,02,03,假設(shè)對這三個記錄的 ID 作為關(guān)鍵值進(jìn)行 Hash 算法之后的結(jié)果依舊是 01,02,03。

我們想把這三條數(shù)據(jù)放到三個緩存節(jié)點(diǎn)中,可以把這個結(jié)果分別對 3 這個數(shù)字取模得到余數(shù),這個余數(shù)就是這三條記錄分別放置的緩存節(jié)點(diǎn)。

Hash 算法是某種程度上的平均放置,策略比較簡單,如果要增加緩存節(jié)點(diǎn),對已經(jīng)存在的數(shù)據(jù)會有較大的變動。

②一致性哈希算法

一致性 Hash 是將數(shù)據(jù)按照特征值映射到一個首尾相接的 Hash 環(huán)上,同時(shí)也將緩存節(jié)點(diǎn)映射到這個環(huán)上。

如果要緩存數(shù)據(jù),通過數(shù)據(jù)的關(guān)鍵值(Key)在環(huán)上找到自己存放的位置。這些數(shù)據(jù)按照自身的 ID 取 Hash 之后得到的值按照順序在環(huán)上排列。

如果這個時(shí)候要插入一條新的數(shù)據(jù)其 ID 是 115,那么就應(yīng)該插入到如下圖的位置。

同理如果要增加一個緩存節(jié)點(diǎn) N4 150,也可以放到如下圖的位置。

這種算法對于增加緩存數(shù)據(jù),和緩存節(jié)點(diǎn)的開銷相對比較小。

③Range Based 算法

這種方式是按照關(guān)鍵值(例如 ID)將數(shù)據(jù)劃分成不同的區(qū)間,每個緩存節(jié)點(diǎn)負(fù)責(zé)一個或者多個區(qū)間。跟一致性哈希有點(diǎn)像。

例如:存在三個緩存節(jié)點(diǎn)分別是 N1,N2,N3。他們用來存放數(shù)據(jù)的區(qū)間分別是,N1(0, 100], N2(100, 200], N3(300, 400]。

那么數(shù)據(jù)根據(jù)自己 ID 作為關(guān)鍵字做 Hash 以后的結(jié)果就會分別對應(yīng)放到這幾個區(qū)域里面了。

可用性

根據(jù)事物的兩面性,在分布式緩存帶來高性能的同時(shí),我們也需要重視它的可用性。那么哪些潛在的風(fēng)險(xiǎn)是我們需要防范的呢?

①緩存雪崩

當(dāng)緩存失效,緩存過期被清除,緩存更新的時(shí)候。請求是無法命中緩存的,這個時(shí)候請求會直接回源到數(shù)據(jù)庫。

如果上述情況頻繁發(fā)生或者同時(shí)發(fā)生的時(shí)候,就會造成大面積的請求直接到數(shù)據(jù)庫,造成數(shù)據(jù)庫訪問瓶頸。我們稱這種情況為緩存雪崩。

從如下兩方面來思考解決方案:

  • 緩存方面
  • 設(shè)計(jì)方面

緩存方面:

  • 避免緩存同時(shí)失效,不同的 key 設(shè)置不同的超時(shí)時(shí)間。
  • 增加互斥鎖,對緩存的更新操作進(jìn)行加鎖保護(hù),保證只有一個線程進(jìn)行緩存更新。緩存一旦失效可以通過緩存快照的方式迅速重建緩存。對緩存節(jié)點(diǎn)增加主備機(jī)制,當(dāng)主緩存失效以后切換到備用緩存繼續(xù)工作。

設(shè)計(jì)方面,這里給出了幾點(diǎn)建議供大家參考:

  • 熔斷機(jī)制:某個緩存節(jié)點(diǎn)不能工作的時(shí)候,需要通知緩存代理不要把請求路由到該節(jié)點(diǎn),減少用戶等待和請求時(shí)長。
  • 限流機(jī)制:在接入層和代理層可以做限流(之前的文章講到過),當(dāng)緩存服務(wù)無法支持高并發(fā)的時(shí)候,前端可以把無法響應(yīng)的請求放入到隊(duì)列或者丟棄。
  • 隔離機(jī)制:緩存無法提供服務(wù)或者正在預(yù)熱重建的時(shí)候,把該請求放入隊(duì)列中,這樣該請求因?yàn)楸桓綦x就不會被路由到其他的緩存節(jié)點(diǎn)。

如此就不會因?yàn)檫@個節(jié)點(diǎn)的問題影響到其他節(jié)點(diǎn)。當(dāng)緩存重建以后,再從隊(duì)列中取出請求依次處理。

②緩存穿透

緩存一般是 Key,Value 方式存在,一個 Key 對應(yīng)的 Value 不存在時(shí),請求會回源到數(shù)據(jù)庫。

假如對應(yīng)的 Value 一直不存在,則會頻繁的請求數(shù)據(jù)庫,對數(shù)據(jù)庫造成訪問壓力。如果有人利用這個漏洞攻擊,就麻煩了。

解決方法:如果一個 Key 對應(yīng)的 Value 查詢返回為空,我們?nèi)匀话堰@個空結(jié)果緩存起來,如果這個值沒有變化下次查詢就不會請求數(shù)據(jù)庫了。

將所有可能存在的數(shù)據(jù)哈希到一個足夠大的 Bitmap 中,那么不存在的數(shù)據(jù)會被這個 Bitmap 過濾器攔截掉,避免對數(shù)據(jù)庫的查詢壓力。

③緩存擊穿

在數(shù)據(jù)請求的時(shí)候,某一個緩存剛好失效或者正在寫入緩存,同時(shí)這個緩存數(shù)據(jù)可能會在這個時(shí)間點(diǎn)被超高并發(fā)請求,成為“熱點(diǎn)”數(shù)據(jù)。

這就是緩存擊穿問題,這個和緩存雪崩的區(qū)別在于,這里是針對某一個緩存,前者是針對多個緩存。

解決方案:導(dǎo)致問題的原因是在同一時(shí)間讀/寫緩存,所以只有保證同一時(shí)間只有一個線程寫,寫完成以后,其他的請求再使用緩存就可以了。

比較常用的做法是使用 mutex(互斥鎖)。在緩存失效的時(shí)候,不是立即寫入緩存,而是先設(shè)置一個 mutex(互斥鎖)。當(dāng)緩存被寫入完成以后,再放開這個鎖讓請求進(jìn)行訪問。

總結(jié)

今天內(nèi)容有點(diǎn)多,讓我們一起來回顧一下。緩存設(shè)計(jì)有五大策略,從用戶請求開始依次是:

  • HTTP 緩存
  • CDN 緩存
  • 負(fù)載均衡緩存
  • 進(jìn)程內(nèi)緩存
  • 分布式緩存

前兩種緩存靜態(tài)數(shù)據(jù),后三種緩存動態(tài)數(shù)據(jù):

  • HTTP 緩存包括強(qiáng)制緩存和對比緩存。
  • CDN 緩存和 HTTP 緩存是好搭檔。
  • 負(fù)載均衡器緩存相對穩(wěn)定資源,需要服務(wù)協(xié)助工作。
  • 進(jìn)程內(nèi)緩存,效率高,但容量有限制,有兩個方案可以應(yīng)對緩存同步的問題。
  • 分布式緩存容量大,能力強(qiáng),牢記三個性能算法并且防范三個緩存風(fēng)險(xiǎn)。

網(wǎng)頁標(biāo)題:沒看這篇干貨,別說你會使用“緩存”
文章地址:http://jinyejixie.com/news/98754.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營銷、網(wǎng)站制作、網(wǎng)站內(nèi)鏈商城網(wǎng)站、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)
全南县| 东海县| 嘉黎县| 林州市| 通州市| 谷城县| 泸州市| 苍溪县| 建水县| 新晃| 五原县| 双牌县| 漯河市| 荣成市| 克山县| 克山县| 措勤县| 京山县| 新平| 毕节市| 常熟市| 海晏县| 岳阳县| 哈密市| 平顶山市| 鞍山市| 祥云县| 河北省| 桂阳县| 榕江县| 手游| 容城县| 广德县| 岑溪市| 开阳县| 中西区| 怀仁县| 高清| 迁安市| 兴隆县| 阜城县|