Redis處理高并發(fā)之布隆過(guò)濾器詳解
前言
隨著我們業(yè)務(wù)開(kāi)發(fā)越來(lái)越來(lái)大,并染請(qǐng)求就會(huì)越來(lái)越多,那么我們的項(xiàng)目的壓力就會(huì)越來(lái)越大,基本都會(huì)使用緩存,除本地緩存,還會(huì)用到redis緩存,但是你以為使用緩存就沒(méi)啥問(wèn)題了么,那肯定不是的,使用了緩存又會(huì)出現(xiàn)新的問(wèn)題,比如,緩存的key失效導(dǎo)致大量的請(qǐng)求到數(shù)據(jù)庫(kù),大量的讀請(qǐng)求瞬間到達(dá)了數(shù)據(jù)庫(kù),cpu的使用率爆增,導(dǎo)致數(shù)據(jù)庫(kù)都可能掛掉,這種情況下我們就要考慮使用redis的布隆過(guò)濾器了。
緩存穿透、擊穿、雪崩
首先我們從緩存會(huì)出現(xiàn)的幾種問(wèn)題,來(lái)進(jìn)行分析,在高并發(fā)的場(chǎng)景下如果出現(xiàn)這種情況,我們應(yīng)該如何解決。
正常情況下,我們的web應(yīng)用會(huì)先去請(qǐng)求緩存服務(wù),如果緩存命中,那么就去拿緩存里面的數(shù)據(jù),返回結(jié)果給應(yīng)用,
緩存穿透
緩存穿透與緩存雪崩和緩存擊穿還是不一樣的,雪崩和擊穿的情況下,數(shù)據(jù)庫(kù)的數(shù)據(jù)都是真正常的,可以去請(qǐng)求數(shù)據(jù)庫(kù)獲取數(shù)據(jù),只是緩存層出現(xiàn)問(wèn)題,等待緩存恢復(fù)了,就會(huì)減輕數(shù)據(jù)庫(kù)的壓力。 而緩存透不一樣的就是,緩存和數(shù)據(jù)庫(kù)都沒(méi)有要請(qǐng)求的數(shù)據(jù),大量的請(qǐng)求來(lái)了,數(shù)據(jù)庫(kù)的壓力很大。
出現(xiàn)情況
- 數(shù)據(jù)庫(kù)數(shù)據(jù)被大量清除,導(dǎo)致訪問(wèn)不到
- 黑客惡意攻擊
常見(jiàn)的解決方案
- redis緩存空值,請(qǐng)求不到的時(shí)候返回給應(yīng)用空值。
- 使用布隆過(guò)濾器,把數(shù)據(jù)庫(kù)的一部分?jǐn)?shù)據(jù)hash到布隆過(guò)濾器里,在請(qǐng)求數(shù)據(jù)庫(kù)之前先去布隆過(guò)濾器里篩選到一部分請(qǐng)求,判斷數(shù)據(jù)是否存在,避免直接去訪問(wèn)數(shù)據(jù)庫(kù)。
緩存擊穿
出現(xiàn)情況
- 大量熱點(diǎn)數(shù)據(jù)庫(kù)過(guò)期,導(dǎo)致無(wú)法從緩存獲取到數(shù)據(jù),大量請(qǐng)求數(shù)據(jù)庫(kù)也無(wú)法返回書就
解決方案
- 加鎖,保證同一時(shí)間內(nèi),只允許有一個(gè)線程去更新緩存,等鎖釋放后在重新去請(qǐng)求緩存。
- 熱點(diǎn)數(shù)據(jù)不去設(shè)置過(guò)期時(shí)間,如果要設(shè)置過(guò)期時(shí)間,在過(guò)期的時(shí)候通知后臺(tái)去更新緩存的過(guò)期時(shí)間。
緩存雪崩
- 大量緩存在同一時(shí)間失效,導(dǎo)致大量請(qǐng)求進(jìn)入數(shù)據(jù)庫(kù)
- redis故障宕機(jī),導(dǎo)致緩存不能使用。
解決方案
- 同上加鎖
- 給緩存的過(guò)期時(shí)間加入隨機(jī)數(shù),保證緩存不會(huì)在同一時(shí)間同時(shí)失效。
- 副本key策略,就是對(duì)于一個(gè)key,在它的基礎(chǔ)上在設(shè)置一個(gè)key,它們的value都是一樣的,只不過(guò)一個(gè)設(shè)置過(guò)期時(shí)間、一個(gè)不設(shè)置過(guò)期時(shí)間,相當(dāng)于給key做了個(gè)副本,只不過(guò)在更新緩存的時(shí)候,副本key也是要更新的,避免出現(xiàn)數(shù)據(jù)不一致的現(xiàn)象。
布隆過(guò)濾器 Bloom filter
前面提到過(guò)布隆過(guò)濾器在請(qǐng)求比較高的時(shí)候,可以幫助我們抵擋一部分請(qǐng)求,從而減輕數(shù)據(jù)庫(kù)的壓力,布隆過(guò)濾器的數(shù)據(jù)結(jié)構(gòu)是一個(gè)二進(jìn)制的bit向量,或者說(shuō)是一個(gè)bit數(shù)組,它相對(duì)于list、set、map這些集合,它占用的空間更少,不足之處處就是返回的結(jié)果會(huì)有一定概率的誤差。
public static void main(String[] args) { int size = 1_000_000; BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size); for (int i = 0; i < size; i++) { bloomFilter.put(i); } for (int i = 0; i < size; i++) { if (!bloomFilter.mightContain(i)) { System.out.println("有漏網(wǎng)之魚"); } } List<Integer> list = new ArrayList<>(1000); for (int i = size + 10000; i < size + 20000; i++) { if (bloomFilter.mightContain(i)) { list.add(i); } } System.out.println("有誤差的數(shù)量:" + list.size()); }
確實(shí)有誤差的數(shù)量,但是誤差量不大,追求效率的同時(shí)只是犧牲一點(diǎn)誤差了。
總結(jié)
加鎖的排隊(duì)的場(chǎng)景確實(shí)能幫助我們很好的解決緩存穿透、擊穿的一些問(wèn)題,但是效率也是非常低了,因?yàn)槊總€(gè)請(qǐng)求都是排隊(duì)等待,如果可以接受輕微誤差的話,布隆過(guò)濾器的確是個(gè)很不錯(cuò)的選擇,Bloom filter的bitmap的存儲(chǔ)效率確實(shí)很高。
以上就是Redis處理高并發(fā)之布隆過(guò)濾器詳解的詳細(xì)內(nèi)容,更多關(guān)于Redis布隆過(guò)濾器處理高并發(fā)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Redis GEO實(shí)現(xiàn)搜索附近用戶的項(xiàng)目實(shí)踐
RedisGEO主要用于存儲(chǔ)地理位置信息,并對(duì)存儲(chǔ)的信息進(jìn)行操作,本文主要介紹了Redis GEO實(shí)現(xiàn)搜索附近用戶的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下2024-05-05window手動(dòng)操作清理redis緩存的技巧總結(jié)
在本篇文章中小編給大家分享了關(guān)于window環(huán)境手動(dòng)操作清理redis緩存的方法和技巧,有興趣的朋友們可以跟著學(xué)習(xí)下。2019-07-07Redis高級(jí)數(shù)據(jù)類型Hyperloglog、Bitmap的使用
很多小伙伴在面試中都會(huì)被問(wèn)道 Redis的常用數(shù)據(jù)結(jié)構(gòu)有哪些?可能很大一部分回答都是 string、hash、list、set、zset,但其實(shí)還有Hyperloglog和Bitmap,本文就來(lái)介紹一下2021-05-05Redis 的查詢很快的原因解析及Redis 如何保證查詢的高效
由于redis是內(nèi)存數(shù)據(jù)庫(kù),歸功于它的數(shù)據(jù)結(jié)構(gòu)所以查詢效率非常高,今天通過(guò)本文給大家介紹下Redis 的查詢很快的原因解析及Redis 如何保證查詢的高效,感興趣的朋友一起看看吧2022-03-03