java高分面试指南:redis怎么保证高可用
緩存雪崩
緩存雪崩指的是Redis當(dāng)中的大量緩存在同一時間全部失效,而假如恰巧這一段時間同時又有大量請求被發(fā)起,那么就會造成請求直接訪問到數(shù)據(jù)庫,可能會把數(shù)據(jù)庫沖垮。
緩存雪崩一般形容的是緩存中沒有而數(shù)據(jù)庫中有的數(shù)據(jù),而因為時間到期導(dǎo)致請求直達(dá)數(shù)據(jù)庫。
解決方案
解決緩存雪崩的方法有很多:
-
1、加鎖,保證單線程訪問緩存。這樣就不會有很多請求同時訪問到數(shù)據(jù)庫。
-
2、失效時間不要設(shè)置成一樣。典型的就是初始化預(yù)熱數(shù)據(jù)的時候,將數(shù)據(jù)存入緩存時可以采用隨機時間來確保不會咋同一時間有大量緩存失效。
-
3、內(nèi)存允許的情況下,可以將緩存設(shè)置為永不失效。
緩存擊穿
緩存擊穿和緩存雪崩很類似,區(qū)別就是緩存擊穿一般指的是單個緩存失效,而同一時間又有很大的并發(fā)請求需要訪問這個key,從而造成了數(shù)據(jù)庫的壓力。
解決方案
解決緩存擊穿的方法和解決緩存雪崩的方法很類似:
-
1、加鎖,保證單線程訪問緩存。這樣第一個請求到達(dá)數(shù)據(jù)庫后就會重新寫入緩存,后續(xù)的請求就可以直接讀取緩存。
-
2、內(nèi)存允許的情況下,可以將緩存設(shè)置為永不失效。
緩存穿透
緩存穿透和上面兩種現(xiàn)象的本質(zhì)區(qū)別就是這時候訪問的數(shù)據(jù)其在數(shù)據(jù)庫中也不存在,那么既然數(shù)據(jù)庫不存在,所以緩存里面肯定也不會存在,這樣如果并發(fā)過大就會造成數(shù)據(jù)源源不斷的到達(dá)數(shù)據(jù)庫,給數(shù)據(jù)庫造成極大壓力。
解決方案
對于緩存穿透問題,加鎖并不能起到很好地效果,因為本身key就是不存在,所以即使控制了線程的訪問數(shù),但是請求還是會源源不斷的到達(dá)數(shù)據(jù)庫。
解決緩存穿透問題一般可以采用以下方案配合使用:
-
1、接口層進行校驗,發(fā)現(xiàn)非法的key直接返回。比如數(shù)據(jù)庫中采用的是自增id,那么如果來了一個非整型的id或者負(fù)數(shù)id可以直接返回,或者說如果采用的是32位uuid,那么發(fā)現(xiàn)id長度不等于32位也可以直接返回。
-
2、將不存在的數(shù)據(jù)也進行緩存,可以直接緩存一個空或者其他約定好的無效value。采用這種方案最好將key設(shè)置一個短期失效時間,否則大量不存在的key被存儲到Redis中,也會占用大量內(nèi)存。
布隆過濾器(Bloom Filter)
針對上面緩存穿透的解決方案,我們思考一下:假如一個key可以繞過第1種方法的校驗,而此時有大量的不存在key被訪問(如1億個或者10億個),那么這時候全部存儲到緩存,會占用非常大的空間,會浪費大量服務(wù)器內(nèi)存,導(dǎo)致內(nèi)存不足。
那么有沒有一種更好的解決方案呢?這就是我們接下來要介紹的布隆過濾器,布隆過濾器就可以最大程度的解決key值過多的這個問題。
什么是布隆過濾器
可能大部分人都知道有這么一個面試問題:如何在10億的海量的無序的數(shù)據(jù)中快速判斷一個元素是否存在?
要解決這個問題就需要用到布隆過濾器,否則大部分服務(wù)器的內(nèi)存是無法存儲這么大的數(shù)量級的數(shù)據(jù)的。
布隆過濾器(Bloom Filter)是由布隆在1970年提出的。它實際上是一個很長的二進制向量(位圖)和一系列隨機映射函數(shù)(哈希函數(shù))。
布隆過濾器可以用于檢索一個元素是否在一個集合中。它的優(yōu)點是空間效率和查詢時間都比一般的算法要好的多,缺點是有一定的誤識別率而且刪除困難。
位圖(Bitmap)
Redis當(dāng)中有一種數(shù)據(jù)結(jié)構(gòu)就是位圖,布隆過濾器其中重要的實現(xiàn)就是位圖的實現(xiàn),也就是位數(shù)組,并且在這個數(shù)組中每一個位置只有0和1兩種狀態(tài),每個位置只占用1個字節(jié),其中0表示沒有元素存在,1表示有元素存在。如下圖所示就是一個簡單的布隆過濾器示例(一個key值經(jīng)過哈希運算和位運算就可以得出應(yīng)該落在哪個位置):
哈希碰撞
上面我們發(fā)現(xiàn),lonely和wolf落在了同一個位置,這種不同的key值經(jīng)過哈希運算后得到相同值的現(xiàn)象就稱之為哈希碰撞。發(fā)生哈希碰撞之后再經(jīng)過位運算,那么最后肯定會落在同一個位置。
如果發(fā)生過多的哈希碰撞,就會影響到判斷的準(zhǔn)確性,所以為了減少哈希碰撞,我們一般會綜合考慮以下2個因素:
-
1、增大位圖數(shù)組的大小(位圖數(shù)組越大,占用的內(nèi)存越大)。
-
2、增加哈希函數(shù)的次數(shù)(同一個key值經(jīng)過1個函數(shù)相等了,那么經(jīng)過2個或者更多個哈希函數(shù)的計算,都得到相等結(jié)果的概率就自然會降低了)。
上面兩個方法我們需要綜合考慮:比如增大位數(shù)組,那么就需要消耗更多的空間,而經(jīng)過越多的哈希計算也會消耗cpu影響到最終的計算時間,所以位數(shù)組到底多大,哈希函數(shù)次數(shù)又到底需要計算多少次合適需要具體情況具體分析。
布隆過濾器的2大特點
下面這個就是一個經(jīng)過了2次哈希函數(shù)得到的布隆過濾器,根據(jù)下圖我們很容易看到,假如我們的Redis根本不存在,但是Redis經(jīng)過2次哈希函數(shù)之后得到的兩個位置已經(jīng)是1了(一個是wolf通過f2得到,一個是Nosql通過f1得到)。
所以通過上面的現(xiàn)象,我們從布隆過濾器的角度可以得出布隆過濾器主要有2大特點:
-
1、如果布隆過濾器判斷一個元素存在,那么這個元素可能存在。
-
2、如果布隆過濾器判斷一個元素不存在,那么這個元素一定不存在。
而從元素的角度也可以得出2大特點:
-
1、如果元素實際存在,那么布隆過濾器一定會判斷存在。
-
2、如果元素不存在,那么布隆過濾器可能會判斷存在。
PS:需要注意的是,如果經(jīng)過N次哈希函數(shù),則需要得到的N個位置都是1才能判定存在,只要有一個是0,就可以判定為元素不存在布隆過濾器中。
fpp
因為布隆過濾器中總是會存在誤判率,因為哈希碰撞是不可能百分百避免的。布隆過濾器對這種誤判率稱之為假陽性概率,即:False Positive Probability,簡稱為fpp。
在實踐中使用布隆過濾器時可以自己定義一個fpp,然后就可以根據(jù)布隆過濾器的理論計算出需要多少個哈希函數(shù)和多大的位數(shù)組空間。需要注意的是這個fpp不能定義為100%,因為無法百分保證不發(fā)生哈希碰撞。
最后分享一波我的面試寶典——一線互聯(lián)網(wǎng)大廠Java核心面試題庫
以下是我個人的一些做法,希望可以給各位提供一些幫助:
點擊《一線互聯(lián)網(wǎng)大廠Java核心面試題庫》即可免費領(lǐng)取,整理了很長一段時間,拿來復(fù)習(xí)面試刷題非常合適,其中包括了Java基礎(chǔ)、異常、集合、并發(fā)編程、JVM、Spring全家桶、MyBatis、Redis、數(shù)據(jù)庫、中間件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等,且還會持續(xù)的更新…可star一下!
283頁的Java進階核心pdf文檔
Java部分:Java基礎(chǔ),集合,并發(fā),多線程,JVM,設(shè)計模式
數(shù)據(jù)結(jié)構(gòu)算法:Java算法,數(shù)據(jù)結(jié)構(gòu)
開源框架部分:Spring,MyBatis,MVC,netty,tomcat
分布式部分:架構(gòu)設(shè)計,Redis緩存,Zookeeper,kafka,RabbitMQ,負(fù)載均衡等
微服務(wù)部分:SpringBoot,SpringCloud,Dubbo,Docker
還有源碼相關(guān)的閱讀學(xué)習(xí)
gCloud,Dubbo,Docker
[外鏈圖片轉(zhuǎn)存中…(img-IQmcDROd-1625046573471)]
還有源碼相關(guān)的閱讀學(xué)習(xí)
[外鏈圖片轉(zhuǎn)存中…(img-sQ31gj3D-1625046573473)]
總結(jié)
以上是生活随笔為你收集整理的java高分面试指南:redis怎么保证高可用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 英雄联盟求个搞英雄联盟频道开业典礼的人才
- 下一篇: 从入门到精通!java可视化编程软件哪个