這幾道Redis面試題都不懂,offer肯定與你擦肩而過
今天來分享一下Redis幾道常見的面試題:
如何解決快取雪崩?
如何解決快取穿透?
如何保證快取與資料庫雙寫時一致的問題?
一、快取雪崩
1.1什麼是快取雪崩?
回顧一下我們為什麼要用快取(Redis):
現在有個問題,如果我們的快取掛掉了,這意味著我們的全部請求都跑去資料庫了。
在前面學習我們都知道Redis不可能把所有的資料都快取起來(記憶體昂貴且有限),所以Redis需要對資料設定過期時間,並採用的是惰性刪除+定期刪除兩種策略對過期鍵刪除。
如果快取資料設定的過期時間是相同的,並且Redis恰好將這部分資料全部刪光了。這就會導致在這段時間內,這些快取同時失效,全部請求到資料庫中。
這就是快取雪崩:
Redis掛掉了,請求全部走資料庫。
對快取資料設定相同的過期時間,導致某段時間內快取失效,請求全部走資料庫。
快取雪崩如果發生了,很可能就把我們的資料庫搞垮,導致整個服務癱瘓!
1.2如何解決快取雪崩?
對於“對快取資料設定相同的過期時間,導致某段時間內快取失效,請求全部走資料庫。”這種情況,非常好解決:
解決方法:在快取的時候給過期時間加上一個隨機值,這樣就會大幅度的減少快取在同一時間過期。
對於“Redis掛掉了,請求全部走資料庫”這種情況,我們可以有以下的思路:
事發前:實現Redis的高可用(主從架構+Sentinel 或者Redis Cluster),儘量避免Redis掛掉這種情況發生。
事發中:萬一Redis真的掛了,我們可以設定本地快取(ehcache)+限流(hystrix),儘量避免我們的資料庫被幹掉(起碼能保證我們的服務還是能正常工作的)
事發後:redis持久化,重啟後自動從磁碟上載入資料,快速恢復快取資料。
二、快取穿透
2.1什麼是快取穿透?
比如,我們有一張資料庫表,ID都是從1開始的(正數):
但是可能有駭客想把我的資料庫搞垮,每次請求的ID都是負數。這會導致我的快取就沒用了,請求全部都找資料庫去了,但資料庫也沒有這個值啊,所以每次都返回空出去。
快取穿透是指查詢一個一定不存在的資料。由於快取不命中,並且出於容錯考慮,如果從資料庫查不到資料則不寫入快取,這將導致這個不存在的資料每次請求都要到資料庫去查詢,失去了快取的意義。
這就是快取穿透:
請求的資料在快取大量不命中,導致請求走資料庫。
快取穿透如果發生了,也可能把我們的資料庫搞垮,導致整個服務癱瘓!
2.1如何解決快取穿透?
解決快取穿透也有兩種方案:
由於請求的引數是不合法的(每次都請求不存在的引數),於是我們可以使用布隆過濾器(BloomFilter)或者壓縮filter提前攔截,不合法就不讓這個請求到資料庫層!
當我們從資料庫找不到的時候,我們也將這個空物件設定到快取裡邊去。下次再請求的時候,就可以從快取裡邊獲取了。
這種情況我們一般會將空物件設定一個較短的過期時間。
三、快取與資料庫雙寫一致
3.1對於讀操作,流程是這樣的
上面講快取穿透的時候也提到了:如果從資料庫查不到資料則不寫入快取。
一般我們對讀操作的時候有這麼一個固定的套路:
如果我們的資料在快取裡邊有,那麼就直接取快取的。
如果快取裡沒有我們想要的資料,我們會先去查詢資料庫,然後將資料庫查出來的資料寫到快取中。
最後將資料返回給請求
3.2什麼是快取與資料庫雙寫一致問題?
如果僅僅查詢的話,快取的資料和資料庫的資料是沒問題的。但是,當我們要更新時候呢?各種情況很可能就造成資料庫和快取的資料不一致了。
這裡不一致指的是:資料庫的資料跟快取的資料不一致
從理論上說,只要我們設定了鍵的過期時間,我們就能保證快取和資料庫的資料最終是一致的。因為只要快取資料過期了,就會被刪除。隨後讀的時候,因為快取裡沒有,就可以查資料庫的資料,然後將資料庫查出來的資料寫入到快取中。順便在此給大家推薦一個Java架構方面的交流學習群:834962734,群裡有(分散式架構、高可擴充套件、高效能、高併發、效能最佳化、Spring boot、Redis、ActiveMQ、等學習資源)進群免費送給每一位Java小夥伴,不管你是轉行,還是工作中想提升自己能力都可以,歡迎進群一起深入交流學習!
除了設定過期時間,我們還需要做更多的措施來儘量避免資料庫與快取處於不一致的情況發生。
3.3對於更新操作
一般來說,執行更新操作時,我們會有兩種選擇:
先運算元據庫,再操作快取
先操作快取,再運算元據庫
首先,要明確的是,無論我們選擇哪個,我們都希望這兩個操作要麼同時成功,要麼同時失敗。所以,這會演變成一個分散式事務的問題。
所以,如果原子性被破壞了,可能會有以下的情況:
運算元據庫成功了,操作快取失敗了。
操作快取成功了,運算元據庫失敗了。
如果第一步已經失敗了,我們直接返回Exception出去就好了,第二步根本不會執行。
下面我們具體來分析一下吧。
3.3.1操作快取
操作快取也有兩種方案:
更新快取
刪除快取
一般我們都是採取刪除快取快取策略的,原因如下:
高併發環境下,無論是先運算元據庫還是後運算元據庫而言,如果加上更新快取,那就更加容易導致資料庫與快取資料不一致問題。(刪除快取直接和簡單很多)
如果每次更新了資料庫,都要更新快取【這裡指的是頻繁更新的場景,這會耗費一定的效能】,倒不如直接刪除掉。等再次讀取時,快取裡沒有,那我到資料庫找,在資料庫找到再寫到快取裡邊(體現懶載入)
基於這兩點,對於快取在更新時而言,都是建議執行刪除操作!
3.3.2先更新資料庫,再刪除快取
正常的情況是這樣的:
先運算元據庫,成功;
再刪除快取,也成功;
如果原子性被破壞了:
第一步成功(運算元據庫),第二步失敗(刪除快取),會導致資料庫裡是新資料,而快取裡是舊資料。
如果第一步(運算元據庫)就失敗了,我們可以直接返回錯誤(Exception),不會出現資料不一致。
如果在高併發的場景下,出現資料庫與快取資料不一致的機率特別低,也不是沒有:
快取剛好失效
執行緒A查詢資料庫,得一箇舊值
執行緒B將新值寫入資料庫
執行緒B刪除快取
執行緒A將查到的舊值寫入快取
要達成上述情況,還是說一句機率特別低:
因為這個條件需要發生在讀快取時快取失效,而且併發著有一個寫操作。而實際上資料庫的寫操作會比讀操作慢得多,而且還要鎖表,而讀操作必需在寫操作前進入資料庫操作,而又要晚於寫操作更新快取,所有的這些條件都具備的機率基本並不大。
對於這種策略,其實是一種設計模式:Cache Aside Pattern
刪除快取失敗的解決思路:
將需要刪除的key傳送到訊息佇列中
自己消費訊息,獲得需要刪除的key
不斷重試刪除操作,直到成功
3.3.3先刪除快取,再更新資料庫
正常情況是這樣的:
先刪除快取,成功;
再更新資料庫,也成功;
如果原子性被破壞了:
第一步成功(刪除快取),第二步失敗(更新資料庫),資料庫和快取的資料還是一致的。
如果第一步(刪除快取)就失敗了,我們可以直接返回錯誤(Exception),資料庫和快取的資料還是一致的。
看起來是很美好,但是我們在併發場景下分析一下,就知道還是有問題的了:
執行緒A刪除了快取
執行緒B查詢,發現快取已不存在
執行緒B去資料庫查詢得到舊值
執行緒B將舊值寫入快取
執行緒A將新值寫入資料庫
所以也會導致資料庫和快取不一致的問題。
併發下解決資料庫與快取不一致的思路:
將刪除快取、修改資料庫、讀取快取等的操作積壓到佇列裡邊,實現序列化。
3.4對比兩種策略
我們可以發現,兩種策略各自有優缺點:
先刪除快取,再更新資料庫
在高併發下表現不如意,在原子性被破壞時表現優異
先更新資料庫,再刪除快取(Cache Aside Pattern設計模式)
在高併發下表現優異,在原子性被破壞時表現不如意
3.5其他保障資料一致的方案與資料
可以用databus或者阿里的canal監聽binlog進行更新。
最後
這是幾道Redis常見的面試題,希望大家看完有所幫助,順利拿到offer!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31545684/viewspace-2650292/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【Java】幾道讓你拿offer的面試題Java面試題
- 熟悉這幾道 Redis 高頻面試題,面試不用愁Redis面試題
- 27道Redis精選面試題,你會做幾題?Redis面試題
- 這是道面試題,想不懂,請教大家面試題
- 面試還搞不懂redis,快看看這40道面試題(含答案和思維導圖)Redis面試題
- 如果這10道關於資料庫的測試題你都會,面試必過!資料庫面試
- 速看!這8道嵌入式面試題你都會嗎?面試題
- 這些js原型及原型鏈面試題你能做對幾道JS原型面試題
- 這幾道Java集合框架面試題在面試中幾乎必問Java框架面試題
- 分享30道Redis面試題,面試官能問到的我都找到了Redis面試題
- 邦芒面試:這10個問題都答不上來,你還想透過面試?面試
- iOS開發面試的43道最新面試題,讓你穩拿大廠offer!iOS面試題
- 10道Linux常見面試題,你知道幾個?Linux面試題
- 75 道 BAJT 高階 Java 面試題,你能答上幾道?Java面試題
- 75 道 BAJT 中高階 Java 面試題,你能答上幾道?Java面試題
- 求助,這幾道面試題有些我回答不出來了面試題
- 學習Python這些面試題你都知道嗎?Python面試題
- 這些年背過的面試題——Redis篇面試題Redis
- 3道常見的vue面試題,你都會了嗎?Vue面試題
- 面試中的這些坑,你踩過幾個?面試
- 面試現場簡單幾道java演算法題, 你能寫出幾道?面試Java演算法
- 最全的50道Redis面試題Redis面試題
- 40道 Redis 運維面試題Redis運維面試題
- 吐血整理Redis面試題66道Redis面試題
- 10道網路安全基礎面試題,你答對了幾道?面試題
- 又面試了Python爬蟲工程師,碰到這麼幾道面試題,Python面試題No9Python爬蟲工程師面試題
- 2019年Spring Boot面試都問了什麼?快看看這22道面試題!Spring Boot面試題
- 不懂Spring別說你會Java,Spring系列最全 66 道 面試題(含答案)SpringJava面試題
- 面試現場:這些常問的面試題你都會了嗎面試題
- 「劍指offer」27道Mybatis面試題含解析MyBatis面試題
- 10道Python基礎面試題附答案,你都掌握了嗎?Python面試題
- 談談OKHttp的幾道面試題HTTP面試題
- 面試10家拿到7家offer 我都遇到了哪些面試題面試題
- 【面試篇】金九銀十面試季,這些面試題你都會了嗎?面試題
- 你會這道阿里多執行緒面試題嗎?阿里執行緒面試題
- 週三面試Python開發,這幾道Python面試題差點答錯,Python面試題No7Python面試題
- 你可能也罵過這兩個面試題!面試題
- 每天10道Java面試題,跟我走,offer有!Java面試題