提到快取,作為服務端的開發人員并不陌生,無論是本地快取還是分布式快取,其目的都是為了提高系統回應速度的同時減輕資料庫的查詢壓力;在快取開發中有個問題必需要解決,那就是“快取一致性問題”!
快取一致性

軟體開發中的快取一致性是指快取中的資料要和資料庫(或者資料提供方)的資料保持一致
關于快取
我們必需要明白一點,并不是所有的場景下都適合加入快取,當資料量較小時合理利用資料庫的索引來加快查詢速度來的更加方便,除非
- 資料量比較大單純資料庫查詢性能無法滿足性能要求??
- 資料的查詢比較頻繁且更新頻率不高
- 業務上必需能夠容忍短暫的資料不一致的情況,如果是類似于銀行金額等要求必須實時一直的情況,請慎用快取
快取一致性方案探討?
你是否被問過這個問題:當資料發生變更時,是先更新快取還是先更新資料庫?
??這是一個在面試中經常被問到的問題,一般來講,這個時候無論你回答先更新哪個答案都是錯誤的,
-
- ??先更新快取,那萬一更新完快取,資料庫更新失敗了怎么辦?
- ??先更新資料庫,如果更新資料庫成功,更新快取失敗了怎么辦?
??無論上述兩種情況任何一種出現,都會導致快取和資料庫的資料不一致的情況
為了解決上述問題,我們一般會想到
??“先洗掉快取,然后再更新資料庫,這樣即使更新失敗了,快取也不會出現臟資料”真的是這樣嗎?
在單執行緒操作的情況下確實是這樣的,但是實際應用中我們沒法控制客戶端請求是線性運行的,所以先洗掉快取在更新資料庫的方案是不可行的,容易產生臟資料,如圖?

快取雙刪
????為了保證快取和資料庫的資料一致
先洗掉快取--->更新資料庫--->再次洗掉快取資料

如上圖所示,雙刪也可能會存在問題,比如T5時刻洗掉了快取,T6時刻卻將T3時刻讀取的資料更新到了快取,從而導致快取資料與資料庫資料不一致;
針對上面存在的問題,我們可以采取如下方案
改進方案
一.鎖加延時洗掉

流程說明:
- 上圖鎖并不能解決執行緒安全問題,而是為了減少查詢執行緒查詢資料庫后更新快取的次數(鎖驗證),若考慮到操作的便利性也可以去掉流程中的鎖相關環節;
- 為了提高更新執行緒的并發效率,上圖中的鎖可以使用累加鎖標記,默認是0(無鎖),以后每一個更新執行緒獲取鎖時都對鎖計數+1,更新執行緒釋放鎖的時候鎖計數-1;
- 多個更新執行緒的并發及順序問題可以交給資料庫來控制也可以在業務中額外增加分布式鎖或者有序佇列來實作
- 查詢執行緒中的獲取鎖可以理解為判斷當前鎖標記的計數是否等于0;
- 更新執行緒中先獲取 鎖再洗掉是考慮到如果先洗掉快取的話在獲取 鎖之前,查詢執行緒會額外增加一次執行緒更新操作;
- 在釋放鎖之后再次延時洗掉快取是為了避免在查詢執行緒在查詢完資料庫后,更新執行緒更新了資料庫的值,此時查詢執行緒將剛剛查詢到的舊資料維護進快取;
- 在更新和查詢都比較頻繁的情況下,更新的時候,根據資料的唯一標識,將操作添加進有序佇列中進行處理,讀取資料的時候,如果發現資料不在快取中,那么將重新讀取資料+更新快取的操作,根據唯一標識也發送一個有序佇列中,但是要考慮到請求效率和超時問題,
寫在最后,鑒于筆者能力有限,上述方案獲取存在著不足,如果您發現有不足的地方,歡迎留言討論
https://www.cnblogs.com/lsgspace/ 原創作品歡迎轉載,轉載請注明出處
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/536144.html
標籤:架構設計
下一篇:設計模式 - 概述
