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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

缓存穿透、击穿、雪崩什么的傻傻分不清楚?看了这篇文后,我明白了

發布時間:2025/3/16 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 缓存穿透、击穿、雪崩什么的傻傻分不清楚?看了这篇文后,我明白了 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

對于緩存,大家肯定都不陌生,不管是前端還是服務端開發,緩存幾乎都是必不可少的優化方式之一。在實際生產環境中,緩存的使用規范也是一直備受重視的,如果使用的不好,很容易就遇到緩存擊穿、雪崩等嚴重異常情景,從而給系統帶來難以預料的災害。

為了避免緩存使用不當帶來的損失,我們有必要了解每種異常產生的原因和解決辦法,從而做出更好的預防措施。

緩存穿透

而緩存穿透是指緩存和數據庫中都沒有的數據,這樣每次請求都會去查庫,不會查緩存,如果同一時間有大量請求進來的話,就會給數據庫造成巨大的查詢壓力,甚至擊垮db系統。

比如說查詢id為-1的商品,這樣的id在商品表里肯定不存在,如果沒做特殊處理的話,攻擊者很容易可以讓系統奔潰,那我們該如何避免這種情況發生呢?

一般來說,緩存穿透常用的解決方案大概有兩種:

一、緩存空對象

當緩存和數據都查不到對應key的數據時,可以將返回的空對象寫到緩存中,這樣下次請求該key時直接從緩存中查詢返回空對象,就不用走db了。當然,為了避免存儲過多空對象,通常會給空對象設置一個比較短的過期時間,就比如像這樣給key設置30秒的過期時間:

redisTemplate.opsForValue().set(key,?null,?30,?TimeUnit.SECONDS);

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

  • 如果有大量的key穿透,緩存空對象會占用寶貴的內存空間。

  • 空對象的key設置了過期時間,這段時間內可能數據庫剛好有了該key的數據,從而導致數據不一致的情況。

這種情況下,我們可以用更好的解決方案,也就是布隆過濾器

二、Bloom Filter

布隆過濾器(Bloom Filter)是1970年由一個叫布隆的小伙子提出的,是一種由一個很長的二進制向量和一系列隨機映射函數構成的概率型數據結構,這種數據結構的空間效率非常高,可以用于檢索集合中是否存在特定的元素。

設計思想

布隆過濾器由一個長度為m比特的位數組(bit array)與k個哈希函數(hash function)組成的數據結構。原理是當一個元素被加入集合時,通過K個散列函數將這個元素映射成一個位數組中的K個點,把它們置為1。檢索時,我們只要看看這些點是不是都是1就大約知道集合中有沒有它了,也就是說,如果這些點有任何一個0,則被檢元素一定不在;如果都是1,則被檢元素很可能在。

至于說為什么都是1的情況只是可能存在檢索元素,這是因為不同的元素計算的哈希值有可能一樣,會出現哈希碰撞,導致一個不存在的元素有可能對應的比特位為1。

舉個例子:下圖是一個布隆過濾器,共有18個比特位,3個哈希函數。當查詢某個元素w時,通過三個哈希函數計算,發現有一個比特位的值為0,可以肯定認為該元素不在集合中。

優缺點

優點:

  • 節省空間:不需要存儲數據本身,只需要存儲數據對應hash比特位

  • 時間復雜度低:基于哈希算法來查找元素,插入和查找的時間復雜度都為O(k),k為哈希函數的個數

缺點:

  • 準確率有誤:布隆過濾器判斷存在,可能出現元素不在集合中;判斷準確率取決于哈希函數的個數

  • 不能刪除元素:如果一個元素被刪除,但是卻不能從布隆過濾器中刪除,這樣進一步導致了不存在的元素也會顯示1的情況。

適用場景

  • 爬蟲系統url去重

  • 垃圾郵件過濾

  • 黑名單

緩存擊穿

緩存擊穿從字面上看很容易讓人跟穿透搞混,這也是很多面試官喜歡埋坑的地方,當然,只要我們對知識點了然于心的話,面試的時候也不會那么被糊弄

簡單來說,緩存擊穿是指一個key非常熱點,在不停的扛著大并發,大并發集中對這一個點進行訪問,當這個key在失效的瞬間,持續的大并發就穿破緩存,直接請求數據庫,就好像堤壩突然破了一個口,大量洪水洶涌而入。

當發生緩存擊穿的時候,數據庫的查詢壓力會倍增,導致大量的請求阻塞。

解決辦法也不難,既然是熱點key,那么說明該key會一直被訪問,既然如此,我們就不對這個key設置失效時間了,如果數據需要更新的話,我們可以后臺開啟一個異步線程,發現過期的key直接重寫緩存即可。

當然,這種解決方案只適用于不要求數據嚴格一致性的情況,因為當后臺線程在構建緩存的時候,其他的線程很有可能也在讀取數據,這樣就會訪問到舊數據了。

如果要嚴格保證數據一致的話,可以用互斥鎖

互斥鎖

互斥鎖就是說,當key失效的時候,讓一個線程讀取數據并構建到緩存中,其他線程就先等待,直到緩存構建完后重新讀取緩存即可。

如果是單機系統,用JDK本身的同步工具Synchronized或ReentrantLock就可以實現,但一般來說,都達到防止緩存擊穿的流量了誰還搞什么單機系統,肯定是分布式高大上點啊,這種情況我們就可以用分布式鎖來做互斥效果。

為了你們能更懂流程,作為暖男的我還是一如既往的給你們準備了偽代碼啦:

public?String?getData(String?key){String?data?=?redisTemplate.opsForValue().get(key);if?(StringUtils.isNotEmpty(data)){return?data;}String?lockKey?=?this.getClass().getName()?+?":"?+?key;RLock?lock?=?redissonClient.getLock(lockKey);try?{boolean?boo?=?lock.tryLock(5,?5,?TimeUnit.SECONDS);if?(!boo)?{//?休眠一會兒,然后再請求Thread.sleep(200L);data?=?getData(key);}//?讀取數據庫的數據data?=?getDataByDB(key);if?(StringUtils.isNotEmpty(data)){//?把數據構建到緩存中setDataToRedis(key,data);}}?catch?(InterruptedException?e)?{//?異常處理,記錄日志或者拋異常什么的}finally?{if?(lock?!=?null?&&?lock.isLocked()){lock.unlock();}}return?data; }

當然,采用互斥鎖的方案也是有缺陷的,當緩存失效的時候,同一時間只有一個線程讀數據庫然后回寫緩存,其他線程都處于阻塞狀態。如果是高并發場景,大量線程阻塞勢必會降低吞吐量。這種情況該如何處理呢?我只能說沒什么設計是完美的,你又想數據一致,又想保證吞吐量,哪有那么好的事,為了系統能更加健全,必要的時候犧牲下性能也是可以采取的措施,兩者之間怎么取舍要根據實際業務場景來決定,萬能的技術方案什么的根本不存在。

緩存雪崩

緩存雪崩也是key失效后大量請求打到數據庫的異常情況,不過,跟緩存擊穿不同的是,緩存擊穿因為指一個熱點key失效導致的情況,而緩存雪崩是指緩存中大批量的數據同時過期,巨大的請求量直接落到db層,引起db壓力過大甚至宕機,這也符合字面上的“雪崩”說法。

解決方案

緩存雪崩的解決方案和擊穿的思路一致,可以設置key不過期或者互斥鎖的方式。

除此之外,因為是預防大面積的key同時失效,可以給不同的key過期時間加上隨機值,讓緩存失效的時間點盡量均勻 ,這樣可以保證數據不會在同一時間大面積失效

redisTemplate.opsForValue().set(Key, value, time + Math.random()?* 1000, TimeUnit.SECONDS);??

同時還可以結合主備緩存策略來讓互斥鎖的方式更加的可靠,

主緩存:有效期按照經驗值設置,設置為主讀取的緩存,主緩存失效后從數據庫加載最新值。

備份緩存:有效期長,獲取鎖失敗時讀取的緩存,主緩存更新時需要同步更新備份緩存。

一般來說,上面三種緩存異常場景問的比較多,了解這幾種基本就夠了,但有些面試官可能喜歡劍走偏鋒,進一步延伸其他的異常情景做詢問,以防萬一,我們也加個菜,介紹下另外兩種常見緩存異常。

緩存預熱

緩存預熱就是系統上線后,先將相關的數據構建到緩存中,這樣就可以避免用戶請求的時候直接查庫。

這部分預熱的數據主要取決于訪問量和數據量大小,如果數據的訪問量不大的話,那么就沒必要做預熱,都沒什么多少請求了,直接按正常的緩存讀取流程執行就好。

訪問量大的話,也要看數據的大小來做預熱措施。

  • 數據量不大的時候,工程啟動的時候進行加載緩存動作,這種數據一般可以是電商首頁的運營位之類的信息;

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

  • 數據量太大的時候,優先保證熱點數據進行提前加載到緩存,并且確保訪問期間不能更改緩存,比如用定時器在秒殺活動前30分鐘就把商品信息之類的刷新到緩存,同時規定后臺運營人員不能在秒殺期間更改商品屬性。

緩存降級

緩存降級是指緩存失效或緩存服務器掛掉的情況下,不去訪問數據庫,直接返回默認數據或訪問服務的內存數據。

在項目實戰中通常會將部分熱點數據緩存到服務的內存中,類似HashMap、Guava這樣的工具,一旦緩存出現異常,可以直接使用服務的內存數據,從而避免數據庫遭受巨大壓力。

當然,這樣的操作對于業務是有損害的,分布式系統中很容易就出現數據不一致的問題,所以,一般這種情況下,我們都優先保證從運維角度確保緩存服務器的高可用性,比如Redis的部署采用集群方式,同時做好備份,總之,盡量避免出現降級的影響。

最后

關于緩存的幾大異常處理我們就講解到這了,雖然每種異常我們都給出了解決的方案,但不是說這玩意直接套上就能用了。現實開發過程中還是要根據實際情況來針對緩存做相應措施,比如用布隆過濾器預防緩存穿透雖然很有效,但并不算特別常用,這年頭,防止惡意攻擊什么的都是先在運維層面做限制,業務代碼層面更多的是對參數和數據做校驗。

如果每個使用緩存的地方都要考慮的這么復雜的話,那工作量無疑會更加繁雜,過度設計只會讓代碼維護起來也麻煩,而且實用性還不一定強,沒必要啊。程序員嘛,給自己增添煩惱的事情越少越好,畢竟我們最大的敵人不是996,而是那珍貴的發量啊。

有道無術,術可成;有術無道,止于術

歡迎大家關注Java之道公眾號

好文章,我在看??

總結

以上是生活随笔為你收集整理的缓存穿透、击穿、雪崩什么的傻傻分不清楚?看了这篇文后,我明白了的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 日本一区二区三区在线免费观看 | 起碰在线 | 色妞ww精品视频7777 | 5个黑人躁我一个视频 | 免费观看视频一区二区 | www.成人网.com | 精品欧美一区二区久久久久 | 裸体毛片| 午夜精品久久久久久久久久久久久蜜桃 | 国产91福利 | 国内精品视频在线 | 韩国主播青草55部完整 | 最近最经典中文mv字幕 | 91香蕉一区二区三区在线观看 | 国产欧美日韩中文字幕 | 爱逼av| 少妇高潮av久久久久久 | 欧美三级一区 | 日韩综合精品 | 丰满大肥婆肥奶大屁股 | 久久精品a | 日韩一二三四区 | 国产福利影院 | 成年人在线免费观看视频网站 | 嫩草嫩草嫩草嫩草 | 欧美性另类 | 国产免费av在线 | 亚洲伦理精品 | 一个人看的毛片 | 影音先锋男人的天堂 | 久久成人在线观看 | 打屁股无遮挡网站 | 少妇无码av无码专区在线观看 | 玖玖爱这里只有精品 | 国产成人综合视频 | 国产尤物视频在线观看 | 神马久久精品 | 在线观看国产三级 | 无码人妻一区二区三区av | 蜜臀视频在线观看 | av网站免费在线观看 | 男人和女人日b视频 | 日本动漫艳母 | 中文字幕永久在线视频 | 黑人巨大精品人妻一区二区 | 亚洲精品一区二区潘金莲 | 福利小视频在线观看 | 足疗店女技师按摩毛片 | 国产精品色在线网站 | 欧美日韩八区 | av中文字幕在线播放 | 日韩黄色一级大片 | av鲁丝一区鲁丝二区鲁丝 | 刘亦菲国产毛片bd | 中文在线天堂网 | av噜噜在线观看 | 偷拍夫妻性生活 | 国产精品一品 | 无码人妻精品一区二区三区不卡 | 成人福利视频 | 日本大尺度电影免费观看全集中文版 | 日本午夜激情视频 | 日韩精品视 | 精品免费一区二区 | 秋霞在线观看视频 | 久久久96人妻无码精品 | 草草在线观看 | 日本在线视频免费观看 | 深夜激情影院 | 国产精品亚洲一区二区三区 | 中文字幕日韩高清 | 亚洲一卡一卡 | 亚洲精品一级片 | 精彩视频一区二区 | 超碰在线成人 | 亚洲丁香婷婷 | 51成人精品网站 | 超碰在线观看91 | 91在线免费视频观看 | 日韩涩| 久久av资源| 热久久最新网址 | 99国内揄拍国内精品人妻免费 | 米奇狠狠干 | 人人插人人干 | 在线观看高清av | av一区在线播放 | av手机观看| 丰满岳乱妇在线观看中字无码 | 国产精品国产三级国产专区51 | 蜜臀va| 少妇性高潮视频 | 91极品在线 | 欧美丰满美乳xxx高潮www | 国产美女明星三级做爰 | 久久国精品 | 丁香av | 国产av一区二区三区精品 | 蜜臀人妻四季av一区二区不卡 |