面試官:3 種緩存更新策略是怎樣的?
優(yōu)采云 發(fā)布時(shí)間: 2022-07-28 00:10面試官:3 種緩存更新策略是怎樣的?
作者丨小林coding
轉載來(lái)源 |小林coding
八股文網(wǎng)站:今天跟大家聊聊,常見(jiàn)的 3 種緩存更新策略。實(shí)際開(kāi)發(fā)中,Redis 和 MySQL 的更新策略用的是 Cache Aside,另外兩種策略主要應用在計算機系統里。
01Cache Aside (旁路緩存)策略Cache Aside(旁路緩存)策略是最常用的,應用程序直接與「數據庫、緩存」交互,并負責對緩存的維護,該策略又可以細分為「讀策略」和「寫(xiě)策略」。
寫(xiě)策略的步驟:讀策略的步驟:注意,寫(xiě)策略的步驟的順序順序不能倒過(guò)來(lái),即不能先刪除緩存再更新數據庫,原因是在「讀+寫(xiě)」并發(fā)的時(shí)候,會(huì )出現緩存和數據庫的數據不一致性的問(wèn)題。舉個(gè)例子,假設某個(gè)用戶(hù)的年齡是 20,請求 A 要更新用戶(hù)年齡為 21,所以它會(huì )刪除緩存中的內容。這時(shí),另一個(gè)請求 B 要讀取這個(gè)用戶(hù)的年齡,它查詢(xún)緩存發(fā)現未命中后,會(huì )從數據庫中讀取到年齡為 20,并且寫(xiě)入到緩存中,然后請求 A 繼續更改數據庫,將用戶(hù)的年齡更新為 21。
最終,該用戶(hù)年齡在緩存中是 20(舊值),在數據庫中是 21(新值),緩存和數據庫的數據不一致。為什么「先更新數據庫再刪除緩存」不會(huì )有數據不一致的問(wèn)題?繼續用「讀 + 寫(xiě)」請求的并發(fā)的場(chǎng)景來(lái)分析。假如某個(gè)用戶(hù)數據在緩存中不存在,請求 A 讀取數據時(shí)從數據庫中查詢(xún)到年齡為 20,在未寫(xiě)入緩存中時(shí)另一個(gè)請求 B 更新數據。它更新數據庫中的年齡為 21,并且清空緩存。這時(shí)請求 A 把從數據庫中讀到的年齡為 20 的數據寫(xiě)入到緩存中。
最終,該用戶(hù)年齡在緩存中是 20(舊值),在數據庫中是 21(新值),緩存和數據庫數據不一致。從上面的理論上分析,先更新數據庫,再刪除緩存也是會(huì )出現數據不一致性的問(wèn)題,但是在實(shí)際中,這個(gè)問(wèn)題出現的概率并不高。因為緩存的寫(xiě)入通常要遠遠快于數據庫的寫(xiě)入,所以在實(shí)際中很難出現請求 B 已經(jīng)更新了數據庫并且刪除了緩存,請求 A 才更新完緩存的情況。而一旦請求 A 早于請求 B 刪除緩存之前更新了緩存,那么接下來(lái)的請求就會(huì )因為緩存不命中而從數據庫中重新讀取數據,所以不會(huì )出現這種不一致的情況。Cache Aside 策略適合讀多寫(xiě)少的場(chǎng)景,不適合寫(xiě)多的場(chǎng)景,因為當寫(xiě)入比較頻繁時(shí),緩存中的數據會(huì )被頻繁地清理,這樣會(huì )對緩存的命中率有一些影響。如果業(yè)務(wù)對緩存命中率有嚴格的要求,那么可以考慮兩種解決方案:
02Read/Write Through(讀穿/寫(xiě)穿)策略Read/Write Through(讀穿 / 寫(xiě)穿)策略原則是應用程序只和緩存交互,不再和數據庫交互,而是由緩存和數據庫交互,相當于更新數據庫的操作由緩存自己代理了。Read Through 策略先查詢(xún)緩存中數據是否存在,如果存在則直接返回,如果不存在,則由緩存組件負責從數據庫查詢(xún)數據,并將結果寫(xiě)入到緩存組件,最后緩存組件將數據返回給應用。Write Through 策略當有數據更新的時(shí)候,先查詢(xún)要寫(xiě)入的數據在緩存中是否已經(jīng)存在:下面是 Read Through/Write Through 策略的*敏*感*詞*:
Read Through/Write Through 策略的特點(diǎn)是由緩存節點(diǎn)而非應用程序來(lái)和數據庫打交道,在我們開(kāi)發(fā)過(guò)程中相比 Cache Aside 策略要少見(jiàn)一些,原因是我們經(jīng)常使用的分布式緩存組件,無(wú)論是 Memcached 還是 Redis 都不提供寫(xiě)入數據庫和自動(dòng)加載數據庫中的數據的功能。而我們在使用本地緩存的時(shí)候可以考慮使用這種策略。
03Write Back(寫(xiě)回)策略Write Back(寫(xiě)回)策略在更新數據的時(shí)候,只更新緩存,同時(shí)將緩存數據設置為臟的,然后立馬返回,并不會(huì )更新數據庫。對于數據庫的更新,會(huì )通過(guò)批量異步更新的方式進(jìn)行。實(shí)際上,Write Back(寫(xiě)回)策略也不能應用到我們常用的數據庫和緩存的場(chǎng)景中,因為 Redis 并沒(méi)有異步更新數據庫的功能。Write Back 是計算機體系結構中的設計,比如 CPU 的緩存、操作系統中文件系統的緩存都采用了 Write Back(寫(xiě)回)策略。Write Back 策略特別適合寫(xiě)多的場(chǎng)景,因為發(fā)生寫(xiě)操作的時(shí)候, 只需要更新緩存,就立馬返回了。比如,寫(xiě)文件的時(shí)候,實(shí)際上是寫(xiě)入到文件系統的緩存就返回了,并不會(huì )寫(xiě)磁盤(pán)。但是帶來(lái)的問(wèn)題是,數據不是強一致性的,而且會(huì )有數據丟失的風(fēng)險,因為緩存一般使用內存,而內存是非持久化的,所以一旦緩存機器掉電,就會(huì )造成原本緩存中的臟數據丟失。所以你會(huì )發(fā)現系統在掉電之后,之前寫(xiě)入的文件會(huì )有部分丟失,就是因為 Page Cache 還沒(méi)有來(lái)得及刷盤(pán)造成的。這里貼一張 CPU 緩存與內存使用 Write Back 策略的流程圖:
好啦,今天的內容分享就到這,感覺(jué)不錯的同學(xué)記得分享點(diǎn)贊哦!<br />PS:工作日早?8:30,CSDN 企業(yè)招聘?持續分享程序員學(xué)習、面試相關(guān)干貨,不見(jiàn)不散!<br />點(diǎn)分享點(diǎn)收藏點(diǎn)點(diǎn)贊點(diǎn)在看