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ù)查詢,將查詢出的結(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è)線程去查詢這個(gè)熱點(diǎn)key,其它線程保持阻塞狀態(tài)(可以讓它們sleep幾秒)。當(dāng)這個(gè)進(jìn)入數(shù)據(jù)庫(kù)的線程查詢出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)求去查詢多個(gè)key時(shí),此時(shí)redis緩存中失效或者查不到,然后海量的請(qǐng)求都去都去db查詢,從而導(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繁查詢才會(huì)對(duì)系統(tǒng)造成很大的問(wèn)題: key緩存并且數(shù)據(jù)庫(kù)不存在,所以每次查詢都會(huì)查詢數(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ā)起海量查詢請(qǐng)求,導(dǎo)致這些請(qǐng)求在redis中查不到相應(yīng)的數(shù)據(jù),只能去數(shù)據(jù)庫(kù)中查詢,從而導(dǎo)致數(shù)據(jù)庫(kù)崩潰。)

解決方案:
1.當(dāng)類似的請(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)文章
Spring boot+redis實(shí)現(xiàn)消息發(fā)布與訂閱的代碼
這篇文章主要介紹了Spring boot+redis實(shí)現(xiàn)消息發(fā)布與訂閱,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值需要的朋友可以參考下2020-04-04
redis啟動(dòng)redis-server.exe閃退問(wèn)題解決
本文主要介紹了redis啟動(dòng)redis-server.exe閃退問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-02-02
ubuntu 16.04安裝redis的兩種方式教程詳解(apt和編譯方式)
這篇文章主要介紹了ubuntu 16.04安裝redis的兩種方式教程詳解(apt和編譯方式),需要的朋友可以參考下2018-03-03
了解redis中RDB結(jié)構(gòu)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了redis中RDB結(jié)構(gòu),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
Redis中管道操作pipeline的實(shí)現(xiàn)
RedisPipeline是一種優(yōu)化客戶端與服務(wù)器通信的技術(shù),通過(guò)批量發(fā)送和接收命令減少網(wǎng)絡(luò)往返次數(shù),提高命令執(zhí)行效率,本文就來(lái)介紹一下Redis中管道操作pipeline的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2025-03-03
用Redis實(shí)現(xiàn)微博關(guān)注關(guān)系
在微博中,每一個(gè)用戶都會(huì)有一個(gè)關(guān)注列表,一個(gè)粉絲列表。用戶可以查看自己的關(guān)注,粉絲列表,也可以查看別人的關(guān)注,粉絲列表。并且,要展示列表里每個(gè)人與當(dāng)前查看者的關(guān)注狀態(tài)。2015-09-09

