天天看點

高并發下緩存與資料庫雙寫不一緻解決方案

1、最初級的緩存不一緻問題以及解決方案

問題:先修改資料庫,再删除緩存,如果删除緩存失敗了,那麼會導緻資料庫中是新資料,緩存中是舊資料,資料出現不一緻。

解決思路:

  先删除緩存,再修改資料庫,如果删除緩存成功了修改資料庫失敗了,那麼資料庫中是舊資料,緩存中是空的,那麼資料不會不一緻,因為讀的時候緩存沒有,則讀資料庫中舊資料,然後更新到緩存中。

  

高并發下緩存與資料庫雙寫不一緻解決方案

2、并發下資料緩存不一緻問題分析

問題:

  第一個請求資料發生變更,先删除了緩存,然後要去修改資料庫,此時還沒來得及去修改;

  第二個請求過來去讀緩存,發現緩存空了,去查詢資料庫,查到了修改前的舊資料,放到了緩存中;

  第三個請求讀取緩存中的資料 (此時第一個請求已經完成了資料庫修改的操作)。

  完了,資料庫和緩存中的資料不一樣了。。。。

問題分析:

  隻有在對同一條資料并發讀寫的時候,才可能會出現這種問題。其實如果說你的并發量很低的話,特别是讀并發很低,每天通路量就1萬次,那麼很少的情況下,會出現剛才描述的那種不一緻的場景;但如果每天的是上億的流量,每秒并發讀是幾萬,每秒隻要有資料更新的請求,就可能會出現上述的資料庫+緩存不一緻的情況。

解決思路

  資料庫的緩存更新與讀取操作進行串行化,一個隊列對應一個工作線程,每個工作線程串行拿到對應的操作,然後一條一條的執行。

  1. 首先我們的項目裡維護一組線程池和記憶體隊列。

  2. 更新資料的時候,根據資料的唯一辨別将請求路由到一個jvm隊列中,去更新資料庫,然後請求結束。

  3. 讀取資料的時候,先查緩存,如果發現資料不在緩存中,那麼将根據唯一辨別路由之後,也發送同一個jvm内部的隊列中,重新讀取資料庫後更新緩存,最後請求結束。

   

高并發下緩存與資料庫雙寫不一緻解決方案

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

轉載于:https://www.cnblogs.com/wlwl/p/11601632.html