(轉)面試前必知Redis面試題—緩存雪崩+穿透+緩存與數據庫雙寫一致問題

背景:redis問題在面試過程當中常常被問到,對於常見問題必定不能放過。面試

面試前必知Redis面試題—緩存雪崩+穿透+緩存與數據庫雙寫一致問題redis

1、緩存雪崩

1.1什麼是緩存雪崩?

若是緩存數據設置的過時時間是相同的,而且Redis剛好將這部分數據所有刪光了。這就會致使在這段時間內,這些緩存同時失效,所有請求到數據庫中數據庫

這就是緩存雪崩設計模式

  • Redis掛掉了,請求所有走數據庫。緩存

  • 對緩存數據設置相同的過時時間,致使某段時間內緩存失效,請求所有走數據庫。架構

緩存雪崩若是發生了,極可能就把咱們的數據庫搞垮,致使整個服務癱瘓!併發

1.2如何解決緩存雪崩?

對於「對緩存數據設置相同的過時時間,致使某段時間內緩存失效,請求所有走數據庫。」這種狀況,很是好解決:ide

  • 解決方法:在緩存的時候給過時時間加上一個隨機值,這樣就會大幅度的減小緩存在同一時間過時高併發

對於「Redis掛掉了,請求所有走數據庫」這種狀況,咱們能夠有如下的思路:spa

  • 事發前:實現Redis的高可用(主從架構+Sentinel 或者Redis Cluster),儘可能避免Redis掛掉這種狀況發生。

  • 事發中:萬一Redis真的掛了,咱們能夠設置本地緩存(ehcache)+限流(hystrix),儘可能避免咱們的數據庫被幹掉(起碼能保證咱們的服務仍是能正常工做的)

  • 事發後:redis持久化,重啓後自動從磁盤上加載數據,快速恢復緩存數據

2、緩存穿透

2.1什麼是緩存穿透

緩存穿透是指查詢一個必定不存在的數據。因爲緩存不命中,而且出於容錯考慮,若是從數據庫查不到數據則不寫入緩存,這將致使這個不存在的數據每次請求都要到數據庫去查詢,失去了緩存的意義。

這就是緩存穿透

  • 請求的數據在緩存大量不命中,致使請求走數據庫。

緩存穿透若是發生了,也可能把咱們的數據庫搞垮,致使整個服務癱瘓!

2.1如何解決緩存穿透?

解決緩存穿透也有兩種方案:

  • 因爲請求的參數是不合法的(每次都請求不存在的參數),因而咱們可使用布隆過濾器(BloomFilter)或者壓縮filter提早攔截,不合法就不讓這個請求到數據庫層!

  • 當咱們從數據庫找不到的時候,咱們也將這個空對象設置到緩存裏邊去。下次再請求的時候,就能夠從緩存裏邊獲取了。

  • 這種狀況咱們通常會將空對象設置一個較短的過時時間

3、緩存與數據庫雙寫一致

3.1對於讀操做,流程是這樣的

上面講緩存穿透的時候也提到了:若是從數據庫查不到數據則不寫入緩存。

通常咱們對讀操做的時候有這麼一個固定的套路

  • 若是咱們的數據在緩存裏邊有,那麼就直接取緩存的。

  • 若是緩存裏沒有咱們想要的數據,咱們會先去查詢數據庫,而後將數據庫查出來的數據寫到緩存中

  • 最後將數據返回給請求

3.2什麼是緩存與數據庫雙寫一致問題?

若是僅僅查詢的話,緩存的數據和數據庫的數據是沒問題的。可是,當咱們要更新時候呢?各類狀況極可能就形成數據庫和緩存的數據不一致了。

  • 這裏不一致指的是:數據庫的數據跟緩存的數據不一致

刪除緩存失敗的解決思路

  • 將須要刪除的key發送到消息隊列中

  • 本身消費消息,得到須要刪除的key

  • 不斷重試刪除操做,直到成功

3.3.3先刪除緩存,再更新數據庫

正常狀況是這樣的:

  • 先刪除緩存,成功;

  • 再更新數據庫,也成功;

若是原子性被破壞了:

  • 第一步成功(刪除緩存),第二步失敗(更新數據庫),數據庫和緩存的數據仍是一致的。

  • 若是第一步(刪除緩存)就失敗了,咱們能夠直接返回錯誤(Exception),數據庫和緩存的數據仍是一致的。

看起來是很美好,可是咱們在併發場景下分析一下,就知道仍是有問題的了:

  • 線程A刪除了緩存

  • 線程B查詢,發現緩存已不存在

  • 線程B去數據庫查詢獲得舊值

  • 線程B將舊值寫入緩存

  • 線程A將新值寫入數據庫

因此也會致使數據庫和緩存不一致的問題。

併發下解決數據庫與緩存不一致的思路

  • 將刪除緩存、修改數據庫、讀取緩存等的操做積壓到隊列裏邊,實現串行化

3.4對比兩種策略

咱們能夠發現,兩種策略各自有優缺點:

  • 先刪除緩存,再更新數據庫

  • 在高併發下表現不如意,在原子性被破壞時表現優異

  • 先更新數據庫,再刪除緩存(Cache Aside Pattern設計模式)

  • 在高併發下表現優異,在原子性被破壞時表現不如意#總結

相關文章
相關標籤/搜索