緩存存儲,也是資料的備援。
(1)資料庫通路資料,磁盤IO,慢;
(2)緩存裡通路資料,存操作,快;
(3)資料庫裡的熱資料,可在緩存備援一份;
(4)先通路緩存,如果命中,能大大的提升通路速度,降低資料庫壓力;
這些,是緩存的核心讀加速原理。
但是,一旦沒有命中緩存,或者一旦涉及寫操作,流程會比沒有緩存更加複雜,這些是今天要分享的話題。
讀操作,如果沒有命中緩存,流程是怎麼樣的?
答:如下圖所示
(1)嘗試從緩存get資料,結果沒有命中;
(2)從資料庫擷取資料,讀從庫,讀寫分離;
(3)把資料set到緩存,未來能夠命中緩存;
讀操作的流程應該沒有歧義。
寫操作,流程是怎麼樣的?
答:寫操作,既要操作資料庫中的資料,又要操作緩存裡的資料。
這裡,有兩個方案:
(1)先操作資料庫,再操作緩存;
(2)先操作緩存,再操作資料庫;
并且,希望保證兩個操作的原子性,要麼同時成功,要麼同時失敗。
這演變為一個分布式事務的問題,保證原子性十分困難,很有可能出現一半成功,一半失敗,接下來看下,當原子性被破壞的時候,分别會發生什麼。
一、先操作資料庫,再操作緩存
如上圖,正常情況下:
(1)先操作資料庫,成功;
(2)再操作緩存(delete或者set),也成功;
但如果這兩個動作原子性被破壞:第一步成功,第二步失敗,會導緻,資料庫裡是新資料,而緩存裡是舊資料,業務無法接受。
畫外音:如果第一步就失敗,可以傳回調用方50X,不會出現資料不一緻。
二、先操作緩存,再操作資料庫
(1)先操作緩存(delete或者set),成功;
(2)再操作資料庫,也成功;
畫外音:如果第一步就失敗,也可以傳回調用方50X,不會出現資料不一緻。
如果原子性被破壞,會發生什麼呢?
這裡又分了兩種情況:
(1)操作緩存使用set
(2)操作緩存使用delete
使用set的情況:第一步成功,第二步失敗,會導緻,緩存裡是set後的資料,資料庫裡是之前的資料,資料不一緻,業務無法接受。
并且,一般來說,資料最終以資料庫為準,寫緩存成功,其實并不算成功。
使用delete的情況:第一步成功,第二步失敗,會導緻,緩存裡沒有資料,資料庫裡是之前的資料,資料沒有不一緻,對業務無影響。隻是下一次讀取,會多一次cache miss。
畫外音:此時可以傳回調用方50X。
**最終,先操作緩存,還是先操作資料庫?
**
答:
(1)讀請求,先讀緩存,如果沒有命中,讀資料庫,再set回緩存
(2)寫請求
(2.1)先緩存,再資料庫
(2.2)緩存,使用delete,而不是set
畫外音:《緩存,究竟是淘汰,還是修改?》也提到了,淘汰緩存還是修改緩存的建議。
希望大家有收獲,有不同方案歡迎讨論。
末了,挖個坑:
在緩存讀取流程中,如果主從沒有同步完成,步驟二讀取到一個舊資料,可能導緻緩存裡set一個舊資料,最終導緻資料庫和緩存資料不一緻。
如何解決這種情況下,緩存與資料庫資料不一緻的問題,是下一章要讨論的内容。