欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis緩存異常常用解決方案總結

 更新時間:2023年12月13日 11:53:14   作者:cxzm_java  
Redis緩存異常問題分別是緩存雪崩,緩存預熱,緩存穿透,緩存降級,緩存擊穿,本文主要介紹了Redis緩存異常常用解決方案總結,具有一定的參考價值,感興趣的可以了解一下

前言

Redis緩存異常問題分別是:1.緩存雪崩。2.緩存預熱。3.緩存穿透。4.緩存降級。5.緩存擊穿,以及對應Redis緩存異常問題解決方案。

1.緩存雪崩

1.1、什么是緩存雪崩

如果緩存集中在一段時間內失效,發(fā)生大量的緩存穿透,所有的查詢都落在數(shù)據(jù)庫上,造成了緩存雪崩由于原有緩存失效,新緩存未到期間所有原本應該訪問緩存的請求都去查詢數(shù)據(jù)庫了,而對數(shù)據(jù)庫CPU和內存造成巨大壓力,嚴重的會造成數(shù)據(jù)庫宕機。

舉例來說, 我們在準備一項搶購的促銷運營活動,活動期間將帶來大量的商品信息、庫存等相關信息的查詢。

為了避免商品數(shù)據(jù)庫的壓力,將商品數(shù)據(jù)放入緩存中存儲。不巧的是,搶購活動期間,大量的熱門商品緩存同時失

效過期了,導致很大的查詢流量落到了數(shù)據(jù)庫之上,對于數(shù)據(jù)庫來說造成很大的壓力。

1.2、解決方案

1、加鎖排隊

mutex互斥鎖解決,Redis的SETNX去set一個mutex key,當操作返回成功時,再進行加載數(shù)據(jù)庫的操作并回設緩存,否則,就重試整個get緩存的方法。

2、數(shù)據(jù)預熱

緩存預熱就是系統(tǒng)上線后,將相關的緩存數(shù)據(jù)直接加載到緩存系統(tǒng)。這樣就可以避免在用戶請求的時候,先查詢數(shù)據(jù)庫,然后再將數(shù)據(jù)緩存的問題。用戶直接查詢事先被預熱的緩存數(shù)據(jù)。可以通過緩存reload機制,預先去更新緩存,再即將發(fā)生大并發(fā)訪問前手動觸發(fā)加載緩存不同的key。

3、雙層緩存策略

C1為原始緩存,C2為拷貝緩存,C1失效時,可以訪問C2,C1緩存失效時間設置為短期,C2設置為長期。

4、定時更新緩存策略

實效性要求不高的緩存,容器啟動初始化加載,采用定時任務更新或移除緩存

5、設置不同的過期時間。

讓緩存失效的時間點盡量均勻。

2.緩存預熱

2.1、什么是緩存預熱

緩存預熱就是系統(tǒng)上線后,將相關的緩存數(shù)據(jù)直接加載到緩存系統(tǒng)。這樣就可以避免在用戶請求的時候,先查詢數(shù)據(jù)庫,然后再將數(shù)據(jù)緩存的問題。用戶直接查詢事先被預熱的緩存數(shù)據(jù)。

如圖所示:

如果不進行預熱, 那么 Redis 初識狀態(tài)數(shù)據(jù)為空,系統(tǒng)上線初期,對于高并發(fā)的流量,都會訪問到數(shù)據(jù)庫中, 對數(shù)據(jù)庫造成流量的壓力。

2.2、解決方案

  • 數(shù)據(jù)量不大的時候,工程啟動的時候進行加載緩存動作;

  • 數(shù)據(jù)量大的時候,設置一個定時任務腳本,進行緩存的刷新;

  • 數(shù)據(jù)量太大的時候,優(yōu)先保證熱點數(shù)據(jù)進行提前加載到緩存。

3.緩存穿透

3.1、什么是緩存穿透

緩存穿透是指用戶查詢數(shù)據(jù),在數(shù)據(jù)庫沒有,自然在緩存中也不會有。這樣就導致用戶查詢的時候,在緩存中找不到對應key的value,每次都要去數(shù)據(jù)庫再查詢一遍,然后返回空(相當于進行了兩次無用的查詢)。這樣請求就繞過緩存直接查數(shù)據(jù)庫。

3.2、解決方案

1、緩存空對象

簡單粗暴的方法,如果一個查詢返回的數(shù)據(jù)為空(不管是數(shù)據(jù)不存在,還是系統(tǒng)故障),我們仍然把這個空結果進行緩存,但它的過期時間會很短,最長不超過五分鐘。

2、布隆過濾器

優(yōu)勢:占用內存空間很小,位存儲;性能特別高,使用key的hash判斷key存不存在。

將所有可能存在的數(shù)據(jù)哈希到一個足夠大的bitmap中,一個一定不存在的數(shù)據(jù)會被這個bitmap攔截掉,從而避免了對底層存儲系統(tǒng)的查詢壓力。

4.緩存降級

降級的情況,就是緩存失效或者緩存服務掛掉的情況下,我們也不去訪問數(shù)據(jù)庫

我們直接訪問內存部分數(shù)據(jù)緩存或者直接返回默認數(shù)據(jù)。

舉例來說:

對于應用的首頁,一般是訪問量非常大的地方,首頁里面往往包含了部分推薦商品的展示信息。這些推薦商品都會放到緩存中進行存儲,同時我們?yōu)榱吮苊饩彺娴漠惓G闆r,對熱點商品數(shù)據(jù)也存儲到了內存中。同時內存中還保留了一些默認的商品信息。

降級一般是有損的操作,所以盡量減少降級對于業(yè)務的影響程度。

5.緩存擊穿

5.1、什么是緩存擊穿

緩存擊穿是指緩存中沒有但數(shù)據(jù)庫中有的數(shù)據(jù)(一般是緩存時間到期),這時由于并發(fā)用戶特別多,同時讀緩存沒

讀到數(shù)據(jù),又同時去數(shù)據(jù)庫去取數(shù)據(jù),引起數(shù)據(jù)庫壓力瞬間增大,造成過大壓力。

5.2、會帶來什么問題

會造成某一時刻數(shù)據(jù)庫請求量過大,壓力劇增

5.3、解決方案

5.3.1.使用互斥鎖(mutex key)

這種解決方案思路比較簡單,就是只讓一個線程構建緩存,其他線程等待構建緩存的線程執(zhí)行完,重新從緩存獲取數(shù)據(jù)就可以了。

如果是單機,可以用synchronized或者lock來處理;

如果是分布式環(huán)境可以用分布式鎖就可以了(分布式鎖,可以用memcache的add, redis的setnx, zookeeper的添加節(jié)點操作)。

5.3.2.永遠不過期

  • 從redis上看,確實沒有設置過期時間,這就保證了,不會出現(xiàn)熱點key過期問題,也就是“物理”不過期。

  • 從功能上看,如果不過期,那不就成靜態(tài)的了嗎?所以我們把過期時間存在key對應的value里,如果發(fā)現(xiàn)要過期了,通過一個后臺的異步線程進行緩存的構建,也就是“邏輯”過期。

5.3.3.緩存屏障

該方法類似于方法一

使用countDownLatch和atomicInteger.compareAndSet()方法,實現(xiàn)輕量級鎖。

 public class MyCache{
 ?
     private ConcurrentHashMap<String, String> map;
 ?
     private CountDownLatch countDownLatch;
 ?
     private AtomicInteger atomicInteger;
 ?
     public MyCache(ConcurrentHashMap<String, String> map, CountDownLatch countDownLatch,
                    AtomicInteger atomicInteger) {
         this.map = map;
         this.countDownLatch = countDownLatch;
         this.atomicInteger = atomicInteger;
     }
 ?
     public String get(String key){
 ?
         String value = map.get(key);
         if (value != null){
             System.out.println(Thread.currentThread().getName()+"\t 線程獲取value值 value="+value);
             return value;
         }
         // 如果沒獲取到值
         // 首先嘗試獲取token,然后去查詢db,初始化化緩存;
         // 如果沒有獲取到token,超時等待
         if (atomicInteger.compareAndSet(0,1)){
             System.out.println(Thread.currentThread().getName()+"\t 線程獲取token");
             return null;
         }
 ?
         // 其他線程超時等待
         try {
             System.out.println(Thread.currentThread().getName()+"\t 線程沒有獲取token,等待中。。。");
             countDownLatch.await();
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         // 初始化緩存成功,等待線程被喚醒
         // 等待線程等待超時,自動喚醒
         System.out.println(Thread.currentThread().getName()+"\t 線程被喚醒,獲取value ="+map.get("key"));
         return map.get(key);
     }
 ?
     public void put(String key, String value){
 ?
         try {
             Thread.sleep(2000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
 ?
         map.put(key, value);
 ?
         // 更新狀態(tài)
         atomicInteger.compareAndSet(1, 2);
 ?
         // 通知其他線程
         countDownLatch.countDown();
         System.out.println();
         System.out.println(Thread.currentThread().getName()+"\t 線程初始化緩存成功!value ="+map.get("key"));
     }
 ?
 }
 ?
 public  class MyThread implements Runnable{
 ?
     private MyCache myCache;
 ?
     public MyThread(MyCache myCache) {
         this.myCache = myCache;
     }
 ?
     @Override
     public void run() {
         String value = myCache.get("key");
         if (value == null){
             myCache.put("key","value");
         }
 ?
     }
 }
 ?
 public class CountDownLatchDemo {
     public static void main(String[] args) {
 ?
         MyCache myCache = new MyCache(new ConcurrentHashMap<>(), new CountDownLatch(1), new AtomicInteger(0));
 ?
         MyThread myThread = new MyThread(myCache);
 ?
         ExecutorService executorService = Executors.newFixedThreadPool(5);
         for (int i = 0; i < 5; i++) {
             executorService.execute(myThread);
         }
     }
 }

到此這篇關于Redis緩存異常常用解決方案總結的文章就介紹到這了,更多相關Redis緩存異常內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • redis+lua實現(xiàn)限流的項目實踐

    redis+lua實現(xiàn)限流的項目實踐

    redis有很多限流的算法(比如:令牌桶,計數(shù)器,時間窗口)等,在分布式里面進行限流的話,我們則可以使用redis+lua腳本進行限流,下面就來介紹一下redis+lua實現(xiàn)限流
    2023-10-10
  • Redis整合SpringBoot的RedisTemplate實現(xiàn)類(實例詳解)

    Redis整合SpringBoot的RedisTemplate實現(xiàn)類(實例詳解)

    這篇文章主要介紹了Redis整合SpringBoot的RedisTemplate實現(xiàn)類,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • Redis如何實現(xiàn)分布式鎖

    Redis如何實現(xiàn)分布式鎖

    這篇文章主要介紹了Redis如何實現(xiàn)分布式鎖問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • redis列表類型_動力節(jié)點Java學院整理

    redis列表類型_動力節(jié)點Java學院整理

    這篇文章主要為大家詳細介紹了redis列表類型的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Redis妙用之存儲用戶token問題

    Redis妙用之存儲用戶token問題

    這篇文章主要介紹了Redis妙用之存儲用戶token問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Redis 實現(xiàn)分布式鎖時需要考慮的問題解決方案

    Redis 實現(xiàn)分布式鎖時需要考慮的問題解決方案

    本文詳細探討了使用Redis實現(xiàn)分布式鎖時需要考慮的問題,包括鎖的競爭、鎖的釋放、超時管理、網(wǎng)絡分區(qū)等,并提供了相應的解決方案和代碼實例,有助于開發(fā)者正確且安全地使用Redis實現(xiàn)分布式鎖
    2024-09-09
  • K8s部署Redis主從集群教程

    K8s部署Redis主從集群教程

    本文介紹了在Kubernetes環(huán)境下搭建Redis集群的詳細步驟,包括環(huán)境準備、安裝NFS、創(chuàng)建PV卷、搭建Redis集群、集群初始化、主從切換測試以及開放外網(wǎng)端口等內容
    2025-01-01
  • Redis筆記點贊排行榜的實現(xiàn)示例

    Redis筆記點贊排行榜的實現(xiàn)示例

    探店筆記類似點評網(wǎng)站的評價,本文主要介紹了Redis筆記點贊排行榜的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01
  • Redis大key多key拆分實現(xiàn)方法解析

    Redis大key多key拆分實現(xiàn)方法解析

    這篇文章主要介紹了Redis大key多key拆分實現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • Redis命令處理過程源碼解析

    Redis命令處理過程源碼解析

    這篇文章主要介紹了Redis命令處理過程源碼解析,本文是基于社區(qū)版redis4.0.8,通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-02-02

最新評論