国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

緩存雪崩、緩存穿透、緩存更新了解多少?

CNZPH / 1994人閱讀

摘要:緩存穿透是指查詢一個一定不存在的數(shù)據(jù)。這就是緩存穿透請求的數(shù)據(jù)在緩存大量不命中,導致請求走數(shù)據(jù)庫。并發(fā)下解決數(shù)據(jù)庫與緩存不一致的思路將刪除緩存修改數(shù)據(jù)庫讀取緩存等的操作積壓到隊列里邊,實現(xiàn)串行化。

前言
只有光頭才能變強。
文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3y

回顧前面:

從零單排學Redis【青銅】

從零單排學Redis【白銀】

從零單排學Redis【黃金】

從零單排學Redis【鉑金一】

從零單排學Redis【鉑金二】

今天來分享一下Redis幾道常見的面試題:

如何解決緩存雪崩?

如何解決緩存穿透?

如何保證緩存與數(shù)據(jù)庫雙寫時一致的問題?

一、緩存雪崩 1.1什么是緩存雪崩?

回顧一下我們?yōu)槭裁匆镁彺?Redis):

現(xiàn)在有個問題,如果我們的緩存掛掉了,這意味著我們的全部請求都跑去數(shù)據(jù)庫了

在前面學習我們都知道Redis不可能把所有的數(shù)據(jù)都緩存起來(內(nèi)存昂貴且有限),所以Redis需要對數(shù)據(jù)設置過期時間,并采用的是惰性刪除+定期刪除兩種策略對過期鍵刪除。Redis對過期鍵的策略+持久化

如果緩存數(shù)據(jù)設置的過期時間是相同的,并且Redis恰好將這部分數(shù)據(jù)全部刪光了。這就會導致在這段時間內(nèi),這些緩存同時失效,全部請求到數(shù)據(jù)庫中。

這就是緩存雪崩

Redis掛掉了,請求全部走數(shù)據(jù)庫。

對緩存數(shù)據(jù)設置相同的過期時間,導致某段時間內(nèi)緩存失效,請求全部走數(shù)據(jù)庫。

緩存雪崩如果發(fā)生了,很可能就把我們的數(shù)據(jù)庫搞垮,導致整個服務癱瘓!

1.2如何解決緩存雪崩?

對于“對緩存數(shù)據(jù)設置相同的過期時間,導致某段時間內(nèi)緩存失效,請求全部走數(shù)據(jù)庫。”這種情況,非常好解決:

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

對于“Redis掛掉了,請求全部走數(shù)據(jù)庫”這種情況,我們可以有以下的思路:

事發(fā)前:實現(xiàn)Redis的高可用(主從架構(gòu)+Sentinel 或者Redis Cluster),盡量避免Redis掛掉這種情況發(fā)生。

事發(fā)中:萬一Redis真的掛了,我們可以設置本地緩存(ehcache)+限流(hystrix),盡量避免我們的數(shù)據(jù)庫被干掉(起碼能保證我們的服務還是能正常工作的)

事發(fā)后:redis持久化,重啟后自動從磁盤上加載數(shù)據(jù),快速恢復緩存數(shù)據(jù)

二、緩存穿透 2.1什么是緩存穿透

比如,我們有一張數(shù)據(jù)庫表,ID都是從1開始的(正數(shù)):

但是可能有黑客想把我的數(shù)據(jù)庫搞垮,每次請求的ID都是負數(shù)。這會導致我的緩存就沒用了,請求全部都找數(shù)據(jù)庫去了,但數(shù)據(jù)庫也沒有這個值啊,所以每次都返回空出去。

緩存穿透是指查詢一個一定不存在的數(shù)據(jù)。由于緩存不命中,并且出于容錯考慮,如果從數(shù)據(jù)庫查不到數(shù)據(jù)則不寫入緩存,這將導致這個不存在的數(shù)據(jù)每次請求都要到數(shù)據(jù)庫去查詢,失去了緩存的意義。

這就是緩存穿透

請求的數(shù)據(jù)在緩存大量不命中,導致請求走數(shù)據(jù)庫。

緩存穿透如果發(fā)生了,也可能把我們的數(shù)據(jù)庫搞垮,導致整個服務癱瘓!

2.1如何解決緩存穿透?

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

由于請求的參數(shù)是不合法的(每次都請求不存在的參數(shù)),于是我們可以使用布隆過濾器(BloomFilter)或者壓縮filter提前攔截,不合法就不讓這個請求到數(shù)據(jù)庫層!

當我們從數(shù)據(jù)庫找不到的時候,我們也將這個空對象設置到緩存里邊去。下次再請求的時候,就可以從緩存里邊獲取了。

這種情況我們一般會將空對象設置一個較短的過期時間

參考資料:

緩存系列文章--5.緩存穿透問題

https://carlosfu.iteye.com/blog/2248185

三、緩存與數(shù)據(jù)庫雙寫一致 3.1對于讀操作,流程是這樣的

上面講緩存穿透的時候也提到了:如果從數(shù)據(jù)庫查不到數(shù)據(jù)則不寫入緩存。

一般我們對讀操作的時候有這么一個固定的套路

如果我們的數(shù)據(jù)在緩存里邊有,那么就直接取緩存的。

如果緩存里沒有我們想要的數(shù)據(jù),我們會先去查詢數(shù)據(jù)庫,然后將數(shù)據(jù)庫查出來的數(shù)據(jù)寫到緩存中

最后將數(shù)據(jù)返回給請求

3.2什么是緩存與數(shù)據(jù)庫雙寫一致問題?

如果僅僅查詢的話,緩存的數(shù)據(jù)和數(shù)據(jù)庫的數(shù)據(jù)是沒問題的。但是,當我們要更新時候呢?各種情況很可能就造成數(shù)據(jù)庫和緩存的數(shù)據(jù)不一致了。

這里不一致指的是:數(shù)據(jù)庫的數(shù)據(jù)跟緩存的數(shù)據(jù)不一致

從理論上說,只要我們設置了鍵的過期時間,我們就能保證緩存和數(shù)據(jù)庫的數(shù)據(jù)最終是一致的。因為只要緩存數(shù)據(jù)過期了,就會被刪除。隨后讀的時候,因為緩存里沒有,就可以查數(shù)據(jù)庫的數(shù)據(jù),然后將數(shù)據(jù)庫查出來的數(shù)據(jù)寫入到緩存中。

除了設置過期時間,我們還需要做更多的措施來盡量避免數(shù)據(jù)庫與緩存處于不一致的情況發(fā)生。

3.3對于更新操作

一般來說,執(zhí)行更新操作時,我們會有兩種選擇:

先操作數(shù)據(jù)庫,再操作緩存

先操作緩存,再操作數(shù)據(jù)庫

首先,要明確的是,無論我們選擇哪個,我們都希望這兩個操作要么同時成功,要么同時失敗。所以,這會演變成一個分布式事務的問題。

所以,如果原子性被破壞了,可能會有以下的情況:

操作數(shù)據(jù)庫成功了,操作緩存失敗了

操作緩存成功了,操作數(shù)據(jù)庫失敗了

如果第一步已經(jīng)失敗了,我們直接返回Exception出去就好了,第二步根本不會執(zhí)行。

下面我們具體來分析一下吧。

3.3.1操作緩存

操作緩存也有兩種方案:

更新緩存

刪除緩存

一般我們都是采取刪除緩存緩存策略的,原因如下:

高并發(fā)環(huán)境下,無論是先操作數(shù)據(jù)庫還是后操作數(shù)據(jù)庫而言,如果加上更新緩存,那就更加容易導致數(shù)據(jù)庫與緩存數(shù)據(jù)不一致問題。(刪除緩存直接和簡單很多)

如果每次更新了數(shù)據(jù)庫,都要更新緩存【這里指的是頻繁更新的場景,這會耗費一定的性能】,倒不如直接刪除掉。等再次讀取時,緩存里沒有,那我到數(shù)據(jù)庫找,在數(shù)據(jù)庫找到再寫到緩存里邊(體現(xiàn)懶加載)

基于這兩點,對于緩存在更新時而言,都是建議執(zhí)行刪除操作!

3.3.2先更新數(shù)據(jù)庫,再刪除緩存

正常的情況是這樣的:

先操作數(shù)據(jù)庫,成功;

再刪除緩存,也成功;

如果原子性被破壞了:

第一步成功(操作數(shù)據(jù)庫),第二步失敗(刪除緩存),會導致數(shù)據(jù)庫里是新數(shù)據(jù),而緩存里是舊數(shù)據(jù)

如果第一步(操作數(shù)據(jù)庫)就失敗了,我們可以直接返回錯誤(Exception),不會出現(xiàn)數(shù)據(jù)不一致。

如果在高并發(fā)的場景下,出現(xiàn)數(shù)據(jù)庫與緩存數(shù)據(jù)不一致的概率特別低,也不是沒有:

緩存剛好失效

線程A查詢數(shù)據(jù)庫,得一個舊值

線程B將新值寫入數(shù)據(jù)庫

線程B刪除緩存

線程A將查到的舊值寫入緩存

要達成上述情況,還是說一句概率特別低

因為這個條件需要發(fā)生在讀緩存時緩存失效,而且并發(fā)著有一個寫操作。而實際上數(shù)據(jù)庫的寫操作會比讀操作慢得多,而且還要鎖表,而讀操作必需在寫操作前進入數(shù)據(jù)庫操作,而又要晚于寫操作更新緩存,所有的這些條件都具備的概率基本并不大。

對于這種策略,其實是一種設計模式:Cache Aside Pattern

刪除緩存失敗的解決思路

將需要刪除的key發(fā)送到消息隊列中

自己消費消息,獲得需要刪除的key

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

3.3.3先刪除緩存,再更新數(shù)據(jù)庫

正常情況是這樣的:

先刪除緩存,成功;

再更新數(shù)據(jù)庫,也成功;

如果原子性被破壞了:

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

如果第一步(刪除緩存)就失敗了,我們可以直接返回錯誤(Exception),數(shù)據(jù)庫和緩存的數(shù)據(jù)還是一致的。

看起來是很美好,但是我們在并發(fā)場景下分析一下,就知道還是有問題的了:

線程A刪除了緩存

線程B查詢,發(fā)現(xiàn)緩存已不存在

線程B去數(shù)據(jù)庫查詢得到舊值

線程B將舊值寫入緩存

線程A將新值寫入數(shù)據(jù)庫

所以也會導致數(shù)據(jù)庫和緩存不一致的問題。

并發(fā)下解決數(shù)據(jù)庫與緩存不一致的思路

將刪除緩存、修改數(shù)據(jù)庫、讀取緩存等的操作積壓到隊列里邊,實現(xiàn)串行化

3.4對比兩種策略

我們可以發(fā)現(xiàn),兩種策略各自有優(yōu)缺點:

先刪除緩存,再更新數(shù)據(jù)庫

在高并發(fā)下表現(xiàn)不如意,在原子性被破壞時表現(xiàn)優(yōu)異

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

在高并發(fā)下表現(xiàn)優(yōu)異,在原子性被破壞時表現(xiàn)不如意

3.5其他保障數(shù)據(jù)一致的方案與資料

可以用databus或者阿里的canal監(jiān)聽binlog進行更新。

參考資料:

緩存更新的套路

https://coolshell.cn/articles/17416.html

如何保證緩存與數(shù)據(jù)庫雙寫時的數(shù)據(jù)一致性?

https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/redis-consistence.md

分布式之數(shù)據(jù)庫和緩存雙寫一致性方案解析

https://zhuanlan.zhihu.com/p/48334686

Cache Aside Pattern

https://blog.csdn.net/z50l2o08e2u4aftor9a/article/details/81008933

最后

這是幾道Redis常見的面試題,希望大家看完有所幫助,順利拿到offer!

樂于輸出干貨的Java技術公眾號:Java3y。200多篇原創(chuàng)技術文章、海量視頻資源、精美腦圖!

精彩回顧:

為什么需要Docker?

覺得我的文章寫得不錯,不妨點一下

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/72990.html

相關文章

  • 分布式系統(tǒng)關注點(18)——「緩存穿透」和「緩存雪崩」到底啥區(qū)別?

    摘要:不過,布隆過濾器有一個最大的缺點,也是其為了高效利用內(nèi)存而付出的代價,就是無法確保的準確率。不過這種方式的優(yōu)勢是前面提到的,不會出現(xiàn)誤差,而布隆過濾器的錯誤率會隨著位數(shù)的增加而減少,會不斷趨近于,但不會為。 ?如果第二次看到我的文章,歡迎文末掃碼訂閱我個人的公眾號(跨界架構(gòu)師)喲~ 本文長度為2805字,建議閱讀8分鐘。堅持原創(chuàng),每一篇都是用心之作~ 有句話說得好,欲要使其毀滅,先要...

    tinyq 評論0 收藏0
  • 緩存穿透雪崩、熱點與Redis

    摘要:關于緩存熱點重建原文說到在緩存失效的瞬間,有大量線程來重建緩存,造成后端負載加大,甚至可能會讓應用崩潰,并給出互斥鎖和永遠不過期兩種候選方案。即使繞過互斥鎖,也不會產(chǎn)生什么不好的后果,因為更新緩存是一個冪等操作。 向大家推薦這篇文章——Redis架構(gòu)之防雪崩設計:網(wǎng)站不宕機背后的兵法 (另外推薦我去年的短文作為餐前點心——略談服務端緩存設計) 《Redis架構(gòu)之防雪崩設計》這篇文章(下...

    oujie 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<