1. 程式人生 > 其它 >資料庫和快取資料雙寫一致性問題

資料庫和快取資料雙寫一致性問題

參考:https://blog.csdn.net/qq_33135813/article/details/91352093?utm_medium=distribute.wap_relevant.none-task-blog-2~default~baidujs_title~default-0.wap_blog_relevant_pic

https://blog.csdn.net/wenlin_xie/article/details/87652240

1、什麼是快取-資料庫雙寫一致性問題?

應用設計中,如果為了提高查詢效能,將一些資料庫查詢到的資料放入了快取中,那麼就會出現一種情況,更新資料庫某些資料的時候,由於需要將快取中的資料和資料庫的資料做同步,那麼高併發場景下,就會受到其他更新操作或者查詢操作的影響。

2、使用到快取的情況下,更新資料庫的資料,資料庫和快取應該怎麼更新?

正常情況,對於資料實時性要求不高的系統,可以設定快取有效期,可以保證快取資料最終的一致性。如果對資料實時性要求高,就需要選擇更好的方案。如下:

如果選擇了更新資料庫然後更新快取這種設計,就會導致每次更新庫表都要去查詢最新的資料然後更新到快取,假如這條資料客戶實際訪問的很少,就會導致浪費資源;

所以一般我們可以進行優化,選擇刪除快取,那麼只有當客戶第一次用到這條資料的時候才去資料庫查詢,後續查詢都會先去快取獲取,未命中才去資料庫獲取;

3、先刪除快取,後更新資料庫的方案:(先更新庫,後刪除快取,如果第一步成功了,第二部失敗了會導致兩邊資料不一致的情況)

理論上,如果刪除快取失敗,那麼資料庫也不會去更新,可以保持兩邊資料一致;快取刪除成功,資料庫更新失敗,那麼客戶查詢這條資料的時候會去資料庫獲取,然後更新快取,兩邊資料可以保持一致;

缺陷:假如刪除快取成功了,但是還未更新資料庫,這時執行緒切換,切換到另一個查詢任務執行緒,查詢會走到去資料庫獲取資料然後更新快取,那麼快取儲存的就是舊資料,再切換回去更新資料庫,這時兩邊資料就不一致了。

解決“執行緒切換干擾更新”的方案:

a、雙刪除策略,刪除快取-更新資料庫-等待幾百ms再刪除快取;可以保證上面那種執行緒切換導致讀取舊資料到快取的情形下,將舊資料及時刪除。

如果還擔心第二次刪除會失敗,那就再給快取設定有效期,保證資料最終一致性。

b、引入阻塞佇列。更新時,利用這條資料的唯一標識,建立一個與之對應的任務佇列,儲存到Map<唯一標識id, Queue<String>>,更新完資料庫和快取後,移除佇列的這個元素,後續有讀操作的時候,利用唯一標識獲取相應佇列,然後判斷佇列內是否有其他操作,是的話進入佇列等候,後續再來一個查詢請求時,判斷如果佇列中已經存在一個相同的查詢等待請求任務在等待了,就不需要進入佇列,直接阻塞等待更新操作完成再往下走。