快取與庫先寫哪個,這十幾張圖告訴你

*IT界農民工* 發表於 2020-10-26

日常生產場景中,為了避免大量請求同時打在資料庫上導致故障,資料庫+快取的方式已經成了日常標配。

對於讀取的部分,大家都很熟悉。但是對於寫的部分,到底是先寫庫還是先寫快取,這點可能困擾著很多人。

各位看官請跟隨小萊往下看:

快取與庫先寫哪個,這十幾張圖告訴你思維導圖

旁路快取策略

提到這個有逼格的名詞你可能不是很熟悉,但是說到它的使用方式,你肯定用過。

這是一種最經典的快取+資料庫讀寫的模式,英文是這樣 Cache Aside Pattern,可能你見過。

這種模式對應的使用方式有兩種情況,一讀一寫:

  • 基本讀取方式;
  • 先更新資料庫,後刪除快取。

1、基本讀取方式

這部分相信大家已經輕車熟路:先讀快取,快取中沒有資料的話就去資料庫讀取,然後再存入快取中,同時返回響應。

這沒什麼可說的,平時都這麼用。如果還不清楚,看下小萊為大家畫的圖:

快取與庫先寫哪個,這十幾張圖告訴你

 

那我們再看寫的部分。

2、先更新資料庫,後刪除快取

你可能會問了,為什麼不在更新完資料庫後,採取更新快取的方案,而是將其刪除。原因有這麼幾點:

  • 頻繁更新浪費資源

你想想,如果修改庫中的某個欄位,一段時間內頻繁進行更新。那麼你修改多少次,快取也跟著更新多少次。但是這個快取資料在這段時間內也就被偶爾使用了幾次。

那麼你看,是不是就會導致資源浪費了。

  • 快取資料計算複雜

還有一種情況,如果這個快取的資料計算成本比較高。比如為了一個資料,要通過多張表來計算才能得到結果。那麼每修改一次,為了更新快取還要再查詢多張表來算一次,我的天。

  • 兩種情況都具備

這種情況最為致命,不但修改頻繁,同時快取資料還要經過複雜計算。

生產環境裡要是這麼搞的話,那估計你就可以準備簡歷了。

既然更新快取的方式不可行,那麼我們換個思路,刪除掉呢?

還是按照上邊的步驟,先更新資料庫,只是我們把更新快取的操作換成了刪除。

在這種情況下,讀請求過來的時候,發現 Redis 中沒有資料,就會去資料庫裡讀取,然後寫入快取中。

這也是一種懶載入方式,只有快取被需要的時候才會去計算。這樣可以避免大量計算及頻繁更新。

但是,這樣會有什麼隱患的問題?是不是看著沒什麼毛病。你想想,如果資料更新成功,但是刪除快取失敗怎麼辦? 

快取與庫先寫哪個,這十幾張圖告訴你快取與庫先寫哪個,這十幾張圖告訴你快取與庫先寫哪個,這十幾張圖告訴你

如圖中所示,剛開始時(初始),資料庫和快取中的資料是一致的,但是在寫請求過來後,資料庫更新成功,而快取刪除失敗。這就導致資料庫中的資料是最新的,但快取中卻依然存著舊資料。

這時,如果讀請求過來,就會直接讀取快取中的舊資料返回了。

雙寫一致方案

1、先刪除快取,後更新資料庫

既然問題的原因是刪除快取失敗了,那麼我們先確保把快取刪除成功了,再去更新資料庫。也就是說我們先刪除快取,後更新資料庫。

可能你會問了,如果我資料庫更新失敗了呢?

我們不妨通過圖來看下這種情況:

快取與庫先寫哪個,這十幾張圖告訴你快取與庫先寫哪個,這十幾張圖告訴你快取與庫先寫哪個,這十幾張圖告訴你

快取刪除成功後為空了,但是資料庫卻失敗了,還是原來的舊資料。

如果這時候有請求過來的話,一看快取中沒有資料,於是就到資料庫讀取了舊資料更新到快取中。

如果你的專案併發量很低的話,每天訪問量就那麼點,那這麼用沒毛病,很少情況下才會出現資料不一致的問題。

這種策略只能算作初級的解決方案,為什麼這麼說呢?

2、快取延時雙刪策略

如果同時來了兩個請求,一個寫請求,一個讀請求。

寫請求先刪除Redis中的資料,然後去資料庫進行更新操作。

讀請求判斷Redis中有沒有資料,沒有資料時去請求資料庫,拿到資料後寫入快取中。

但是寫請求此時並沒有更新成功,或者執行了一個事務還沒有成功。

這樣的話,讀請求拿到未修改的舊資料寫入快取。過了一會兒,寫請求將資料庫更新成功了,那麼此時快取與庫中的資料就不一致了。

快取與庫先寫哪個,這十幾張圖告訴你

解決方案呢?延時雙刪策略:

快取與庫先寫哪個,這十幾張圖告訴你

寫請求過來先把 Redis快取刪掉,等資料庫更新成功後,非同步等待一段時間再次把快取刪掉。

這種方案讀取速度快,但是會出現短時間的髒資料。

總結

旁路快取策略

  • 讀的時候,先讀快取,快取沒有的話,再去讀資料庫,然後取出來放入快取中,同時返回響應。
  • 更新的時候,先更新資料庫,再刪除快取。

雙寫一致方案

  • 先刪除快取,後更新資料庫:

解決了快取刪除失敗導致庫與快取不一致的問題,適用於併發量不高的業務場景。

  • 快取延時雙刪策略:

這種方案解決了高併發情況下,同時有讀請求與寫請求時導致的不一致問題。讀取速度快,但是可能會出現短時間的髒資料。

每種方案各有利弊,對於不同的業務來說沒有通用的技術方案。在選擇技術方案時需要根據業務自身來定。沒有最好的,只有最合適的。

關於作者

作者:大家好,我是萊烏,BAT搬磚工一枚。從小公司進入大廠,一路走來收穫良多,想將這些經驗分享給有需要的人,因此建立了公眾號「IT界農民工」。定時更新,希望能幫助到你。

 快取與庫先寫哪個,這十幾張圖告訴你