日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

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

作者:懶懶張187 ? 更新時間: 2022-05-19 編程語言

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 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,但是這個誤判概率是非常小的。

原文鏈接:https://blog.csdn.net/m0_48811221/article/details/123301041

欄目分類
最近更新