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

歡迎訪問 生活随笔!

生活随笔

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

数据库

Redis缓存穿透、缓存击穿和缓存雪崩

發布時間:2024/9/30 数据库 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis缓存穿透、缓存击穿和缓存雪崩 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

    • 一、緩存穿透
      • 概念
      • 解決方案
        • 布隆過濾器
        • 緩存空對象
    • 二、緩存擊穿
      • 概念
      • 解決方案
        • 使用互斥鎖(mutex key)
        • 設置熱點數據永不過期
    • 三、緩存雪崩
      • 概念
      • 解決方案
        • redis高可用
        • 限流降級
        • 數據預熱

作為一個內存數據庫,redis也總是免不了有各種各樣的問題,這篇文章主要是針對其中三個問題進行講解:緩存穿透、緩存擊穿和緩存雪崩。并給出一些解決方案。這三個問題是基本問題也是面試常問問題。

一、緩存穿透

概念

緩存穿透的概念很簡單,用戶想要查詢一個數據,發現redis內存數據庫沒有,也就是緩存沒有命中,于是向持久層數據庫查詢。發現也沒有,于是本次查詢失敗。當用戶很多的時候,緩存都沒有命中,于是都去請求了持久層數據庫。這會給持久層數據庫造成很大的壓力,這時候就相當于出現了緩存穿透。

這里需要注意和緩存擊穿的區別,緩存擊穿,是指一個key非常熱點,在不停的扛著大并發,大并發集中對這一個點進行訪問,當這個key在失效的瞬間,持續的大并發就穿破緩存,直接請求數據庫,就像在一個屏障上鑿開了一個洞。

解決方案

布隆過濾器

布隆過濾器是一種數據結構,垃圾網站和正常網站加起來全世界據統計也有幾十億個。網警要過濾這些垃圾網站,總不能到數據庫里面一個一個去比較吧,這就可以使用布隆過濾器。假設我們存儲一億個垃圾網站地址。

可以先有一億個二進制比特,然后網警用八個不同的隨機數產生器(F1,F2, …,F8) 產生八個信息指紋(f1, f2, …, f8)。接下來用一個隨機數產生器 G 把這八個信息指紋映射到 1 到1億中的八個自然數 g1, g2, …,g8。最后把這八個位置的二進制全部設置為一。過程如下:

有一天網警查到了一個可疑的網站,想判斷一下是否是XX網站,首先將可疑網站通過哈希映射到1億個比特數組上的8個點。如果8個點的其中有一個點不為1,則可以判斷該元素一定不存在集合中。

那這個布隆過濾器是如何解決redis中的緩存穿透呢?很簡單首先也是對所有可能查詢的參數以hash形式存儲,當用戶想要查詢的時候,使用布隆過濾器發現不在集合中,就直接丟棄,不再對持久層查詢。

這個形式很簡單。

緩存空對象

當存儲層不命中后,即使返回的空對象也將其緩存起來,同時會設置一個過期時間,之后再訪問這個數據將會從緩存中獲取,保護了后端數據源;

但是這種方法會存在兩個問題:

  • 如果空值能夠被緩存起來,這就意味著緩存需要更多的空間存儲更多的鍵,因為這當中可能會有很多的空值的鍵;
  • 即使對空值設置了過期時間,還是會存在緩存層和存儲層的數據會有一段時間窗口的不一致,這對于需要保持一致性的業務會有影響。

二、緩存擊穿

概念

key可能會在某些時間點被超高并發地訪問,是一種非常“熱點”的數據。這個時候,需要考慮一個問題:緩存被“擊穿”的問題。

解決方案

使用互斥鎖(mutex key)

業界比較常用的做法,是使用mutex。簡單地來說,就是在緩存失效的時候(判斷拿出來的值為空),不是立即去load db,而是先使用緩存工具的某些帶成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一個mutex key,當操作返回成功時,再進行load db的操作并回設緩存;否則,就重試整個get緩存的方法。

SETNX,是「SET if Not eXists」的縮寫,也就是只有不存在的時候才設置,可以利用它來實現鎖的效果。

public String get(key) {String value = redis.get(key);if (value == null) { //代表緩存值過期//設置3min的超時,防止del操作失敗的時候,下次緩存過期一直不能load dbif (redis.setnx(key_mutex, 1, 3 * 60) == 1) { //代表設置成功value = db.get(key);redis.set(key, value, expire_secs);redis.del(key_mutex);} else { //這個時候代表同時候的其他線程已經load db并回設到緩存了,這時候重試獲取緩存值即可sleep(50);get(key); //重試}} else {return value; }}

memcache代碼:

if (memcache.get(key) == null) { // 3 min timeout to avoid mutex holder crash if (memcache.add(key_mutex, 3 * 60 * 1000) == true) { value = db.get(key); memcache.set(key, value); memcache.delete(key_mutex); } else { sleep(50); retry(); } }

設置熱點數據永不過期

從緩存層面來看, 沒有設置過期時間, 所以不會出現熱點 key 過期后產生的問題

三、緩存雪崩

概念

緩存雪崩是指,緩存層出現了錯誤,不能正常工作了。于是所有的請求都會達到存儲層,存儲層的調用量會暴增,造成存儲層也會掛掉的情況。

解決方案

redis高可用

這個思想的含義是,既然redis有可能掛掉,那我多增設幾臺redis,這樣一臺掛掉之后其他的還可以繼續工作,其實就是搭建的集群。

限流降級

這個解決方案的思想是,在緩存失效后,通過加鎖或者隊列來控制讀數據庫寫緩存的線程數量。比如對某個key只允許一個線程查詢數據和寫緩存,其他線程等待。

數據預熱

數據加熱的含義就是在正式部署之前,我先把可能的數據先預先訪問一遍,這樣部分可能大量訪問的數據就會加載到緩存中。在即將發生大并發訪問前手動觸發加載緩存不同的key,設置不同的過期時間,讓緩存失效的時間點盡量均勻。

文章已上傳gitee https://gitee.com/codingce/hexo-blog
項目地址: https://github.com/xzMhehe/codingce-java

總結

以上是生活随笔為你收集整理的Redis缓存穿透、缓存击穿和缓存雪崩的全部內容,希望文章能夠幫你解決所遇到的問題。

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