偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

一篇學(xué)會(huì)緩存穿透、緩存擊穿、緩存雪崩

存儲(chǔ) 存儲(chǔ)架構(gòu)
當(dāng)查詢數(shù)據(jù)庫(kù)和緩存都無數(shù)據(jù)時(shí),因?yàn)閿?shù)據(jù)庫(kù)查詢無數(shù)據(jù),出于容錯(cuò)考慮,不會(huì)將結(jié)果保存到緩存中,因此每次請(qǐng)求都會(huì)去查詢數(shù)據(jù)庫(kù),這種情況就叫做緩存穿透。

大家好,我是樓仔!

今天寫的這個(gè)主題內(nèi)容,其實(shí)非?;A(chǔ),但是作為高并發(fā)非常重要的幾個(gè)場(chǎng)景,絕對(duì)繞不開,估計(jì)大家面試時(shí),也經(jīng)常會(huì)遇到。

這個(gè)主題的文章,網(wǎng)上非常多,本來想直接轉(zhuǎn)載一篇,但是感覺沒有合適的,要么文章不夠精煉,要么就是精簡(jiǎn)過頭,所以還是自己寫一篇吧。

內(nèi)容雖然基礎(chǔ),但我還是秉承以往的寫作風(fēng)格,參考眾多優(yōu)秀的博客后,打算寫一篇能通俗易懂,又不失全面的文章。

前言

我們先看一下正常情況的查詢過程:

  • 先查詢 Redis,如果查詢成功,直接返回,查詢不存在,去查詢 DB;
  • 如果 DB 查詢成功,數(shù)據(jù)回寫 Redis,查詢不存在,直接返回。

緩存穿透

定義:當(dāng)查詢數(shù)據(jù)庫(kù)和緩存都無數(shù)據(jù)時(shí),因?yàn)閿?shù)據(jù)庫(kù)查詢無數(shù)據(jù),出于容錯(cuò)考慮,不會(huì)將結(jié)果保存到緩存中,因此每次請(qǐng)求都會(huì)去查詢數(shù)據(jù)庫(kù),這種情況就叫做緩存穿透。

紅色的線條,就是緩存穿透的場(chǎng)景,當(dāng)查詢的 Key 在緩存和 DB 中都不存在時(shí),就會(huì)出現(xiàn)這種情況。

可以想象一下,比如有個(gè)接口需要查詢商品信息,如果有惡意用戶模擬不存在的商品 ID 發(fā)起請(qǐng)求,瞬間并發(fā)量很高,估計(jì)你的 DB 會(huì)直接掛掉。

可能大家第一反應(yīng)就是對(duì)入?yún)⑦M(jìn)行正則校驗(yàn),過濾掉無效請(qǐng)求,對(duì)!這個(gè)沒錯(cuò),那有沒有其它更好的方案呢?

緩存空值

當(dāng)我們從數(shù)據(jù)庫(kù)中查詢到空值時(shí),我們可以向緩存中回種一個(gè)空值,為了避免緩存被長(zhǎng)時(shí)間占用,需要給這個(gè)空值加一個(gè)比較短的過期時(shí)間,例如 3~5 分鐘。

不過這個(gè)方案有個(gè)問題,當(dāng)大量無效請(qǐng)求穿透過來時(shí),緩存內(nèi)就會(huì)有有大量的空值緩存,如果緩存空間被占滿了,還會(huì)因剔除掉一些已經(jīng)被緩存的用戶信息,反而會(huì)造成緩存命中率的下降,所以這個(gè)方案,需要評(píng)估緩存容量。

如果緩存空值不可取,這時(shí)你可以考慮使用布隆過濾器。

布隆過濾器

布隆過濾器是由一個(gè)可變長(zhǎng)度為 N 的二進(jìn)制數(shù)組與一組數(shù)量可變 M 的哈希函數(shù)構(gòu)成,說的簡(jiǎn)單粗暴一點(diǎn),就是一個(gè) Hash Map。

原理相當(dāng)簡(jiǎn)單:比如元素 key=#3,假如通過 Hash 算法得到一個(gè)為 9 的值,就存在這個(gè) Hash Map 的第 9 位元素中,通過標(biāo)記 1 標(biāo)識(shí)該位已經(jīng)有數(shù)據(jù),如下圖所示,0 是無數(shù)據(jù),1 是有數(shù)據(jù)。

所以通過該方法,會(huì)得到一個(gè)結(jié)論:在 Hash Map 中,標(biāo)記的數(shù)據(jù),不一定存在,但是沒有標(biāo)記的數(shù)據(jù),肯定不存在。

為什么“標(biāo)記的數(shù)據(jù),不一定存在”呢?因?yàn)?Hash 沖突!

比如 Hash Map 的長(zhǎng)度為 100,但是你有 101 個(gè)請(qǐng)求,假如你運(yùn)氣好到爆,這 100 個(gè)請(qǐng)求剛好均勻打在長(zhǎng)度為 100 的 Hash Map 中,此時(shí)你的 Hash Map 已經(jīng)全部標(biāo)記為 1。

當(dāng)?shù)?101 個(gè)請(qǐng)求過來時(shí),就 100% 出現(xiàn) Hash 沖突,雖然我沒有請(qǐng)求過,但是得到的標(biāo)記卻為 1,導(dǎo)致布隆過濾器沒有攔截。

如果需要減少誤判,可以增加 Hash Map 的長(zhǎng)度,并選擇卻分度更高的 Hash 函數(shù),比如多次對(duì) key 進(jìn)行 hash。

除了 Hash 沖突,布隆過濾器其實(shí)會(huì)帶來一個(gè)致命的問題:布隆過濾器更新失敗。

比如有一個(gè)商品 ID 第一次請(qǐng)求,當(dāng) DB 中存在時(shí),需要在 Hash Map 中標(biāo)記一下,但是由于網(wǎng)絡(luò)原因,導(dǎo)致標(biāo)記失敗,那么下次這個(gè)商品 ID 重新發(fā)起請(qǐng)求時(shí),請(qǐng)求會(huì)被布隆過濾器攔截,比如這個(gè)是雙11的爆款商品庫(kù)存,明明有 10W 件商品,你卻提示庫(kù)存不存在,領(lǐng)導(dǎo)可能會(huì)說“明天你可以不用來了”。

所以如果使用布隆過濾器,在對(duì) Hash Map 進(jìn)行數(shù)據(jù)更新時(shí),需要保證這個(gè)數(shù)據(jù)能 100% 更新成功,可以通過異步、重試的方式,所以這個(gè)方案有一定的實(shí)現(xiàn)成本和風(fēng)險(xiǎn)。

緩存擊穿

定義:某個(gè)熱點(diǎn)緩存在某一時(shí)刻恰好失效,然后此時(shí)剛好有大量的并發(fā)請(qǐng)求,此時(shí)這些請(qǐng)求將會(huì)給數(shù)據(jù)庫(kù)造成巨大的壓力,這種情況就叫做緩存擊穿。

這個(gè)其實(shí)和“緩存穿透”流程圖一樣,只是這個(gè)的出發(fā)點(diǎn)是“某個(gè)熱點(diǎn)緩存在某一時(shí)刻恰好失效”,比如某個(gè)非常熱門的爆款商品,緩存突然失效,流量直接全部打到 DB,造成某一時(shí)刻數(shù)據(jù)庫(kù)請(qǐng)求量過大,更強(qiáng)調(diào)瞬時(shí)性。

解決問題的方法主要有 2 種:

  • 分布式鎖:只有拿到鎖的第一個(gè)線程去請(qǐng)求數(shù)據(jù)庫(kù),然后插入緩存,當(dāng)然每次拿到鎖的時(shí)候都要去查詢一下緩存有沒有,這種在高并發(fā)場(chǎng)景下,個(gè)人不太建議用分布式鎖,會(huì)影響查詢效率;
  • 設(shè)置永不過期:對(duì)于某些熱點(diǎn)緩存,我們可以設(shè)置永不過期,這樣就能保證緩存的穩(wěn)定性,但需要注意在數(shù)據(jù)更改之后,要及時(shí)更新此熱點(diǎn)緩存,不然就會(huì)造成查詢結(jié)果的誤差,比如熱門商品,都先預(yù)熱到數(shù)據(jù)庫(kù),后續(xù)再下線掉。

網(wǎng)上還有“緩存續(xù)期”的方式,比如緩存 30 分鐘失效,可以搞個(gè)定時(shí)任務(wù),每 20 分鐘跑一次,感覺這種方式不倫不類,僅供大家參考。

緩存雪崩

定義:在短時(shí)間內(nèi)有大量緩存同時(shí)過期,導(dǎo)致大量的請(qǐng)求直接查詢數(shù)據(jù)庫(kù),從而對(duì)數(shù)據(jù)庫(kù)造成了巨大的壓力,嚴(yán)重情況下可能會(huì)導(dǎo)致數(shù)據(jù)庫(kù)宕機(jī)的情況叫做緩存雪崩。

如果說“緩存擊穿”是單兵反抗,那“緩存雪崩”就是集體起義了,那什么情況會(huì)出現(xiàn)緩存雪崩呢?

  • 短時(shí)間內(nèi)有大量緩存同時(shí)過期;
  • 緩存服務(wù)宕機(jī),導(dǎo)致某一時(shí)刻發(fā)生大規(guī)模的緩存失效。

那么有哪些解決方案呢?

  • 緩存添加隨機(jī)時(shí)間:可在設(shè)置緩存時(shí)添加隨機(jī)時(shí)間,比如 0~60s,這樣就可以極大的避免大量的緩存同時(shí)失效;
  • 分布式鎖:加一個(gè)分布式鎖,第一個(gè)請(qǐng)求將數(shù)據(jù)持久化到緩存后,其它的請(qǐng)求才能進(jìn)入;
  • 限流和降級(jí):通過限流和降級(jí)策略,減少請(qǐng)求的流量;
  • 集群部署:Redis 通過集群部署、主從策略,主節(jié)點(diǎn)宕機(jī)后,會(huì)切換到從節(jié)點(diǎn),保證服務(wù)的可用性。

緩存添加隨機(jī)時(shí)間示例:

// 緩存原本的失效時(shí)間
int exTime = 10 * 60;
// 隨機(jī)數(shù)生成類
Random random = new Random();
// 緩存設(shè)置
jedis.setex(cacheKey, exTime + random.nextInt(1000) , value);
責(zé)任編輯:武曉燕 來源: 樓仔
相關(guān)推薦

2019-10-12 14:19:05

Redis數(shù)據(jù)庫(kù)緩存

2023-03-10 13:33:00

緩存穿透緩存擊穿緩存雪崩

2019-11-05 14:24:31

緩存雪崩框架

2021-06-05 09:01:01

Redis緩存雪崩緩存穿透

2020-03-16 14:57:24

Redis面試雪崩

2022-03-08 00:07:51

緩存雪崩數(shù)據(jù)庫(kù)

2023-04-14 07:34:19

2022-11-18 14:34:28

2023-11-10 14:58:03

2025-06-30 01:55:00

2024-03-12 10:44:42

2020-10-13 07:44:40

緩存雪崩 穿透

2023-12-06 13:38:00

Redis緩存穿透緩存擊穿

2021-12-25 22:28:27

緩存穿透緩存擊穿緩存雪崩

2020-10-23 10:46:03

緩存雪崩擊穿

2022-07-11 07:36:36

緩存緩存雪崩緩存擊穿

2020-12-28 12:37:36

緩存擊穿穿透

2020-03-05 09:09:18

緩存原因方案

2024-04-18 11:43:28

緩存數(shù)據(jù)庫(kù)Redis

2024-04-07 00:00:02

Redis雪崩緩存
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)