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

歡迎訪問 生活随笔!

生活随笔

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

数据库

Redis缓存雪崩、缓存穿透、热点Key

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

我們通常使用 緩存 + 過期時間的策略來幫助我們加速接口的訪問速度,減少了后端負載,同時保證功能的更新。

1、緩存穿透

緩存系統,按照KEY去查詢VALUE,當KEY對應的VALUE一定不存在的時候并對KEY并發請求量很大的時候,就會對后端造成很大的壓力。

(查詢一個必然不存在的數據。比如文章表,查詢一個不存在的id,每次都會訪問DB,如果有人惡意破壞,很可能直接對DB造成影響。)

由于緩存不命中,每次都要查詢持久層。從而失去緩存的意義。

1.1 使用互斥鎖排隊

業界比價普遍的一種做法,即根據key獲取value值為空時,鎖上,從數據庫中load數據后再釋放鎖。若其它線程獲取鎖失敗,則等待一段時間后重試。這里要注意,分布式環境中要使用分布式鎖,單機的話用普通的鎖(synchronized、Lock)就夠了。

public String getWithLock(String key, Jedis jedis, String lockKey,String uniqueId, long expireTime) {// 通過key獲取valueString value = redisService.get(key);if (StringUtil.isEmpty(value)) {// 分布式鎖,詳細可以參考https://blog.csdn.net/fanrenxiang/article/details/79803037// 封裝的tryDistributedLock包括setnx和expire兩個功能,在低版本的redis中不支持try {boolean locked = redisService.tryDistributedLock(jedis,lockKey, uniqueId, expireTime);if (locked) {value = userService.getById(key);redisService.set(key, value);redisService.del(lockKey);return value;} else {// 其它線程進來了沒獲取到鎖便等待50ms后重試Thread.sleep(50);getWithLock(key, jedis, lockKey, uniqueId, expireTime);}} catch (Exception e) {log.error("getWithLock exception=" + e);return value;} finally {redisService.releaseDistributedLock(jedis, lockKey, uniqueId);}}return value;}

這樣做思路比較清晰,也從一定程度上減輕數據庫壓力,但是鎖機制使得邏輯的復雜度增加,吞吐量也降低了,有點治標不治本。

1.2 布隆過濾器

bloomfilter就類似于一個hash set,用于快速判某個元素是否存在于集合中,其典型的應用場景就是快速判斷一個key是否存在于某容器,不存在就直接返回。布隆過濾器的關鍵就在于hash算法和容器大小,下面先來簡單的實現下看看效果,我這里用guava實現的布隆過濾器:

<dependencies> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>23.0</version> </dependency> </dependencies> public class BloomFilterTest {private static final int capacity = 1000000;private static final int key = 999998;private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), capacity);static {for (int i = 0; i < capacity; i++) {bloomFilter.put(i);}}public static void main(String[] args) {/* 返回計算機最精確的時間,單位微妙 */long start = System.nanoTime();if (bloomFilter.mightContain(key)) {System.out.println("成功過濾到" + key);}long end = System.nanoTime();System.out.println("布隆過濾器消耗時間:" + (end - start));int sum = 0;for (int i = capacity + 20000; i < capacity + 30000; i++) {if (bloomFilter.mightContain(i)) {sum = sum + 1;}}System.out.println("錯判率為:" + sum);}}成功過濾到999998 布隆過濾器消耗時間:215518 錯判率為:318

可以看到,100w個數據中只消耗了約0.2毫秒就匹配到了key,速度足夠快。然后模擬了1w個不存在于布隆過濾器中的key,匹配錯誤率為318/10000,也就是說,出錯率大概為3%,跟蹤下BloomFilter的源碼發現默認的容錯率就是0.03

2、緩存雪崩問題

緩存在同一時間內大量鍵過期(失效),接著來的一大波請求瞬間都落在了數據庫中導致連接異常。

解決方案:

  • 在緩存失效后,通過加鎖或者隊列來控制讀數據庫寫緩存的線程數量。比如對某個key只允許一個線程查詢數據和寫緩存,其他線程等待。
  • 可以通過緩存reload機制,預先去更新緩存,再即將發生大并發訪問前手動觸發加載緩存
  • 不同的key,設置不同的過期時間,讓緩存失效的時間點盡量均勻
  • 做二級緩存,或者雙緩存策略。A1為原始緩存,A2為拷貝緩存,A1失效時,可以訪問A2,A1緩存失效時間設置為短期,A2設置為長期。
  • public String getByKey(String keyA, String keyB) {String value = redisService.get(keyA);if (StringUtil.isEmpty(value)) {value = redisService.get(keyB);String newValue = getFromDbById();redisService.set(keyA, newValue, 31, TimeUnit.DAYS);redisService.set(keyB, newValue);}return value;}

    3、熱點key

    (1) 這個key是一個熱點key(例如一個重要的新聞,一個熱門的八卦新聞等等),所以這種key訪問量可能非常大。

    (2) 緩存的構建是需要一定時間的。(可能是一個復雜計算,例如復雜的sql、多次IO、多個依賴(各種接口)等等)

    于是就會出現一個致命問題:在緩存失效的瞬間,有大量線程來構建緩存(見下圖),造成后端負載加大,甚至可能會讓系統崩潰 。

    解決方法:
  • 使用互斥鎖(mutex key):這種解決方案思路比較簡單,就是只讓一個線程構建緩存,其他線程等待構建緩存的線程執行完,重新從緩存獲取數據就可以了

  • "提前"使用互斥鎖(mutex key):在value內部設置1個超時值(timeout1), timeout1比實際的memcache timeout(timeout2)小。當從cache讀取到timeout1發現它已經過期時候,馬上延長timeout1并重新設置到cache。然后再從數據庫加載數據并設置到cache中。

  • “永遠不過期”:

  • 這里的“永遠不過期”包含兩層意思:

    (1) 從redis上看,確實沒有設置過期時間,這就保證了,不會出現熱點key過期問題,也就是“物理”不過期。(2) 從功能上看,如果不過期,那不就成靜態的了嗎?所以我們把過期時間存在key對應的value里,如果發現要過期了,通過一個后臺的異步線程進行緩存的構建,也就是“邏輯”過期
  • 資源保護:可以做資源的隔離保護主線程池,如果把這個應用到緩存的構建也未嘗不可。
  • 4、緩存和數據庫間數據一致性問題

    分布式環境下(單機就不用說了)非常容易出現緩存和數據庫間的數據一致性問題,針對這一點的話,只能說,如果你的項目對緩存的要求是強一致性的,那么請不要使用緩存。我們只能采取合適的策略來降低緩存和數據庫間數據不一致的概率,而無法保證兩者間的強一致性。合適的策略包括 合適的緩存更新策略,更新數據庫后要及時更新緩存、緩存失敗時增加重試機制,例如MQ模式的消息隊列。

    5、拓展

    http://www.mobabel.net/總結redis熱點key發現及常見解決方案/

    總結

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

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

    主站蜘蛛池模板: 午夜高清 | 国产伦精品一区二区三区视频我 | 国产精品乱轮 | 日日摸日日碰夜夜爽无码 | 黄色一区二区三区四区 | 黄色一级大片在线观看 | 九九爱精品视频 | a视频免费在线观看 | 成人在线影片 | 免费黄色链接 | 久久免费视频1 | 日本亚洲欧美 | 欧美67194| 中文字幕第18页 | 色天使亚洲 | 五月天婷婷在线播放 | 黑森林福利视频导航 | 香蕉视频网站在线观看 | 成人精品在线 | 琪琪女色窝窝777777 | 欧美国产在线视频 | 男女考妣视频 | 日韩 欧美 中文 | 久久国产中文字幕 | 男人操女人的视频 | 婷婷在线免费 | 欧美一级特黄aaaaaa | 亚洲欧美中文字幕5发布 | 亚洲av毛片成人精品 | 91亚瑟| 日本一区二区三区视频免费看 | 国产一区二区在线观看免费 | 国产a国产片国产 | n0659极腔濑亚美莉在线播放播放 | 久久99久久99精品免观看粉嫩 | 国产精品区一区二 | 伊人久久大香线蕉成人综合网 | 人人叉人人| 日韩精品免费一区二区三区竹菊 | 九九热国产在线 | 国产成人av免费看 | www欧美在线 | 欧美成人国产va精品日本一级 | 潘金莲一级淫片免费放动漫 | 好吊色视频一区二区三区 | www.色天使 | 99国产精品久久久久久久成人热 | 一本高清dvd在线播放 | 亚洲高清视频在线 | 精品乱码一区内射人妻无码 | 麻豆国产在线播放 | 中文字幕一区二区三区在线观看 | 夜夜操夜夜爱 | 国产专区精品 | 成人动漫一区 | www.爱色av.com | 偷看洗澡一二三区美女 | 欧美精品日韩少妇 | 日本黄色一区二区 | 另类激情综合 | 伊人久久久 | 欧美国产中文 | 影院色原网站 | 日韩区在线 | 国产一级高清视频 | 久久综合九色 | 亚洲黄网av | 日韩欧美高清一区 | 操综合| 亚洲区一区二 | av中亚| 成av在线| 欧美视频一区在线观看 | 日韩有码电影 | 亚洲欧美一区二区三区四区五区 | 国产12页 | 黄色免费91 | 亚洲精品乱码久久久久久蜜桃图片 | 日本成人性爱 | 自拍偷拍激情 | 亚洲国产97 | 久久久久久久久久影视 | 精品成人无码久久久久久 | 国产精品69久久久久孕妇欧美 | 91免费黄色 | 精品无码av一区二区三区不卡 | 国产伦精品一区二区三区免费视频 | 免费欧美一区 | 中国国产毛片 | 婷婷六月综合网 | 欧美亚洲色综久久精品国产 | 欧美日韩亚洲成人 | 理想之城连续剧40集免费播放 | 国产女人毛片 | 亚洲精品久久久中文字幕痴女 | 国产日韩视频一区 | 日本特黄一级片 | 成人欧美性 | 亚洲性猛交富婆 |