爲何你的緩存更新策略是先更新數據庫後刪除緩存,講講其餘的狀況有什麼問題?

問題:怎麼保持緩存與數據庫一致?數據庫

要解答這個問題,咱們首先來看不一致的幾種狀況。我將不一致分爲三種狀況緩存

  1. 數據庫有數據,緩存沒有數據;
  2. 數據庫有數據,緩存也有數據,數據不相等;
  3. 數據庫沒有數據,緩存有數據。

在討論這三種狀況以前,先說明一下我使用緩存的策略,也是大多數人使用的策略,叫作 Cache Aside Pattern。酷殼裏的 緩存更新的套路 一文,很值得一讀,個人策略也是從他那學來的。 簡而言之,就是ide

  1. 首先嚐試從緩存讀取,讀到數據則直接返回;若是讀不到,就讀數據庫,並將數據會寫到緩存,並返回。
  2. 須要更新數據時,先更新數據庫,而後把緩存裏對應的數據失效掉(刪掉)。

由於:線程

  1. 讀的邏輯你們都很容易理解,談談更新。若是不採起我提到的這種更新方法,你還能想到什麼更新方法呢?大概會是:先刪除緩存,而後再更新數據庫。這麼作引起的問題是,若是A,B兩個線程同時要更新數據,而且A,B已經都作完了刪除緩存這一步,接下來,A先更新了數據庫,C線程讀取數據,因爲緩存沒有,則查數據庫,並把A更新的數據,寫入了緩存,最後B更新數據庫。那麼緩存和數據庫的值就不一致了。方法

  2. 另外有人會問,若是採用你提到的方法,爲何最後是把緩存的數據刪掉,而不是把更新的數據寫到緩存裏。這麼作引起的問題是,若是A,B兩個線程同時作數據更新,A先更新了數據庫,B後更新數據庫,則此時數據庫裏存的是B的數據。而更新緩存的時候,是B先更新了緩存,而A後更新了緩存,則緩存裏是A的數據。這樣緩存和數據庫的數據也不一致。數據

按照我提到的這種更新緩存的策略,理論上也是有不一致的風險的,酷殼的文章有提到,只不過機率很小,咱們暫時能夠不考慮,後面咱們有其餘手段來補救。 討論完使用緩存的策略,咱們再來看這三種不一致的狀況。時間

  1. 對於第一種,在讀數據的時候,會自動把數據庫的數據寫到緩存,所以不一致自動消除
  2. 對於第二種,數據最終變成了不相等,但他們以前在某一個時間點必定是相等的(無論你使用懶加載仍是預加載的方式,在緩存加載的那一刻,它必定和數據庫一致)。這種不一致,必定是因爲你更新數據所引起的。前面咱們講了更新數據的策略,先更新數據庫,而後刪除緩存。所以,不一致的緣由,必定是數據庫更新了,可是刪除緩存失敗了。
  3. 對於第三種,狀況和第二種相似,你把數據庫的數據刪了,可是刪除緩存的時候失敗了。

所以,最終的結論是,須要解決的不一致,產生的緣由是更新數據庫成功,可是刪除緩存失敗。 我想出的解決方案大概有如下幾種:解決方案

  1. 對刪除緩存進行重試,數據的一致性要求越高,我越是重試得快。
  2. 按期全量更新,簡單地說,就是我按期把緩存所有清掉,而後再全量加載。
  3. 給全部的緩存一個失效期。

第三種方案能夠說是一個大殺器,任何不一致,均可以靠失效期解決,失效期越短,數據一致性越高。可是失效期越短,查數據庫就會越頻繁。所以失效期應該根據業務來定。懶加載

相關文章
相關標籤/搜索