緩存與數據庫的數據一致性的解決方案


使用redis作為mysql緩存數據庫流程:

先讀緩存數據,緩存數據有,則立即返回結果;如果沒有數據,則從數據庫讀數據,並且把讀到的數據同步到緩存里,提供下次讀請求返回數據。

雖說這樣能減輕數據庫壓力,但是如果修改刪除數據,在多線程高並發的場景下會有可能導致緩存和數據庫數據不一致問題,那該如何解決呢?

場景一:

問題的根源其實是讀數據與寫數據請求同時並發時,數據庫與緩存數據已更新,但訪問的數據還是老數據,出現了臟讀數據,我們假設讀請求流程沒有問題,那就分析寫請求流程的優化

  1. 先更新緩存,再更新數據庫

這個方案肯定不行。原因是更新緩存成功,更新數據庫出現異常了,導致緩存數據與數據庫數據完全不一致。

  1. 先更新數據庫,再更新緩存

這個方案同樣不行,原理跟第一個一樣,數據庫更新成功了,緩存更新失敗,同樣會出現數據不一致問題。

解決

我們遇到寫請求時,可用先刪除緩存數據,再更新數據庫,這樣不管數據庫更新失敗還是緩存刪除失敗,緩存與數據庫始終一致。這種方案一般可滿足上萬人並發操作了,因為刪除緩存到更新數據庫的時間可以用毫秒計算,正常的並發影響不大。

場景二:

上億級並發訪問,導致緩存與數據不一致。

解決

方案一:讀寫分離

讀請求只訪問緩存,寫請求只修改數據庫和緩存

寫請求修改數據庫和緩存是事務性動作,如果更新數據庫成功,更新緩存失敗,則回滾數據庫,保證緩存與數據庫數據強一致。這樣實現了讀寫分離,不僅提高了讀的響應速度,由寫請求負責緩存與數據庫一致,只有寫請求成功才會影響到緩存的內容,時效性大大增強。

方案二:隊列存儲請求

沿用場景一的解決方案,為解決其缺陷,添加隊列,凡是遇到寫請求,則將寫請求放入隊列中,由隊列對寫請求統一管理,寫請求處理成功,則從隊列中刪除。當有一個讀請求過來時,到隊列查詢,是否有對應的寫請求,如果有則放入隊列中,等待寫請求執行完之后再執行讀請求。為防止某個請求阻塞情況,為其設置超時機制或者過期機制。

場景三:

訪問量大,處理器來不及處理,隊列內的請求數量越來越高,則會影響查詢效率。

解決:

分布式數據庫集群,再加上消息隊列(kafka等)


免責聲明!

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



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