分布式緩存數據庫一致性問題


緩存和數據庫一致性問題,有很多解決方案,沒有最完美的方案,只有適合自身業務的盡可能完美的方案。

緩存由於其高並發和高性能的特征,已經在項目中被廣泛應用。

  查詢時一般先查詢緩存,如果緩存命中的話,那么直接將數據返回。

  如果緩存中沒有數據(如失效,或者根本沒設置數據),那么,應用程序先從數據庫中查詢數據,如果不為空,則將數據放在緩存中。

那么更新時,怎么處理緩存和數據庫呢?先更新數據庫后更新緩存?先更新數據庫后更新緩存?或者先淘汰緩存后更新數據庫?

為什么沒有先更新緩存后更新數據庫?

  1):如果更新數據庫失敗,那么就造成了數據不一致

 

先更新數據庫后更新緩存的問題

  1):兩個線程並發更新數據庫再更新緩存可能出現緩存更新順序問題

  2):如果更新頻繁,讀少的情況,那么緩存也被頻繁更新,造成不必要的開銷

  3):如果緩存的值是需要經過一系列復雜計算的,那么每次都去更新緩存無疑是浪費性能的

 

先刪緩存后更新數據庫的問題:

  1):線程A刪除緩存更新完數據庫前,線程B沒有命中緩存,從數據庫中查詢到了更新前的值存入緩存中

  解決方案:延時雙刪策略(推薦使用)

  即先刪除緩存,再更新數據庫,休眠一段時間,再刪除緩存

  偽代碼如下:

public void write(String key,Object data){
    redis.delKey(key); 
    db.updateData(data); 
    Thread.sleep(1000); redis.delKey(key);
 }

為什要休眠1秒鍾?為了將這1秒內造成的臟數據刪除,可能有線程讀取到了更新前的舊數據還未來得及寫入緩存

休眠的時間多少如何確定?評估自身項目讀數據業務邏輯的耗時,在這基礎了加100ms即可。可以確保臟數據已經寫入緩存中

讀寫分離怎么辦?

  也是采用延時雙刪策略,休眠時間確保完成主從同步

為了避免休眠造成吞吐量降低,可以將第二次刪除作為異步操作

第二次刪除失敗怎么辦?

  刪除在更新期間寫入緩存的舊值失敗

  解決方案:將需要刪除的key發送到消息隊列,然后自己消費消息,獲得需要刪除的key,繼續重試刪除操作,直到成功。

先更新數據庫后刪緩存

  即Cache Aside Pattern,即緩存旁路模式

  失效:應用程序先從緩存中取數據,沒有取到,則從數據庫中取數據,成功后,放到緩存中

  命中:應用程序從緩存中渠道數據,然后返回

  更新:先把數據存到數據庫中,成功后,再刪除緩存


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM