首頁 > 軟體

redis擊穿 雪崩 穿透超詳細解決方案梳理

2022-03-16 19:01:04

Redis擊穿

redis快取擊穿是指某一個非常熱點的key(即在使用者端搜尋的比較多的關鍵字)突然失效了,這時從使用者端傳送的大量的請求在redis裡找不到這個key,就會去資料裡找,最終導致資料庫壓力過大崩掉。

解決方案:

1.將value的時效設定成永不過期 這種方式非常簡單粗暴但是安全可靠。但是非常佔用空間對記憶體消耗也是極大。個人並不建議使用該方法,應該根據具體業務邏輯來操作。

2.使用Timetask做一個定時任務 使用Timetask做定時,每隔一段時間對一些熱點key進行資料庫查詢,將查詢出的結果更新至redis中。前條件是不會給資料庫過大的壓力。

3.通過synchronized+雙重檢查機制 當發生reids穿透的時候,這時海量請求傳送到資料庫。這時我們的解決辦法是隻讓只讓一個執行緒去查詢這個熱點key,其它執行緒保持阻塞狀態(可以讓它們sleep幾秒)。當這個進入資料庫的執行緒查詢出key對應的value時,我們再將其同步至redis的快取當中,其它執行緒睡醒以後再重新去redis裡邊請求資料。

例子:

 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){
         		//進入synchronized以後再去redis裡查一遍,防止上一個搶到鎖的執行緒已經更新過了。
                value=redis.get(key,String.class);
                 if(value==null||StringUtils.isBlank(value){
                     value=db.query(key);
                      redis.set(key,value,1000); 
          }
       }
     }    
      return value;
   }

缺點:存在死鎖和執行緒阻塞的風險。

Redis雪崩

指的是當海量的請求去查詢多個key時,此時redis快取中失效或者查不到,然後海量的請求都去都去db查詢,從而導致db壓力突然飆升崩潰。

出現原因:

1.key同時失效

2.redis本身崩潰了

解決方案:

1.設定快取時,隨機初始化其失效時間

如果是redis的key同時失效,可採取該辦法,具體失效時間根據業務情況決定…

2.將不同的熱點key放置到不同的節點上去

因redis一般都是叢集部署,將不同的熱點key平均的放置到不同節點,也可以有效避免雪崩。

3.將value的時效設定成永不過期

4.使用Timetask做一個定時任務,在失效之前重新刷redis快取

Redis穿透

因為不良使用者惡意頻繁查詢才會對系統造成很大的問題: key快取並且資料庫不存在,所以每次查詢都會查詢資料庫從而導致資料庫崩潰。

(例如:我們在資料庫存放的資料其主鍵都是自增且沒有負數的,某些駭客就利用這一點,不斷用主鍵id為-1的引數來發起海量查詢請求,導致這些請求在redis中查不到相應的資料,只能去資料庫中查詢,從而導致資料庫崩潰。)

解決方案:

1.當類似的請求發過來,無論查出什麼結果都放入redis快取

這樣解決當他下次再用同一個引數發起請求時,會直接進到redis裡邊去,不會再進入資料庫。

2.拉黑其ip

3.對請求的引數進行合法性校驗,在判斷其不合法的前提下直接return掉

4.使用布隆過濾器

可以將布隆過濾器理解成一個白名單或者黑名單,它的作用就是判斷一個元素是否存在於這個過濾器。

白名單: 過濾器裡有資料庫中所有的合法的引數key,請求經過布隆過濾器,布隆過濾器判斷這個請求的key在不在過濾器,在就放行讓請求進入redis,不在就直接return空資料。

public static void main(String[] args){
	Config config = new Config();
	config.useSingleServer().setAddress("redis://127.0.0.1:6379");
	config.useSingleServer().setPassword("1234");
	//構造Redsson
	RedissonClient redisson = Redisson.create(config);
	RBloomFilter<String> bloomFilter = redisson.getBloomFilter("phoneList");//給我們自己定義的布隆過濾器取名叫phoneList,名字隨便取
	//初始化布隆過濾器設定預計元素為100000000L, 誤差率為3%
	bloomFilter.tryInit(100000000L,0.03);
	//將10086插入到布隆過濾器中
	bloomFilter.add("10086");
	//判斷下面號碼是否存在布隆過濾器中
	//false
	System.out.println("123456");
	//true
	System.out.println("10086");
}

缺點:

布隆過濾器可能會造成誤判,從而穿透redis進入DB,但是這個誤判概率是非常小的。

以上就是redis擊穿 雪崩 穿透超詳細解決方案梳理的詳細內容,更多關於redis 擊穿 雪崩 穿透的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com