究竟先操作快取,還是資料庫?

58沈劍發表於2018-11-06

究竟先操作快取,還是資料庫?

2018年07月09日 20:20:00 架構師之路_ 閱讀數:1007

版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/z50L2O08e2u4afToR9A/article/details/80976862

快取儲存,也是資料的冗餘。

(1)資料庫訪問資料,磁碟IO,慢;

(2)快取裡訪問資料,存操作,快;

(3)資料庫裡的熱資料,可在快取冗餘一份;

(4)先訪問快取,如果命中,能大大的提升訪問速度,降低資料庫壓力;

 

這些,是快取的核心讀加速原理。

 

但是,一旦沒有命中快取,或者一旦涉及寫操作,流程會比沒有快取更加複雜,這些是今天要分享的話題。

 

讀操作,如果沒有命中快取,流程是怎麼樣的?

:如下圖所示

640?wx_fmt=png

(1)嘗試從快取get資料,結果沒有命中;

(2)從資料庫獲取資料,讀從庫,讀寫分離;

(3)把資料set到快取,未來能夠命中快取;

讀操作的流程應該沒有歧義。

 

寫操作,流程是怎麼樣的?

:寫操作,既要運算元據庫中的資料,又要操作快取裡的資料。

 

這裡,有兩個方案:

(1)先運算元據庫,再操作快取;

(2)先操作快取,再運算元據庫;

並且,希望保證兩個操作的原子性,要麼同時成功,要麼同時失敗。

 

這演變為一個分散式事務的問題,保證原子性十分困難,很有可能出現一半成功,一半失敗,接下來看下,當原子性被破壞的時候,分別會發生什麼。

 

一、先運算元據庫,再操作快取

640?wx_fmt=png

如上圖,正常情況下:

(1)先運算元據庫,成功;

(2)再操作快取(delete或者set),也成功;

 

但如果這兩個動作原子性被破壞:第一步成功,第二步失敗,會導致,資料庫裡是新資料,而快取裡是舊資料,業務無法接受

畫外音:如果第一步就失敗,可以返回撥用方50X,不會出現資料不一致。

 

二、先操作快取,再運算元據庫

640?wx_fmt=png

如上圖,正常情況下:

(1)先操作快取(delete或者set),成功;

(2)再運算元據庫,也成功;

畫外音:如果第一步就失敗,也可以返回撥用方50X,不會出現資料不一致。

 

如果原子性被破壞,會發生什麼呢?

 

這裡又分了兩種情況:

(1)操作快取使用set

(2)操作快取使用delete

 

使用set的情況:第一步成功,第二步失敗,會導致,快取裡是set後的資料,資料庫裡是之前的資料,資料不一致,業務無法接受

 

並且,一般來說,資料最終以資料庫為準,寫快取成功,其實並不算成功。

 

使用delete的情況:第一步成功,第二步失敗,會導致,快取裡沒有資料,資料庫裡是之前的資料,資料沒有不一致,對業務無影響。只是下一次讀取,會多一次cache miss。

畫外音:此時可以返回撥用方50X。

 

最終,先操作快取,還是先運算元據庫?

(1)讀請求,先讀快取,如果沒有命中,讀資料庫,再set回快取

(2)寫請求

    (2.1)先快取,再資料庫

    (2.2)快取,使用delete,而不是set

畫外音:《快取,究竟是淘汰,還是修改?》也提到了,淘汰快取還是修改快取的建議。

 

希望大家有收穫,有不同方案歡迎討論。

 

末了,挖個坑:

640?wx_fmt=png

在快取讀取流程中,如果主從沒有同步完成,步驟二讀取到一箇舊資料,可能導致快取裡set一箇舊資料,最終導致資料庫和快取資料不一致。

 

如何解決這種情況下,快取與資料庫資料不一致的問題,是下一章要討論的內容。

 

640?wx_fmt=png

相關推薦:

程式內快取,究竟怎麼玩?

選redis還是memcache,原始碼怎麼說?

快取,你真的用對了麼?

快取,究竟是淘汰,還是修改?

快取,併發更新的大坑?

資料庫主從不一致,怎麼解?

 

文字很短,希望大家有啟示,幫轉。

相關文章