redis擊穿 雪崩 穿透超詳細(xì)解決方案梳理
Redis擊穿
redis緩存擊穿是指某一個(gè)非常熱點(diǎn)的key(即在客戶端搜索的比較多的關(guān)鍵字)突然失效了,這時(shí)從客戶端發(fā)送的大量的請(qǐng)求在redis里找不到這個(gè)key,就會(huì)去數(shù)據(jù)里找,最終導(dǎo)致數(shù)據(jù)庫(kù)壓力過(guò)大崩掉。
解決方案:
1.將value的時(shí)效設(shè)置成永不過(guò)期 這種方式非常簡(jiǎn)單粗暴但是安全可靠。但是非常占用空間對(duì)內(nèi)存消耗也是極大。個(gè)人并不建議使用該方法,應(yīng)該根據(jù)具體業(yè)務(wù)邏輯來(lái)操作。
2.使用Timetask做一個(gè)定時(shí)任務(wù) 使用Timetask做定時(shí),每隔一段時(shí)間對(duì)一些熱點(diǎn)key進(jìn)行數(shù)據(jù)庫(kù)查詢(xún),將查詢(xún)出的結(jié)果更新至redis中。前條件是不會(huì)給數(shù)據(jù)庫(kù)過(guò)大的壓力。
3.通過(guò)synchronized+雙重檢查機(jī)制 當(dāng)發(fā)生reids穿透的時(shí)候,這時(shí)海量請(qǐng)求發(fā)送到數(shù)據(jù)庫(kù)。這時(shí)我們的解決辦法是只讓只讓一個(gè)線程去查詢(xún)這個(gè)熱點(diǎn)key,其它線程保持阻塞狀態(tài)(可以讓它們sleep幾秒)。當(dāng)這個(gè)進(jìn)入數(shù)據(jù)庫(kù)的線程查詢(xún)出key對(duì)應(yīng)的value時(shí),我們?cè)賹⑵渫街羠edis的緩存當(dāng)中,其它線程睡醒以后再重新去redis里邊請(qǐng)求數(shù)據(jù)。
例子:
private static volaite Object obj = new Object(); public String getValue(String key){ String value=redis.get(key,String.class); if(value==null||StringUtils.isBlank(value){ synchronized(obj){ //進(jìn)入synchronized以后再去redis里查一遍,防止上一個(gè)搶到鎖的線程已經(jīng)更新過(guò)了。 value=redis.get(key,String.class); if(value==null||StringUtils.isBlank(value){ value=db.query(key); redis.set(key,value,1000); } } } return value; }
缺點(diǎn):存在死鎖和線程阻塞的風(fēng)險(xiǎn)。
Redis雪崩
指的是當(dāng)海量的請(qǐng)求去查詢(xún)多個(gè)key時(shí),此時(shí)redis緩存中失效或者查不到,然后海量的請(qǐng)求都去都去db查詢(xún),從而導(dǎo)致db壓力突然飆升崩潰。
出現(xiàn)原因:
1.key同時(shí)失效
2.redis本身崩潰了
解決方案:
1.設(shè)置緩存時(shí),隨機(jī)初始化其失效時(shí)間
如果是redis的key同時(shí)失效,可采取該辦法,具體失效時(shí)間根據(jù)業(yè)務(wù)情況決定…
2.將不同的熱點(diǎn)key放置到不同的節(jié)點(diǎn)上去
因redis一般都是集群部署,將不同的熱點(diǎn)key平均的放置到不同節(jié)點(diǎn),也可以有效避免雪崩。
3.將value的時(shí)效設(shè)置成永不過(guò)期
4.使用Timetask做一個(gè)定時(shí)任務(wù),在失效之前重新刷redis緩存
Redis穿透
因?yàn)椴涣加脩魫阂忸l繁查詢(xún)才會(huì)對(duì)系統(tǒng)造成很大的問(wèn)題: key緩存并且數(shù)據(jù)庫(kù)不存在,所以每次查詢(xún)都會(huì)查詢(xún)數(shù)據(jù)庫(kù)從而導(dǎo)致數(shù)據(jù)庫(kù)崩潰。
(例如:我們?cè)跀?shù)據(jù)庫(kù)存放的數(shù)據(jù)其主鍵都是自增且沒(méi)有負(fù)數(shù)的,某些黑客就利用這一點(diǎn),不斷用主鍵id為-1的參數(shù)來(lái)發(fā)起海量查詢(xún)請(qǐng)求,導(dǎo)致這些請(qǐng)求在redis中查不到相應(yīng)的數(shù)據(jù),只能去數(shù)據(jù)庫(kù)中查詢(xún),從而導(dǎo)致數(shù)據(jù)庫(kù)崩潰。)
解決方案:
1.當(dāng)類(lèi)似的請(qǐng)求發(fā)過(guò)來(lái),無(wú)論查出什么結(jié)果都放入redis緩存
這樣解決當(dāng)他下次再用同一個(gè)參數(shù)發(fā)起請(qǐng)求時(shí),會(huì)直接進(jìn)到redis里邊去,不會(huì)再進(jìn)入數(shù)據(jù)庫(kù)。
2.拉黑其ip
3.對(duì)請(qǐng)求的參數(shù)進(jìn)行合法性校驗(yàn),在判斷其不合法的前提下直接return掉
4.使用布隆過(guò)濾器
可以將布隆過(guò)濾器理解成一個(gè)白名單或者黑名單,它的作用就是判斷一個(gè)元素是否存在于這個(gè)過(guò)濾器。
白名單: 過(guò)濾器里有數(shù)據(jù)庫(kù)中所有的合法的參數(shù)key,請(qǐng)求經(jīng)過(guò)布隆過(guò)濾器,布隆過(guò)濾器判斷這個(gè)請(qǐng)求的key在不在過(guò)濾器,在就放行讓請(qǐng)求進(jìn)入redis,不在就直接return空數(shù)據(jù)。
public static void main(String[] args){ Config config = new Config(); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); config.useSingleServer().setPassword("1234"); //構(gòu)造Redsson RedissonClient redisson = Redisson.create(config); RBloomFilter<String> bloomFilter = redisson.getBloomFilter("phoneList");//給我們自己定義的布隆過(guò)濾器取名叫phoneList,名字隨便取 //初始化布隆過(guò)濾器設(shè)置預(yù)計(jì)元素為100000000L, 誤差率為3% bloomFilter.tryInit(100000000L,0.03); //將10086插入到布隆過(guò)濾器中 bloomFilter.add("10086"); //判斷下面號(hào)碼是否存在布隆過(guò)濾器中 //false System.out.println("123456"); //true System.out.println("10086"); }
缺點(diǎn):
布隆過(guò)濾器可能會(huì)造成誤判,從而穿透redis進(jìn)入DB,但是這個(gè)誤判概率是非常小的。
以上就是redis擊穿 雪崩 穿透超詳細(xì)解決方案梳理的詳細(xì)內(nèi)容,更多關(guān)于redis 擊穿 雪崩 穿透的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Redis慢查詢(xún)?nèi)罩九c監(jiān)視器問(wèn)題
這篇文章主要介紹了Redis慢查詢(xún)?nèi)罩九c監(jiān)視器問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12基于Redis實(shí)現(xiàn)短信驗(yàn)證碼登錄項(xiàng)目示例(附源碼)
手機(jī)登錄驗(yàn)證在很多網(wǎng)頁(yè)上都得到使用,本文主要介紹了基于Redis實(shí)現(xiàn)短信驗(yàn)證碼登錄項(xiàng)目示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05Redis如何在項(xiàng)目中合理使用經(jīng)驗(yàn)分享
這篇文章主要給大家介紹了關(guān)于Redis如何在項(xiàng)目中合理使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04Redis分布式鎖方案設(shè)計(jì)之防止訂單重復(fù)提交或支付
這篇文章主要為大家介紹了Redis分布式鎖之防止訂單重復(fù)提交或支付方案設(shè)計(jì)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09Redis 中spark參數(shù)executor-cores引起的異常解決辦法
這篇文章主要介紹了Redis 中spark參數(shù)executor-cores引起的異常解決辦法的相關(guān)資料,需要的朋友可以參考下2017-03-03