高並發下緩存與數據庫雙寫不一致解決方案


1、最初級的緩存不一致問題以及解決方案
問題:先修改數據庫,再刪除緩存,如果刪除緩存失敗了,那么會導致數據庫中是新數據,緩存中是舊數據,數據出現不一致。
解決思路:
  先刪除緩存,再修改數據庫,如果刪除緩存成功了修改數據庫失敗了,那么數據庫中是舊數據,緩存中是空的,那么數據不會不一致,因為讀的時候緩存沒有,則讀數據庫中舊數據,然后更新到緩存中。

  

2、並發下數據緩存不一致問題分析
問題:
  第一個請求數據發生變更,先刪除了緩存,然后要去修改數據庫,此時還沒來得及去修改;
  第二個請求過來去讀緩存,發現緩存空了,去查詢數據庫,查到了修改前的舊數據,放到了緩存中;
  第三個請求讀取緩存中的數據 (此時第一個請求已經完成了數據庫修改的操作)。
  完了,數據庫和緩存中的數據不一樣了。。。。

問題分析:
  只有在對同一條數據並發讀寫的時候,才可能會出現這種問題。其實如果說你的並發量很低的話,特別是讀並發很低,每天訪問量就1萬次,那么很少的情況下,會出現剛才描述的那種不一致的場景;但如果每天的是上億的流量,每秒並發讀是幾萬,每秒只要有數據更新的請求,就可能會出現上述的數據庫+緩存不一致的情況。
解決思路
  數據庫的緩存更新與讀取操作進行串行化,一個隊列對應一個工作線程,每個工作線程串行拿到對應的操作,然后一條一條的執行。
  1. 首先我們的項目里維護一組線程池和內存隊列。
  2. 更新數據的時候,根據數據的唯一標識將請求路由到一個jvm隊列中,去更新數據庫,然后請求結束。
  3. 讀取數據的時候,先查緩存,如果發現數據不在緩存中,那么將根據唯一標識路由之后,也發送同一個jvm內部的隊列中,重新讀取數據庫后更新緩存,最后請求結束。

   

  這里有一個需要優化的點,比如一個隊列中,連續存在多個更新緩存請求串在一起是沒意義的,這樣重復的查詢數據庫並更新緩存的操作應該優化:如果發現隊列中已經有一個更新緩存的請求了,那么就不用再放個更新請求操作進去了,直接讓后面的讀請求阻塞個200ms左右(這里只是舉個例子,實際值可以根據服務的響應時間和機器的處理能力來計算),然后再次查詢緩存,如果緩存沒有值就查數據庫,拿到結果后不用更新緩存,直接返回給頁面即可。


免責聲明!

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



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