本文已收錄于專欄
??《Redis面試題匯總——2021最新版本》??
上千人點贊收藏,全套Redis高頻面試題,大廠必備技能!
面試官心理分析
從面試官的角度分析,出這道題的目的是為了考察你對快取的認知水平,以及結合快取處理業務、改善架構的能力,這道題很明顯是讓你自由發揮,給了你引領面試官往自己最熟悉的知識點引導的機會,所以要盡可能的把握這次機會,給面試官一個好的印象,這道題聊得好,就是能深入交流個把小時了,如果是一面基本上能輕輕松松拿下, 但是千萬不要上來就把話題聊死了,聊太淺了,那基本就是回去等通知了…… ?
比如以下這種回答方式:

很多人會說這么回答也沒錯呀!沒錯是沒錯,但是總有一種給你機會不中用的感覺,
此時此刻面試官內心想發大致是這樣的:
-
比較基礎,應該沒有很深入的了解過Redis
-
想問題停留在表面呀,估計平時就知道干活,沒想過問題
-
給你自由發揮的機會,你不把握呀,看樣子還是得我自己來,先問你幾個分布式、持久化的問題看看水平怎么樣,不行就這樣了吧,后面還有好多人,等會要下班了,
如果不想硬抗下面試官的降龍十八掌,就應該主動挑起面試官的興趣,并且把自己的格局(水平廣度和深度)率先提升起來,將自己會的東西盡可能的多講一些出來, ?
比如以下這種回答方式:

?
Redis面試題匯總

這個我的理解大致是這樣的面試官!!
高性能:高性能一個很大的標準,就是回應時間快,Redis基于記憶體存盤,CPU訪問速度快,此外Redis對于資料結構的極致優化、內部執行緒模型和網路I/O模型的設計,決定了Redis是一個高性能存盤資料庫,唯一的缺點就是記憶體比較昂貴,通常情況下資源比較有限,因此對于非常大的資料快取架構應該合理設計,我們通常不會在Redis中存放過大的資料,因為這樣會導致Redis性能下降,
高并發:高并發通常指標有回應時間(Response Time),吞吐量(Throughput),每秒查詢率QPS(Query Per Second)和并發用戶數等,Redis雖然它是一個單行程單執行緒模型,但是Redis確實高并發業務場景下的一把利器,目前Redis的QPS已經能達到10萬甚至是100萬級別了,這是絕對的高并發,
高可用:Redis高可用主要體現在主從復制、sentinel(哨兵模式)和Cluster(集群模式)三者 ?

這個我的理解大致是這樣的面試官!!
Redis的單執行緒指的是執行命令操作使用單執行緒,Redis6.x發布之后使用多執行緒處理網路資料的讀寫和協議決議,Redis單執行緒這么快的原因主要有這些點:
-
采用I/O多路復用非阻塞模型處理客戶端socket連接,能夠極大的優化Redis服務端回應速度和效率,多路 I/O 復用技術可以讓單個執行緒高效的處理多個連接請求,盡量減少網路 IO 的時間消耗,
-
基于記憶體存盤,減少磁盤IO,讀取速度快
-
Redis對內部資料結構做了極致的優化,使Redis的資料結構非常高效,并且在不同的資料量和存盤內容采取不同的編碼方式,這就涉及到了 Redis 底層的編碼轉換,比如list、hash、zset 三個鍵使用到了 ziplist 壓縮串列編碼,ziplist 是一種結構緊湊的資料結構,當某一鍵值中所包含的元素較少時,會優先存盤在 ziplist 中,當元素個數超過某一值后,才將 ziplist 轉化為標準存盤結構,當然這一值是在redis.conf中可自定義配置,此外SDS的記憶體預分配、Hash結果Rehash中的漸進式hash、ZSet順序基于SkipList存盤,都優化了資料結構,使其更快,
-
Redis在執行命令操作使用單執行緒,無需考慮并發鎖的設計,以及多執行緒帶來的CPU背景關系切換消耗,因此執行命令更快

?
這個我的理解大致是這樣的面試官!!
Redis有5種基本資料型別它們分別是String、List、Hash、Set、ZSet;此外還有三種特殊資料型別Bitmaps、Geospatial、HyperLogLog
| 資料型別 | 簡單描述 | 使用場景 |
|---|---|---|
| String | string(字串)是Redis最簡單也是使用最廣泛的資料結構,它的內部是一個字符陣列,String(字串)是動態字串,允許修改;它在結構上的實作類似于Java中的ArrayList(默認構造一個大小為10的初始陣列),這是冗余分配記憶體的思想,也稱為預分配;這種思想可以減少擴容帶來的性能消耗,當string(字串)的大小達到擴容閾值時,將會對string(字串)進行擴容,string(字串)的擴容主要有三種情況:1.長度小于1MB,擴容后為原先的兩倍; length = length * 2 2.長度大于1MB,擴容后增加1MB; length = length + 1MB 3. 字串的長度最大值為 512MB | 快取、計數器、分布式鎖等, |
| List | Redis的串列相當于Java語言中的LinkedList,它是一個雙向鏈表資料結構(但是這個結構設計比較巧妙,后面會介紹),支持前后順序遍歷,鏈表結構插入和洗掉操作快,時間復雜度O(1),查詢慢,時間復雜度O(n),Redis的list(串列)不是一個簡單,LinkedList,而是quicklist ——“快速串列”,quicklist是多個ziplist(壓縮串列)組成的雙向串列; | 鏈表、異步佇列、微博關注人時間軸串列…… |
| Hash | Redis的hash(字典)相當于Java語言中的HashMap,它是根據散列值分布的無序字典,內部的元素是通過鍵值對的方式存盤,hash(字典)的實作與Java中的HashMap(JDK1.7)的結構也是一致的,它的資料結構也是陣列+鏈表組成的二維結構,節點元素散列在陣列上,如果發生hash碰撞則使用鏈表串聯在陣列節點上,Redis中的hash(字典)存盤的value只能是字串值,此外擴容與Java中的HashMap也不同,Java中的HashMap在擴容的時候是一次性完成的,而Redis考慮到其核心存取是單執行緒的性能問題,為了追求高性能,因而采取了漸進式rehash策略,漸進式rehash指的是并非一次性完成,它是多次完成的,因此需要保留舊的hash結構,所以Redis中的hash(字典)會存在新舊兩個hash結構,在rehash結束后也就是舊hash的值全部搬遷到新hash之后,新的hash在功能上才會完全替代以前的hash, | 用戶資訊、Hash 表…… |
| Set | Redis的set(集合)相當于Java語言里的HashSet,它內部的鍵值對是無序的、唯一的,它的內部實作了一個所有value為null的特殊字典,集合中的最后一個元素被移除之后,資料結構被自動洗掉,記憶體被回收, | 去重功能、贊、踩、共同好友…… |
| ZSet | zset(有序集合)是Redis中最常問的資料結構,它類似于Java語言中的SortedSet和HashMap的結合體,它一方面通過set來保證內部value值的唯一性,另一方面通過value的score(權重)來進行排序,這個排序的功能是通過Skip List(跳躍串列)來實作的,zset(有序集合)的最后一個元素value被移除后,資料結構被自動洗掉,記憶體被回收, | 粉絲串列、學生成績排序、訪問量排行榜、點擊量排行榜…… |
| Bitmaps | Bitmaps 稱為位圖,嚴格來說它不是一種資料型別,Bitmaps底層就是字串(key-value)byte陣列,我們可以使用普通的get/set直接獲取和設值位圖的內容,也可以通過Redis提供的位圖操作getbit/setbit等將byte陣列看成“位陣列”來處理,Bitmaps 的“位陣列”每個單元格只能存盤0和1,陣列的下標在Bitmaps中稱為偏移量,Bitmaps設定時key不存在會自動生成一個新的字串,如果設定的偏移量超出了現有內容的范圍,就會自動將位陣列進行零擴充 | 員工打卡…… |
| Geospatial | Geospatial是Redis在3.2版本以后增加的地理位置GEO模塊 | 微信附近的人,在線點餐“附近的餐館”…… |
| HyperLogLog | HyperLogLog是用來做基數統計的演算法,它提供不精確的去重計數方案(這個不精確并不是非常不精確),標準誤差是0.81%,對于UV這種統計來說這樣的誤差范圍是被允許的,HyperLogLog的優點在于,輸入元素的數量或者體積非常大時,基數計算的存盤空間是固定的,在Redis中,每個HyperLogLog鍵只需要花費12KB記憶體,就可以計算接近2^64個不同的基數,但是HyperLogLog只能統計基數的大小(也就是資料集的大小,集合的個數),他不能存盤元素的本身,不能向set集合那樣存盤元素本身,也就是說無法回傳元素, | 基數統計比如UV等 |

這個我的理解大致是這樣的面試官!!
Redis的資料結構均可以通過EXPIRE key seconds 的方式設定key的過期時間(TTL),我們也習慣的認為Redis的key過期時間到了,就會自動洗掉,顯然這種想法并不正確,Redis的設計考慮到性能/記憶體等綜合因素,設計了一套過期策略,
-
主動洗掉(惰性洗掉)
-
被動洗掉(定期策略)
主動洗掉(惰性洗掉)指的是當key被訪問的時候,先校驗key是否過期,如果過期了則主動洗掉, 被動洗掉(定期策略)指的是Redis服務器定時隨機的測驗key的過期時間,如果過期了則被動洗掉,被動洗掉的存在必不可少,因為存在一些過期且永久不在訪問的key,如果都依賴主動洗掉,那么它們將會永久占用記憶體, Redis為了保證提供高性能服務,被動洗掉過期的key,采用了貪心策略/概率演算法,默認每隔10秒掃描一次,具體策略如下:
-
從過期字典(設定了過期時間的key的集合)中隨機選擇20個key,檢查其是否過期
-
洗掉其中已經過期的key
-
如果洗掉的過期key數量大于25%,則重復步驟1
此外開發在設計Redis快取架構時,一定要注意要盡可能的避免(禁止)將大量的key設定為同一過期時間,因為結合被動洗掉可知,Redis被動洗掉過期key時,會導致服務短暫的不可用;如果存在大量key同時過期,這會導致被動洗掉key的三個步驟回圈多次,從而導致Redis服務出現卡頓情況,這種情況在大型流量專案是無法接收的, 因此為了避免這種情況出現,一定要將一些允許過期時間不需要非常精確的key,設定較為隨機的過期時間,這樣就可以將卡頓時間縮小, ?

這個我的理解大致是這樣的面試官!!
在分布式場景中我們常見的分布式鎖解決方案有(如果自己都會可以把其他兩種也在這帶出來,如果不會那就別把自己坑了呀!):
-
基于資料庫鎖機制實作的分布式鎖
-
基于Zookeeper實作的分布式鎖
-
基于Redis實作的分布式鎖
而關于Redis實作分布式鎖的方案是這樣的, 如果Redis是在單機環境中我們可以通過,Redis提供的原子指令來實作分布式鎖
set key value [EX seconds] [PX milliseconds] [NX|XX]
為了防止A加的鎖,被B洗掉了,可以加鎖時傳入客戶端加鎖標記,只有當客戶端傳入的標記和鎖標記相同時才允許解鎖,不過Redis并未提供這樣的功能,我們只能通過Lua腳本來處理,因為Lua腳本可以保證多個指令的原子性執行,最后我們還要考慮鎖的超時問題,如果客戶端一直不釋放鎖肯定也是不行的,因此鎖只能保證在指定的超時時間范圍內不被其他客戶端解鎖,超時之后就自動釋放了,這種情況很難我們可以這樣優化:
-
盡可能不要在Redis分布式鎖中執行較長的任務,盡可能的縮小鎖區間內執行代碼,就像單JVM鎖中的synchronized優化一樣,我們可以考慮優化鎖的區間
-
多做壓力測驗和線上真實場景的模擬測驗,估算一個合適的鎖超時時間
-
做好Redis分布式鎖超時任務未執行完的問題發生后,資料恢復手段的準備
如果是在分布式環境中,會增加一個新的問題,比如sentinel+一主多從環境中,可能存在客戶端在主節點上申請了鎖,但是同步未完成,主節點宕機了,此時新選舉的主節點上鎖是失效的, 對于這種情況的處理應該是這么考慮的,首先Redis主從同步直接無論如何都無法解決資料會有丟失的情況,所以我們考慮把像一個Redis申請鎖,變成像多個單機Redis申請鎖,只有大部分申請成功就行,這種思想就是RedLock(紅鎖), RedLock通過使用多個Redis實體,各個實體之間沒有主從關系,相互獨立;加鎖的時候,客戶端向所有的節點發送加鎖指令,如果過半的節點set成功,就加鎖成功,釋放鎖時,需要向所有的節點發送del指令來釋放鎖, 紅鎖雖然解決了主從同步的問題,但是帶來新的復雜問題:
-
第一個問題是時鐘漂移
-
第二個問題是客戶端像不同的Redis服務端申請鎖成功的時間是不同的
因此在RedLock中需要計算申請的鎖的最小有效時長,假設客戶端申請鎖成功,第一個key設定成功的時間為TF,最后一個key設定成功的時間為TL,鎖的超時時間為TTL,不同行程之間的時鐘差異為CLOCK_DIFF,則鎖的最小有效時長是:
TIME = TTL - (TF- TL) - CLOCK_DIFF
采用Redis來實作分布式鎖,離不開服務器宕機等不可用問題,這里RedLock紅鎖也一樣,即使是多臺服務器申請鎖,我們也要考慮服務器宕機后的處理,官方建議采用AOF持久化處理, 但是AOF持久化只對正常SHUTDOWN這種指令能做到重啟恢復,但是如果是斷電的情況,可能導致最后一次持久化到斷電期間的鎖資料丟失,當服務器重啟后,可能會出現分布式鎖語意錯誤的情況,所以為了規避這種情況,官方建議Redis服務重啟后,一個最大客戶端TTL時間內該Redis服務不可用(不提供申請鎖的服務),這確實可以解決問題,但是顯而易見這肯定影響Redis服務器的性能,并且在多數節點都出現這種情況的時候,系統將出現全域不可用的狀態, ?

這個我的理解大致是這樣的面試官!!
Redis的非常快,很大一部分原因是因為Redis的資料存盤在記憶體中,既然在記憶體中,那么當服務器宕機或者斷電的時候,資料就會全部丟失了,所以Redis提供了兩種機制來保證Redis資料不會因為故障而全部丟失,這種機制稱為Redis的持久化機制, Redis的持久化機制有兩種:
-
RDB(Redis Data Base) 記憶體快照
-
AOF(Append Only File) 增量日志
RDB(Redis DataBase) 指的是在指定的時間間隔內將記憶體中的資料集快照寫入磁盤,RDB是記憶體快照(記憶體資料的二進制序列化形式)的方式持久化,每次都是從Redis中生成一個快照進行資料的全量備份, 優點:
-
存盤緊湊,節省記憶體空間
-
恢復速度非常快
-
適合全量備份、全量復制的場景,經常用于災難恢復(對資料的完整性和一致性要求相對較低的場合)
缺點:
-
容易丟失資料,容易丟失兩次快照之間Redis服務器中變化的資料,
-
RDB通過fork子行程對記憶體快照進行全量備份,是一個重量級操作,頻繁執行成本高,
-
fork子行程,雖然共享記憶體,但是如果備份時記憶體被修改,最大可能膨脹到2倍大小,
RDB觸發的規則分為兩大類,分別是手動觸發和自動觸發: 自動觸發:
-
配置觸發規則
-
shutdown觸發
-
flushall觸發
手動觸發:
-
save
-
bgsave
AOF(Append Only File)是把所有對記憶體進行修改的指令(寫操作)以獨立日志檔案的方式進行記錄,重啟時通過執行AOF檔案中的Redis命令來恢復資料,AOF能夠解決資料持久化實時性問題,是現在Redis持久化機制中主流的持久化方案(后續會談到4.0以后的混合持久化), 優點:
-
資料的備份更加完整,丟失資料的概率更低,適合對資料完整性要求高的場景
-
日志檔案可讀,AOF可操作性更強,可通過操作日志檔案進行修復
缺點:
-
AOF日志記錄在長期運行中逐漸龐大,恢復起來非常耗時,需要定期對AOF日志進行瘦身處理(后續詳述)
-
恢復備份速度比較慢
-
同步寫操作頻繁會帶來性能壓力
AOF日志是以檔案的形式存在的,當程式對AOF日志檔案進行寫操作時,實際上將內容寫到了內核為檔案描述符分配的一個記憶體緩沖區中,隨后內核會異步的將緩沖區中的資料重繪到磁盤中,如果緩沖區中的資料沒來得及刷回磁盤時,服務器宕機了,這些資料就會丟失, 因此Redis通過呼叫Linux作業系統的glibc提供的fsync(int fid)來將指定檔案的內容強制從內核緩沖區刷回磁盤,以此來保證緩沖區中的資料不會丟失,不過這是一個IO操作,相比Redis的性能來說它是非常慢的,所以不能頻繁的執行, Redis組態檔中有三種重繪緩沖區的配置:
appendfsync always 每次Redis寫操作,都寫入AOF日志,這種配置理論上Linux作業系統扛不住,因為Redis的并發遠遠超過了Linux作業系統提供的最大重繪頻率,就算Redis寫操作比較少的情況,這種配置也是非常耗性能的,因為涉及到IO操作,所以這個配置基本上不會用 ?
appendfsync everysec 每秒重繪一次緩沖區中的資料到AOF檔案,這個Redis組態檔中默認的策略,兼容了性能和資料完整性的折中方案,這種配置,理論上丟失的資料在一秒鐘左右 ?
appendfsync no Redis行程不會主動的去重繪緩沖區中的資料到AOF檔案中,而是直接交給作業系統去判斷,這種操作也是不推薦的,丟失資料的可能性非常大, ?
前面提到AOF的缺點時,說過AOF屬于日志追加的形式來存盤Redis的寫指令,這會導致大量冗余的指令存盤,從而使得AOF日志檔案非常龐大,這種情況不僅占記憶體,也會導致恢復的時候非常緩慢,因此Redis提供重寫機制來解決這個問題,Redis的AOF持久化機制執行重寫后,保存的只是恢復資料的最小指令集,我們如果想手動觸發可以使用如下指令
bgrewriteaof
Redis4.0后的重寫使用的是RDB快照和AOF指令拼接的方式,在AOF檔案的頭部是RDB快照的二進制形式的資料,尾部是快照產生后發生的寫入操作的指令, 由于重寫AOF檔案時,會對Redis的性能帶來一定的影響,因此也不能隨便的進行自動重寫,Redis提供兩個配置用于自動進行AOF重寫的指標,只有這兩個指標同時滿足的時候才會發生重寫:
auto-aof-rewrite-percentage 100:指的是當檔案的記憶體達到原先記憶體的兩倍
auto-aof-rewrite-min-size 64mb:指的是檔案重寫的最小記憶體大小
此外Redis4.0后大部分的使用場景都不會單獨使用RDB或者AOF來做持久化機制,而是兼顧二者的優勢混合使用, 最后來總結這兩者,到呼叫哪個更好呢?
-
推薦是兩者均開啟
-
如果對資料不敏感,可以選單獨用RDB
-
不建議單獨用AOF,因為可能會出現Bug
-
如果只是做純記憶體快取,可以都不用

這個我的理解大致是這樣的面試官!!
Redis是基于記憶體存盤的key-value資料庫,我們知道記憶體雖然快但空間小,當物理記憶體達到上限時,系統就會跑的很慢,所以我們會設定Redis的最大記憶體,當Redis記憶體達到設定閾值的時候會觸發記憶體回收,Redis提供了很多記憶體淘汰策略:
-
noeviction:當達到記憶體限制并且客戶端嘗試執行可能導致使用更多記憶體的命令時回傳錯誤,簡單來說讀操作仍然允許,但是不準寫入新的資料,del(洗掉)請求可以,
-
allkeys-lru:從全體key中,通過lru(Least Recently Used - 最近最少使用)演算法進行淘汰
-
allkeys-random:從全體key中,隨機進行淘汰
-
volatile-lru:從設定了過期時間的全部key中,通過lru(Least Recently Used - 最近最少使用)演算法進行淘汰,這樣可以保證未設定過期時間需要被持久化的資料,不會被選中淘汰
-
volatile-random:從設定了過期時間的全部key中,隨機進行淘汰
-
volatile-ttl:從設定了過期時間的全部key中,通過比較key的剩余過期時間TTL的值,TTL越小越先被淘汰
-
volatile-lfu:對有過期時間的key采用LFU淘汰演算法
-
allkeys-lfu:對全部key采用LFU淘汰演算法
在這些策略中有兩個比較重要的演算法一個是LRU,也就是淘汰最近最少使用的key,不過Redis使用了近似LRU演算法,并不是完完全全準確的淘汰掉最近最不經常使用的key,但是總體的準確度也可以得到保證,近似LRU演算法非常簡單,在Redis的key物件中,增加24bit用于存盤最近一次訪問的系統時間戳,當客戶端對Redis服務端發送key的寫入相關請求時,發現記憶體達到maxmemory,此時觸發惰性洗掉;Redis服務通過隨機采樣,選擇5個滿足條件的key(注意這個隨機采樣allkeys-lru是從所有的key中隨機采樣,volatile-lru是從設定了過期時間的所有key中隨機采樣),通過key物件中記錄的最近訪問時間戳進行比較,淘汰掉這5個key中最舊的key;如果記憶體仍然不夠,就繼續重復這個步驟,在Redis 3.0 maxmemory_samples設定為10的時候,Redis的近似LRU演算法已經非常的接近真實LRU演算法了,但是顯然maxmemory_samples設定為10比maxmemory_samples 設定為5要更加消耗CPU計算時間,因為每次采樣的樣本資料增大,計算時間也會增加,Redis3.0的LRU比Redis2.8的LRU演算法更加準確,是因為Redis3.0增加了一個與maxmemory_samples相同大小的淘汰池,每次淘汰key的時候,先與淘汰池中等待被淘汰的key進行比較,最后淘汰掉最老舊的key,其實就是被選中淘汰的key放到一起再比較一下,淘汰其中最舊的, ?
LRU有一個明顯的缺點,它無法正確的表示一個Key的熱度,如果一個key從未被訪問過,僅僅發生記憶體淘汰的前一會兒被用戶訪問了一下,在LRU演算法中這會被認為是一個熱key,LFU(Least Frequently Used)是Redis 4.0 引入的淘汰演算法,它通過key的訪問頻率比較來淘汰key,重點突出的是Frequently Used, ?
LRU與LFU的區別:
-
LRU -> Recently Used,根據最近一次訪問的時間比較
-
LFU -> Frequently Used,根據key的訪問頻率比較
在LFU模式下,Redis物件頭的24bit lru欄位被分成兩段來存盤,高16bit存盤ldt(Last Decrement Time),低8bit存盤logc(Logistic Counter),高16bit用來記錄最近一次計數器降低的時間,由于只有8bit,存盤的是Unix分鐘時間戳取模2^16,16bit能表示的最大值為65535(65535/24/60≈45.5),大概45.5天會折返(折返指的是取模后的值重新從0開始),低8位用來記錄訪問頻次,8bit能表示的最大值為255,logc肯定無法記錄真實的Rediskey的訪問次數,其實從名字可以看出存盤的是訪問次數的對數值,每個新加入的key的logc初始值為5(LFU_INITI_VAL),這樣可以保證新加入的值不會被首先選中淘汰;logc每次key被訪問時都會更新;此外,logc會隨著時間衰減, Logistic Counter不僅會增長,也會衰弱,增長和衰弱的規則也可以通過redis.conf進行配置,
-
lfu-log-factor 用于調整Logistic Counter的增長速度,lfu-log-factor值越大,Logistic Counter增長越慢,
-
lfu-decay-time 用于調整Logistic Counter的衰減速度,它是一個以分鐘為單位的數值,默認值為1,;lfu-decay-time值越大,衰減越慢,

這個我的理解大致是這樣的面試官!!
快取擊穿: 就是說某個訪問非常頻繁的熱點 key ,處于集中式高并發訪問的情況,當這個 key 在失效的瞬間,大量的請求就擊穿了快取,直接請求資料庫,直接穿過了Redis,
解決方式:
-
若快取的資料比較固定,則可嘗試將該熱點資料設定為永不過期,
-
若快取的資料更新不頻繁,且快取重繪的整個流程耗時較少的情況下,則可以采用基于 Redis、zookeeper 等分布式中間件的分布式互斥鎖,或者本地互斥鎖以保證僅少量的請求能請求資料庫并重新構建快取,其余執行緒則在鎖釋放后能訪問到新快取,
-
若快取的資料更新頻繁或者在快取重繪的流程耗時較長的情況下,可以利用定時執行緒在快取過期前主動地重新構建快取或者延后快取的過期時間,以保證所有的請求能一直訪問到對應的快取,
快取穿透: 指的是快取和資料庫中都不存在的資料被請求,這種情況通常是被黑客攻擊力,如果不做好防御很容易導致資料庫被請求打死,比如黑客使用負數id查詢你的某個表,我們的id通常不會設定為負數,
解決方式:
-
資料庫未查詢到,則在快取中設定一個空值,這種辦法無法解決采用不同負數id請求的情況,
-
使用布隆過濾器,將資料庫中所有的資料映射到布隆過濾器中,請求打過來之前先用布隆過濾器判斷是否存在,不存在直接回傳就行,
關于布隆過濾器可以查看我的Redis專欄中關于該知識點的詳述,面試超級有用的!!!! ?
快取雪崩: 快取雪崩發生在大量快取同時失效的情況,會導致資料庫瞬間崩潰(高并發場景),而且這種情況下如果快取不恢復,資料庫起來也沒用,還是會繼續被打崩,
解決方式:
-
快取架構設計:設計高可用Redis,主從+sentinel,Redis cluster集群
-
專案服務端:使用本地快取和服務降級處理,盡量減少請求打到MySQL
-
運維手段:定期監測Redis集群,做持久化的備份機制,一旦雪崩還能及時恢復快取資料

差不多回答到這里,面試官的臉色露出了久違的微笑,我們接下來只有接住這一招,這次面試就有了, 當然關于這個知識點不是幾句話能說清楚的,所以建議大家看看這篇文章,就可以輕松hold住了 《Redis分布式——主從復制、Sentinel、集群徹底吃透》?
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/317978.html
標籤:其他
