1. 程式人生 > >Web應用中的快取一致性問題

Web應用中的快取一致性問題

上篇總結了快取中出現頻率比較高的一些問題,今天詳細說說web應用中的快取一致性問題。

主要說以下三個方面

  • 資料庫與快取中資料不一致出現的情形
  • 發生不一致時的優化思路
  • 如何保證資料庫與快取的一致性

先來討論下結論

由於操作快取與操作資料庫不是原子的,所以非常有可能出現執行失敗的情況。

假設先寫資料庫,再淘汰快取:這時候如果出現寫資料庫成功,淘汰快取失敗,則會出現DB中是新資料,cache中是舊資料,資料不一致,此時獲取資料仍然為舊資料,在cache失效之前,獲取的資料均為異常資料如下:

 

 

 

假設先淘汰快取,再寫資料庫:第一步淘汰快取成功,第二步寫資料庫失敗,則只會引發一次cache miss

 

 

 

綜上,在涉及快取操作時應該先淘汰快取,再修改資料

不一致出現的情形

在分散式環境下,資料的讀寫都是併發的,上游有多個應用,通過一個服務的多個部署(為了保證可用性,一定是部署多份的),對同一個資料進行讀寫,在資料庫層面併發的讀寫並不能保證完成順序,也就是說後發出的讀請求很可能先完成(讀出髒資料):

(1)發生了寫請求A,A的第一步淘汰了cache

(2)A的第二步寫資料庫,發出修改請求

(3)發生了讀請求B,B的第一步讀取cache,發現cache中是空的

(4)B的第二步讀取資料庫,發出讀取請求,此時A的第二步寫資料還沒完成,讀出了一個髒資料放入cache

即在資料庫層面,後發出的請求4比先發出的請求2先完成了,讀出了髒資料,髒資料又入了快取,快取與資料庫中的資料不一致出現了

不一致優化思路

如果能做到先發出的請求先執行完成,那是不是能避免這個問題呢?答案是肯定的。那如何能達到這個目的?這裡提供2個思路。

第一個是mysql的可序列化

可序列化——SERIALIZABLE

事務的最高級別,在每個讀的資料行上,加上鎖,使之不可能相互衝突,因此,會導致大量的超時現象。

同一個資料用同一個連結

在用連線池進行訪問資料庫的時候,針對同一個資料的DB訪問,使用同一個連結進行操作,這樣也可以達到先發出的請求完成之後才會進行下一個訪問。

 

轉載自:https://zhuanlan.zhihu.com/p/38919743