




下載本文檔
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、架構(gòu)設(shè)計(jì)能力REDIS緩存穿透,緩存擊穿,緩存雪崩原 因+解決方案架構(gòu)設(shè)計(jì)能力文檔修訂摘要日期修訂號(hào)描述著者審閱者2020-03-29序列號(hào)1完成初稿張海濱架構(gòu)設(shè)計(jì)能力目錄REDIS緩存穿透,緩存擊穿,緩存雪崩原因+解決方案1 .概述2 .初認(rèn)識(shí)3 .緩存穿透解決方案 .56.8.4 .緩存擊穿解決方案 5 .緩存雪崩的解決方案 6 .小Z吉架構(gòu)設(shè)計(jì)能力1.概述在我們?nèi)粘5拈_發(fā)中,無(wú)不都是使用數(shù)據(jù)庫(kù)來(lái)進(jìn)行數(shù)據(jù)的存儲(chǔ),由于一般的系統(tǒng)任務(wù)中通常不會(huì)存在高并發(fā)的情況, 所以這樣看起來(lái)并沒有什么問(wèn)題,可是一旦涉及大數(shù)據(jù)量的需求,比如一些商品搶購(gòu)的情景, 或者是主頁(yè)訪問(wèn)量瞬間較大的時(shí)候,單一使用數(shù)據(jù)庫(kù)來(lái)
2、保存數(shù)據(jù)的系統(tǒng)會(huì)因?yàn)槊嫦虼疟P,磁盤讀 /寫速度比較慢的問(wèn)題而存在嚴(yán)重的性能弊端,一瞬間 成千上萬(wàn)的請(qǐng)求到來(lái),需要系統(tǒng)在極短的時(shí)間內(nèi)完成成千上萬(wàn)次的讀/寫操作,這個(gè)時(shí)候往往不是數(shù)據(jù)庫(kù)能夠承受的, 極其容易造成數(shù)據(jù)庫(kù)系統(tǒng)癱瘓,最終導(dǎo)致服務(wù)宕機(jī)的嚴(yán)重生產(chǎn)問(wèn)題。為了克服上述的問(wèn)題,項(xiàng)目通常會(huì)引入NoSQL技術(shù),這是一種基于內(nèi)存的數(shù)據(jù)庫(kù),并且提供一定的持久化功能。redis技術(shù)就是NoSQL技術(shù)中的一種,但是引入redis又有可能出現(xiàn)緩存穿透,緩存擊穿,緩存雪崩等問(wèn)題。本文就對(duì)這三種問(wèn)題進(jìn)行較深入剖析。2.初認(rèn)識(shí)? 緩存穿透:key對(duì)應(yīng)的數(shù)據(jù)在數(shù)據(jù)源并不存在,每次針對(duì)此key的請(qǐng)求從緩存獲取不至L請(qǐng)求都
3、會(huì)到數(shù)據(jù)源,從而可能壓垮數(shù)據(jù)源。比如用一個(gè)不存在的用戶id獲取用戶信息,不論緩存還是數(shù)據(jù)庫(kù)都沒有,若黑客利用此漏洞進(jìn)行攻擊可能壓垮數(shù)據(jù)庫(kù)。? 緩存擊穿:key對(duì)應(yīng)的數(shù)據(jù)存在,但在 redis中過(guò)期,此時(shí)若有大量并發(fā)請(qǐng)求過(guò)來(lái), 這些請(qǐng)求發(fā)現(xiàn)緩存過(guò)期一般都會(huì)從后端 DB加載數(shù)據(jù)并回設(shè)到緩存,這個(gè)時(shí)候大并 發(fā)的請(qǐng)求可能會(huì)瞬間把后端 DB壓垮。? 緩存雪崩:當(dāng)緩存服務(wù)器重啟或者大量緩存集中在某一個(gè)時(shí)間段失效,這樣在失效 的時(shí)候,也會(huì)給后端系統(tǒng)(比如DB)帶來(lái)很大壓力。3,緩存穿透解決方案一個(gè)一定不存在緩存及查詢不到的數(shù)據(jù),由于緩存是不命中時(shí)被動(dòng)寫的,并且出于容錯(cuò)考慮,如果從存儲(chǔ)層查不 到數(shù)據(jù)則不寫入緩
4、存,這將導(dǎo)致這個(gè)不存在的數(shù)據(jù)每次請(qǐng)求都要到存儲(chǔ)層去查詢,失去了緩存的意義。有很多種方法可以有效地解決緩存穿透問(wèn)題,最常見的則是采用布隆過(guò)濾器,將所有可能存在的數(shù)據(jù)哈希到一個(gè) 足夠大的bitmap中,一個(gè)一定不存在的數(shù)據(jù)會(huì)被這個(gè) bitmap攔截掉,從而避免了對(duì)底層存儲(chǔ)系統(tǒng)的查詢壓力。另外也有一個(gè)更為簡(jiǎn)單粗暴的方法(我們采用的就是這種),如果一個(gè)查詢返回的數(shù)據(jù)為空(不管是數(shù)據(jù)不存在,還是系 統(tǒng)故障),我們?nèi)匀话堰@個(gè)空結(jié)果進(jìn)行緩存,但它的過(guò)期時(shí)間會(huì)很短,最長(zhǎng)不超過(guò)五分鐘。粗暴方式偽代碼:/ 偽代碼 public object GetProductListNew() int cacheTime =
5、30;String cacheKey = "product_list”;String cacheValue = CacheHelper.Get(cacheKey);架構(gòu)設(shè)計(jì)能力if (cacheValue != null) return cacheValue;)cacheValue = CacheHelper.Get(cacheKey);if (cacheValue != null) return cacheValue; else /數(shù)據(jù)庫(kù)查詢不到,為空cacheValue = GetProductListFromDB();if (cacheValue = null) 如果發(fā)現(xiàn)為空,
6、設(shè)置個(gè)默認(rèn)值,也緩存起來(lái) cacheValue = string.Empty;CacheHelper.Add(cacheKey, cacheValue, cacheTime); return cacheValue;4 .緩存擊穿解決方案key可能會(huì)在某些時(shí)間點(diǎn)被超高并發(fā)地訪問(wèn),是一種非常熱點(diǎn)”的數(shù)據(jù)。這個(gè)時(shí)候,需要考慮一個(gè)問(wèn)題:緩存被 擊穿”的問(wèn)題。使用互斥鎖(mutex key)業(yè)界比較常用的做法,是使用 mutex。簡(jiǎn)單地來(lái)說(shuō),就是在緩存失效的時(shí)候(判斷拿出來(lái)的值為空),不是立即去 load db ,而是先使用緩存工具的某些帶成功操作返回值的操作(比如 Redis的SETNX或者M(jìn)emca
7、che的ADD)去 set一個(gè)mutex key ,當(dāng)操作返回成功時(shí),再進(jìn)行l(wèi)oad db的操作并回設(shè)緩存;否則,就重試整個(gè) get緩存的方法。SETNX,是SET if Not eXists J的縮寫,也就是只有不存在的時(shí)候才設(shè)置,可以利用它來(lái)實(shí)現(xiàn)鎖的效果。public String get(key) String value = redis.get(key);if (value = null) /代表緩存值過(guò)期/設(shè)置3min的超時(shí),防止del操作失敗的時(shí)候,下次緩存過(guò)期一直不能load dbif (redis.setnx(key_mutex, 1, 3 * 60) = 1) / 代表設(shè)置成
8、功value = db.get(key);redis.set(key, value, expire_secs);redis.del(key_mutex); else 這個(gè)時(shí)候代表同時(shí)候的其他線程已經(jīng)load db并回設(shè)到緩存了,這時(shí)候重試獲取緩存值即可sleep(50);get(key); /重試架構(gòu)設(shè)計(jì)能力 else return value;memcache 代碼:if (memcache.get(key) = null) / 3 min timeout to avoid mutex holder crashif (memcache.add(key_mutex, 3 * 60 * 1000
9、) = true) value = db.get(key);memcache.set(key, value);memcache.delete(key_mutex); else sleep(50);retry();其它方案:待各位補(bǔ)充。5 .緩存雪崩的解決方案與緩存擊穿的區(qū)別在于這里針對(duì)很多key緩存,前者則是某一個(gè)key。緩存正常從Redis中獲取,示意圖如下:架構(gòu)設(shè)計(jì)能力緩存失效瞬間示意圖如下:緩存失效時(shí)的雪崩效應(yīng)對(duì)底層系統(tǒng)的沖擊非??膳?!大多數(shù)系統(tǒng)設(shè)計(jì)者考慮用加鎖或者隊(duì)列的方式保證來(lái)保證不 會(huì)有大量的線程對(duì)數(shù)據(jù)庫(kù)一次性進(jìn)行讀寫,從而避免失效時(shí)大量的并發(fā)請(qǐng)求落到底層存儲(chǔ)系統(tǒng)上。還有一個(gè)簡(jiǎn)單方
10、案 就時(shí)講緩存失效時(shí)間分散開,比如我們可以在原有的失效時(shí)間基礎(chǔ)上增加一個(gè)隨機(jī)值,比如1-5分鐘隨機(jī),這樣每一個(gè)緩存的過(guò)期時(shí)間的重復(fù)率就會(huì)降低,就很難引發(fā)集體失效的事件。加鎖排隊(duì),偽代碼如下:/ 偽代碼 public object GetProductListNew() int cacheTime = 30;String cacheKey = "product_list"String lockKey = cacheKey;String cacheValue = CacheHelper.get(cacheKey);if (cacheValue != null) return c
11、acheValue; else synchronized(lockKey) cacheValue = CacheHelper.get(cacheKey);if (cacheValue != null) return cacheValue; else /這里一般是sql查詢數(shù)據(jù)cacheValue = GetProductListFromDB();CacheHelper.Add(cacheKey, cacheValue, cacheTime);return cacheValue;架構(gòu)設(shè)計(jì)能力)加鎖排隊(duì)只是為了減輕數(shù)據(jù)庫(kù)的壓力,并沒有提高系統(tǒng)吞吐量。假設(shè)在高并發(fā)下,緩存重建期間key是鎖著的,這是
12、過(guò)來(lái)1000個(gè)請(qǐng)求999個(gè)都在阻塞的。同樣會(huì)導(dǎo)致用戶等待超時(shí),這是個(gè)治標(biāo)不治本的方法!注意:加鎖排隊(duì)的解決方式分布式環(huán)境的并發(fā)問(wèn)題,有可能還要解決分布式鎖的問(wèn)題;線程還會(huì)被阻塞,用戶體驗(yàn)很差!因此,在真正的高并發(fā)場(chǎng)景下很少使用!隨機(jī)值偽代碼:/ 偽代碼 public object GetProductListNew() int cacheTime = 30;String cacheKey = "product_list"/緩存標(biāo)記String cacheSign = cacheKey + "_sign"String sign = CacheHelper.
13、Get(cacheSign);/獲取緩存值String cacheValue = CacheHelper.Get(cacheKey);if (sign != null) return cacheValue; /未過(guò)期,直接返回 else CacheHelper.Add(cacheSign, "1", cacheTime);ThreadPool.QueueUserWorkItem(arg) -> /這里一般是sql查詢數(shù)據(jù)cacheValue = GetProductListFromDB();/日期設(shè)緩存時(shí)間的2倍,用于臟讀CacheHelper.Add(cacheKey, cacheValue, cacheTime * 2););return cacheValue;解釋說(shuō)明:? 緩存標(biāo)記:記錄緩存數(shù)據(jù)是否過(guò)期,如果過(guò)期會(huì)觸發(fā)通知另外的線程在后臺(tái)去更新實(shí)際key的緩存;? 緩存數(shù)據(jù):它的過(guò)期時(shí)間比緩存標(biāo)記的時(shí)間延長(zhǎng)1倍,例:標(biāo)記緩存時(shí)間30分鐘,數(shù)據(jù)緩存設(shè)置為60分鐘。這樣,當(dāng)緩存標(biāo)記key過(guò)期后,實(shí)際緩存還能把舊數(shù)據(jù)返回給調(diào)用端,直到另外的線程在后臺(tái)更新完成后,才會(huì)返 回新緩存
溫馨提示
- 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ù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 高考數(shù)學(xué)(人教A版文科)一輪復(fù)習(xí)考點(diǎn)規(guī)范練53
- 論技工院校計(jì)算機(jī)應(yīng)用課程的開放式教學(xué)
- 精神病強(qiáng)制醫(yī)療程序的救濟(jì)機(jī)制研究
- 小兒不同病理分型闌尾炎臨床特點(diǎn)研究
- 養(yǎng)陰益氣活血法減少糖尿病GK大鼠血糖波動(dòng)的機(jī)制探索
- DB11T-鋼筋套筒灌漿連接技術(shù)規(guī)程編制說(shuō)明
- 買賣房合同范例
- 三方租賃合同范例
- 鄉(xiāng)村涵洞施工合同范例
- 紹興管道安裝施工方案
- 條件概率與全概率公式高二下學(xué)期數(shù)學(xué)人教A版(2019)選擇性必修第三冊(cè)
- (正式版)JBT 10437-2024 電線電纜用可交聯(lián)聚乙烯絕緣料
- 法律知識(shí)圖譜構(gòu)建及應(yīng)用
- 八卦的基本介紹及其科學(xué)內(nèi)涵
- 內(nèi)科護(hù)理學(xué)慢性腎衰竭
- (建筑制圖)課程綜合自測(cè)題3(試卷和答案)
- 公司商業(yè)模式策劃案關(guān)鍵合作伙伴
- 虛擬現(xiàn)實(shí)技術(shù)在工業(yè)設(shè)計(jì)中的應(yīng)用課件
- 學(xué)術(shù)誠(chéng)信與學(xué)術(shù)規(guī)范
- 急診科的急性心肌炎處理
- 郵政分銷述職報(bào)告
評(píng)論
0/150
提交評(píng)論