日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Redis进阶-Redis缓存优化

發布時間:2025/3/21 数据库 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis进阶-Redis缓存优化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 緩存穿透
    • 定義
    • 原因
    • 緩存穿透問題解決方案
      • 緩存空對象
      • 布隆過濾器
  • 緩存同時失效
    • 緩存同時失效解決方案
  • 緩存雪崩
    • 緩存雪崩的解決方案
  • 緩存擊穿 ( 熱點緩存key重建優化 )
    • 緩存擊穿的解決方案 (熱點緩存key重建優化)


緩存穿透

定義

查詢一個根本不存在的數據, 緩存和DB都不會命中, 白嫖了緩存層和DB 。 通常出于容錯的考慮, 如果從存儲層查不到數據則不寫入緩存層。

緩存穿透將導致不存在的數據每次請求都要到存儲層去查詢, 失去了緩存保護后端存儲的意義。


原因

通常緩存穿透的原因如下:

  • 自身業務代碼或者數據出現問題。
  • 惡意攻擊、 爬蟲等造成大量空命中

緩存穿透問題解決方案

緩存空對象

這個也很好理解,需要注意的是對空對象,設置個過期時間,偽代碼如下

String get(String key) {// 從緩存中獲取數據String cacheValue = cache.get(key)// 緩存為空if (StringUtils.isBlank(cacheValue)) {// 從存儲中獲取String storageValue = storage.get(key);cache.set(key, storageValue);// 如果存儲數據為空, 需要設置一個過期時間(300秒)if (storageValue == null) {cache.expire(key, 60 * 5);}return storageValue;} else {// 緩存非空return cacheValue;} }

一般也夠用了,極限情況:惡意攻擊,幾千萬個不存在的id , 都打到了DB,你也都對這幾千萬個id 作為key, 存到了redis , 雖然他們的value都是空,而且你也設置了過期時間。

但是你想一下,你這幾千萬次的DB查詢,你也挺難過吧,并且你redis里緩存這幾千萬個key , 那寶貴的內存資源豈不是白白的浪費掉了。。。。。

所以你需要布隆過濾器。

看場景,取舍。


布隆過濾器

Redis進階-布隆過濾器


緩存同時失效

由于大批量緩存在同一時間失效可能導致大量請求同時穿透緩存直達數據庫,可能會造成數據庫瞬間壓力過大甚至掛掉。

緩存同時失效解決方案

對于這種情況我們在批量增加緩存時最好將這一批數據的緩存過期時間設置為一個時間段內的不同時間 。 比如 5到10分鐘之間的一個隨機時間。

偽代碼如下

String get(String key) {// 從緩存中獲取數據String cacheValue = cache.get(key);// 緩存為空if (StringUtils.isBlank(cacheValue)) {// 從存儲中獲取String storageValue = storage.get(key);cache.set(key, storageValue);//設置一個過期時間(300到600之間的一個隨機數)int expireTime = new Random().nextInt(300) + 300;if (storageValue == null) {cache.expire(key, expireTime);}return storageValue;} else {// 緩存非空return cacheValue;} }

緩存雪崩

緩存雪崩指的是緩存層支撐不住或宕掉后, 流量會像奔逃的野牛一樣, 打向后端存儲層.

由于緩存層承載著大量請求, 有效地保護了存儲層, 但是如果緩存層由于某些原因不能提供服務(比如超大并發過來,緩存層支撐不住,或者由于緩存設計不好,類似大量請求訪問bigkey,導致緩存能支撐的并發急劇下降), 于是大量請求都會達到存儲層, 存儲層的調用量會暴增, 造成存儲層也會級聯宕機的情況。


緩存雪崩的解決方案

預防和解決緩存雪崩問題, 可以從以下三個方面進行著手。

  • 1) 保證緩存層服務高可用性,比如使用Redis Sentinel或Redis Cluster。
  • 2) 依賴隔離組件為后端限流并降級。比如使用Hystrix限流降級組件。
  • 3) 提前演練。 在項目上線前, 演練緩存層宕掉后, 應用以及后端的負載情況以及可能出現的問題, 在此基礎上做一些預案設定。

緩存擊穿 ( 熱點緩存key重建優化 )

一般情況下,我們使用“緩存+過期時間”的策略既可以加速數據讀寫, 又保證數據的定期更新, 這種模式基本能夠滿足絕大部分需求。

但是有兩個問題如果同時出現, 可能就會對應用造成致命的危害:

  • 當前key是一個熱點key(例如一個熱門的娛樂新聞),并發量非常大
  • 重建緩存不能在短時間完成, 可能是一個復雜計算, 例如復雜的SQL、 多次IO、 多個依賴等。

在緩存失效的瞬間, 有大量線程來重建緩存, 造成后端負載加大, 甚至可能會讓應用崩潰 。

再通俗一點來說 :對于一些設置了過期時間的key,假設這些key可能會在某些時間點被超高并發地訪問,是一種非常“熱點”的數據。 如果正好在高并發的時候,這個key過期了。。。。 大量的請求都打到了DB層,造成DB的負載非常大,甚至宕機。

緩存擊穿的解決方案 (熱點緩存key重建優化)

要解決這個問題主要就是要避免大量線程同時重建緩存。

我們可以利用互斥鎖來解決,此方法只允許一個線程重建緩存, 其他線程等待重建緩存的線程執行完, 重新從緩存獲取數據即可。

偽代碼如下

String get(String key) {// 從Redis中獲取數據String value = redis.get(key);// 如果value為空, 則開始重構緩存if (value == null) {// 只允許一個線程重建緩存, 使用nx, 并設置過期時間exString mutexKey = "mutext:key:" + key;if (redis.set(mutexKey, "1", "ex 180", "nx")) {// 從數據源獲取數據value = db.get(key);// 回寫Redis, 并設置過期時間redis.setex(key, timeout, value);13 // 刪除key_mutexredis.delete(mutexKey);}// 其他線程休息50毫秒后重試else {Thread.sleep(50);get(key);}}return value; }

總結

以上是生活随笔為你收集整理的Redis进阶-Redis缓存优化的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。