推薦??:接近100K star 的Java學習/面試指南:JavaGuide
看到很多小伙伴簡歷上寫了“熟練使用快取”,但是被我問到“快取常用的3種讀寫策略”的時候卻一臉懵逼,
在我看來,造成這個問題的原因是我們在學習 Redis 的時候,可能只是簡單了寫一些 Demo,并沒有去關注快取的讀寫策略,或者說壓根不知道這回事,
但是,搞懂3種常見的快取讀寫策略對于實際作業中使用快取以及面試中被問到快取都是非常有幫助的!
下面我會簡單介紹一下自己對于這 3 種快取讀寫策略的理解,
另外,這3 種快取讀寫策略各有優劣,不存在最佳,需要我們根據具體的業務場景選擇更適合的,
個人能力有限,如果文章有任何需要補充/完善/修改的地方,歡迎在評論區指出,共同進步!——愛你們的 Guide 哥
Cache Aside Pattern(旁路快取模式)
Cache Aside Pattern 是我們平時使用比較多的一個快取讀寫模式,比較適合讀請求比較多的場景,
Cache Aside Pattern 中服務端需要同時維系 DB 和 cache,并且是以 DB 的結果為準,
下面我們來看一下這個策略模式下的快取讀寫步驟,
寫 :
- 先更新 DB
- 然后直接洗掉 cache ,
簡單畫了一張圖幫助大家理解寫的步驟,

讀 :
- 從 cache 中讀取資料,讀取到就直接回傳
- cache中讀取不到的話,就從 DB 中讀取資料回傳
- 再把資料放到 cache 中,
簡單畫了一張圖幫助大家理解讀的步驟,

你僅僅了解了上面這些內容的話是遠遠不夠的,我們還要搞懂其中的原理,
比如說面試官很可能會追問:“在寫資料的程序中,可以先洗掉 cache ,后更新 DB 么?”
答案: 那肯定是不行的!因為這樣可能會造成資料庫(DB)和快取(Cache)資料不一致的問題,為什么呢?比如說請求1 先寫資料A,請求2隨后讀資料A的話就很有可能產生資料不一致性的問題,這個程序可以簡單描述為:
請求1先把cache中的A資料洗掉 -> 請求2從DB中讀取資料->請求1再把DB中的A資料更新,
當你這樣回答之后,面試官可能會緊接著就追問:“在寫資料的程序中,先更新DB,后洗掉cache就沒有問題了么?”
答案: 理論上來說還是可能會出現資料不一致性的問題,不過概率非常小,因為快取的寫入速度是比資料庫的寫入速度快很多!
比如請求1先讀資料 A,請求2隨后寫資料A,并且資料A不在快取中的話也有可能產生資料不一致性的問題,這個程序可以簡單描述為:
請求1從DB讀資料A->請求2寫更新資料 A 到資料庫并把洗掉cache中的A資料->請求1將資料A寫入cache,
現在我們再來分析一下 Cache Aside Pattern 的缺陷,
缺陷1:首次請求資料一定不在 cache 的問題
解決辦法:可以將熱點資料可以提前放入cache 中,
缺陷2:寫操作比較頻繁的話導致cache中的資料會被頻繁被洗掉,這樣會影響快取命中率 ,
解決辦法:
- 資料庫和快取資料強一致場景 :更新DB的時候同樣更新cache,不過我們需要加一個鎖/分布式鎖來保證更新cache的時候不存在執行緒安全問題,
- 可以短暫地允許資料庫和快取資料不一致的場景 :更新DB的時候同樣更新cache,但是給快取加一個比較短的過期時間,這樣的話就可以保證即使資料不一致的話影響也比較小,
Read/Write Through Pattern(讀寫穿透)
Read/Write Through Pattern 中服務端把 cache 視為主要資料存盤,從中讀取資料并將資料寫入其中,cache 服務負責將此資料讀取和寫入 DB,從而減輕了應用程式的職責,
這種快取讀寫策略小伙伴們應該也發現了在平時在開發程序中非常少見,拋去性能方面的影響,大概率是因為我們經常使用的分布式快取 Redis 并沒有提供 cache 將資料寫入DB的功能,
寫(Write Through):
- 先查 cache,cache 中不存在,直接更新 DB,
- cache 中存在,則先更新 cache,然后 cache 服務自己更新 DB(同步更新 cache 和 DB),
簡單畫了一張圖幫助大家理解寫的步驟,

讀(Read Through):
- 從 cache 中讀取資料,讀取到就直接回傳 ,
- 讀取不到的話,先從 DB 加載,寫入到 cache 后回傳回應,
簡單畫了一張圖幫助大家理解讀的步驟,

Read-Through Pattern 實際只是在 Cache-Aside Pattern 之上進行了封裝,在 Cache-Aside Pattern 下,發生讀請求的時候,如果 cache 中不存在對應的資料,是由客戶端自己負責把資料寫入 cache,而 Read Through Pattern 則是 cache 服務自己來寫入快取的,這對客戶端是透明的,
和 Cache Aside Pattern 一樣, Read-Through Pattern 也有首次請求資料一定不再 cache 的問題,對于熱點資料可以提前放入快取中,
Write Behind Pattern(異步快取寫入)
Write Behind Pattern 和 Read/Write Through Pattern 很相似,兩者都是由 cache 服務來負責 cache 和 DB 的讀寫,
但是,兩個又有很大的不同:Read/Write Through 是同步更新 cache 和 DB,而 Write Behind Caching 則是只更新快取,不直接更新 DB,而是改為異步批量的方式來更新 DB,
很明顯,這種方式對資料一致性帶來了更大的挑戰,比如cache資料可能還沒異步更新DB的話,cache服務可能就就掛掉了,
這種策略在我們平時開發程序中也非常非常少見,但是不代表它的應用場景少,比如訊息佇列中訊息的異步寫入磁盤、MySQL 的 InnoDB Buffer Pool 機制都用到了這種策略,
Write Behind Pattern 下 DB 的寫性能非常高,非常適合一些資料經常變化又對資料一致性要求沒那么高的場景,比如瀏覽量、點贊量,
我的Github地址:Snailclimb - Overview

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/236898.html
標籤:Java
