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訪問,使用同一個鏈接進行操作,這樣也可以達到先發出的請求完成之後才會進行下一個訪問。
http://weixin.qq.com/r/aS5UTHLE-i_BrTYv93t7 (二維碼自動識別)
推薦閱讀:
※迷你圍棋之奧妙(一):二路圍棋
※SSH前言學習筆記(1)
※聊聊開工這一周
※中美兩位 AI 大師的「巔峰對話」:為何 NLP 領域難以出現「獨角獸」? | 獨家
※留美專業之計算機科學CS