聲明:本文僅限于簡書發(fā)布抖僵,其他第三方網(wǎng)站均為盜版冠摄,原文地址: 簡單看看緩存一致性的幾種做法
緩存是個(gè)好東西,一個(gè)好的緩存算法[4]可以讓我們系統(tǒng)的吞吐能力輕松上升一個(gè)到兩個(gè)數(shù)量級。當(dāng)只有唯一的操作緩存的接口時(shí)意蛀,一切都很簡單淆珊;但是夺饲,一旦有兩個(gè)或以上的操作接口時(shí),事情就會(huì)變得復(fù)雜施符,其核心的問題就是緩存會(huì)被失效往声,這個(gè)時(shí)候該怎么處理是個(gè)值得探究的問題,而我嘗試以我的了解戳吝,以 Python 代碼為示例浩销,做一下小結(jié)。
這是一張展示現(xiàn)代計(jì)算機(jī)各個(gè)不同存儲模塊的性能對比圖听哭,摘自:《深入理解計(jì)算機(jī)系統(tǒng)》
緩存會(huì)失效慢洋,大多數(shù)情況是因?yàn)閿?shù)據(jù)被修改了塘雳,還有少數(shù)情況是被刪除了,所以普筹,我們先關(guān)注一下修改的問題粉捻。對于修改被緩存數(shù)據(jù)的策略比較常見的有三種:
- 直寫:write-through
- 繞寫:write-around
- 回寫:write-back
雖然緩存不是一個(gè)依賴于語言的東西,但是為了更好得解釋以及讓我的邏輯更清晰斑芜,這里我就使用簡單的Python 代碼作為示例肩刃,希望能夠以更容易理解的方式,來模擬不同的這些緩存策略杏头,從而闡述我的理解盈包。
緩存是存儲數(shù)據(jù)的硬件或軟件組件,因此可以更快地響應(yīng)對數(shù)據(jù)的請求醇王。當(dāng)然呢燥,這些數(shù)據(jù)肯定要存儲在一個(gè)自身響應(yīng)速度快于實(shí)際存儲的地方(速度對比見上圖)。例如寓娩,如果您在內(nèi)存中存儲值叛氨,則訪問數(shù)據(jù)通常會(huì)比訪問數(shù)據(jù)庫更快,因?yàn)槟强墒菑拇疟P讀取數(shù)據(jù)啊棘伴。
下面寞埠,我要開始我的表演了,就寫兩個(gè) Python代碼 來表示后臺存儲和緩存先吧:
這里有兩個(gè)類
- BackingStore:用來表示我們直接從數(shù)據(jù)庫/磁盤中讀取數(shù)據(jù)焊夸,也就是比較慢的數(shù)據(jù)操作
- Cache:表示從緩存中讀取數(shù)據(jù)仁连,也就是很快得數(shù)據(jù)操作
下面就以這個(gè)為框架,一一得介紹我的理解阱穗。
直寫:write-through
直寫的意思就是在數(shù)據(jù)更新時(shí)饭冬,同時(shí)寫入緩存Cache和后端存儲。我們用代碼來描述一下就是:
這里的可以看到 Line 12揪阶,直寫操作表示 cache 和 真實(shí)數(shù)據(jù)存儲都要同時(shí)更新才能成功昌抠,這種方法很不錯(cuò),你更新成功之后鲁僚,可以保證緩存和真實(shí)的數(shù)據(jù)保持一致炊苫,但是,問題也很明顯蕴茴,第一個(gè)就是劝评,我們更新的速度會(huì)很慢,還有萬一更新過程中出錯(cuò)了呢倦淀?具體對比我們后續(xù)說蒋畜,下面再看看其他的。
回寫:write-back
這種方式就簡單多了撞叽,具體操作就是只更新緩存姻成,只有當(dāng)緩存被替換時(shí)才進(jìn)行持久化插龄,代碼示例是這樣的:
這種方式我們很明顯就可以看出來,速度很快科展,因?yàn)楦静簧婕暗胶蠖说臄?shù)據(jù)存儲操作均牢,但是玄叠,缺點(diǎn)也很明顯啊苫费,我們得關(guān)注緩存是不是被替換了监氢,而且還有萬一緩存就崩了呢此衅?
繞寫:write-around
既然只寫緩存風(fēng)險(xiǎn)那么大,那我就直接寫后端數(shù)據(jù)饮潦,這樣讓緩存自動(dòng)失效之后银觅,再刷新一遍首繁,代碼這么看:
這種方式的話優(yōu)點(diǎn)是可以保證最終的持久數(shù)據(jù)是正確的坞琴,但是哨查,因?yàn)槲覀儧]有讓緩存失效,所以只能等緩存主動(dòng)失效之后再讀取持久數(shù)據(jù)剧辐,同時(shí)寒亥,更新速度也不快。
對比
基本方式我們上面都介紹過了荧关,但是溉奕,只是簡單得說說各種方式的優(yōu)缺點(diǎn),并沒有揉碎了好好說羞酗,所以腐宋,下面就以一張 Excel 表進(jìn)行介紹,看看具體的對比:
這里可以看出檀轨,各種套路都有自己的優(yōu)缺點(diǎn),我們可以根據(jù)自己項(xiàng)目的需要進(jìn)行選擇欺嗤,但是参萄,通常來說,我們引入緩存是因?yàn)樽x多寫少煎饼,所以可能繞寫(Write-Around)用的更多讹挎,而且常常配合刪除緩存的方法,從而讓緩存更新吆玖。但是筒溃,我們需要清晰得知道刪除緩存會(huì)帶來什么問題,我們是否已經(jīng)注意到這個(gè)問題并且避免了或者不在乎這些問題沾乘,具體的討論可以參考[8]怜奖。
本文的代碼都托管在 Github:Git Code