Cache Aside Pattern(緩存模式)解析
在《究竟先操作緩存,還是數據庫?》,有同學在評論提出,相關方案違背了“Cache Aside Pattern”的原則,故今天聊一聊Cache Aside Pattern。
另外,在討論技術方案時,盡量不說:
- “你是錯的,應該怎么樣”
- “facebook不是這樣,所以你是錯的”
畫外音:憑什么facebook就是真理?它的方案只是適合它的業務而已。
說明適用場景,說明來龍去脈,說明前因后果,比具體使用什么方案更重要。
什么是“Cache Aside Pattern”?
答:旁路緩存方案的經驗實踐,這個實踐又分讀實踐,寫實踐。
對于讀請求
- 先讀cache,再讀db
- 如果,cache hit,則直接返回數據
- 如果,cache miss,則訪問db,并將數據set回緩存
如上圖:
- 先從cache中嘗試get數據,結果miss了
- 再從db中讀取數據,從庫,讀寫分離
- ***把數據set回cache,方便下次讀***
畫外音:這一點上,與《究竟先操作緩存,還是數據庫?》說的是一致的。
對于寫請求
- 淘汰緩存,而不是更新緩存
- 先操作數據庫,再淘汰緩存
如上圖:
(1)***步要操作數據庫,第二步操作緩存
畫外音:這一點上,與《究竟先操作緩存,還是數據庫?》說的不一致,也是評論反駁比較激烈的地方。
(2)緩存,采用delete淘汰,而不是set更新
畫外音:這一點上,與《緩存,究竟是淘汰,還是修改?》說的是一致的。
Cache Aside Pattern為什么建議淘汰緩存,而不是更新緩存?
答:如果更新緩存,在并發寫時,可能出現數據不一致。
如上圖所示,如果采用set緩存。
在1和2兩個并發寫發生時,由于無法保證時序,此時不管先操作緩存還是先操作數據庫,都可能出現:
- 請求1先操作數據庫,請求2后操作數據庫
- 請求2先set了緩存,請求1后set了緩存
導致,數據庫與緩存之間的數據不一致。
所以,Cache Aside Pattern建議,delete緩存,而不是set緩存。
Cache Aside Pattern為什么建議先操作數據庫,再操作緩存?
答:如果先操作緩存,在讀寫并發時,可能出現數據不一致。
如上圖所示,如果先操作緩存。
在1和2并發讀寫發生時,由于無法保證時序,可能出現:
- 寫請求淘汰了緩存
- 寫請求操作了數據庫(主從同步沒有完成)
- 讀請求讀了緩存(cache miss)
- 讀請求讀了從庫(讀了一個舊數據)
- 讀請求set回緩存(set了一個舊數據)
- 數據庫主從同步完成
導致,數據庫與緩存的數據不一致。
所以,Cache Aside Pattern建議,先操作數據庫,再操作緩存。
Cache Aside Pattern方案存在什么問題?
答:如果先操作數據庫,再淘汰緩存,在原子性被破壞時:
- 修改數據庫成功了
- 淘汰緩存失敗了
導致,數據庫與緩存的數據不一致。
如何解決這類問題呢?
答:詳見《究竟先操作緩存,還是數據庫?》。
【本文為51CTO專欄作者“58沈劍”原創稿件,轉載請聯系原作者】