前言
在實際的項目開發中,為了提高響應的速度,通常都會將熱點的數據保存到緩存中,減少數據庫的查詢,有效提高服務端的響應速度,但是添加緩存之后也引入緩存與數據庫的一致性問題,本文將詳細的講解如何保證數據庫與緩存的一致性。
緩存使用策略
在使用緩存時,通常的緩存冊率有如下幾種:
- Cache-Aside Pattern(旁路緩存,業務系統常用)
- Read-Through Pattern
- Write-Through Pattern
- Write-Behind Pattern
Cache-Aside Pattern(旁路緩存模式)
Cache-Aside Pattern 簡稱旁路緩存模式,讀取緩存、讀取數據庫和更新緩存的操作都是在應用系統中完成,也是業務系統最常用的緩存策略。然而旁路路由策略又分為讀緩存和寫緩存。
讀緩存
說明:
- 應用程序需要從數據庫讀取數據時,先檢查緩存數據是否命中。
- 如果緩存未命中,則查詢數據庫獲取數據,同時將數據寫到緩存中,以便后續讀取相同數據會命中緩存,最后再把數據返回給調用者。
- 如果緩存命中,直接返回調用者。
寫緩存
寫緩存的流程就比較簡單,先更新數據庫中的數據,然后刪除舊的緩存即可。
Cache-Aside Pattern 一致性問題場景分析
實際的項目中運用最多的為Cache-Aside Pattern(旁路緩存)模式,在此策略下客戶端先讀取緩存,如果命中則返回,如果沒有命中,則查詢數據庫并發數據寫入緩存,由于數據庫和緩存都需要進行修改,在高并發的場景下,可能會導致數據不一致,針對數據不一致的場景,提供了四種更新方案具體如下:
- 先更新緩存,再更新數據庫。
- 先更新數據庫,再更新緩存。
- 先刪除緩存,再更新數據庫。
- 先更新數據庫,再刪除緩存。
接下來具體來講解四種方案的,以及四種方案存在的問題。
先更新緩存,再更新數據庫。
流程說明: 線程1:先更新緩存成功,但是網絡原因寫數據庫失敗,就會導致緩存是最新數據,而數據庫的數據為舊數據,那緩存就是臟數據, 線程2:讀取緩存中數據,而這個數據數據庫中卻不存在,數據庫都不存在的數據,緩存并返回客戶端就毫無意義了。
此方案在實際生產中不建議采用。
先更新數據庫,再更新緩存。
流程說明:
- 線程1先更新數據庫成功,但是由于網絡卡頓更新緩存失敗,從而導致緩存中的數據為舊數據
- 線程2從緩存中讀取數據,緩存中的數據為舊數,從而導致數據庫與緩存數據不一致。
此方案在實際生產中不建議采用。
先刪除緩存,再更新數據庫。
流程說明:
- 線程1,先刪除緩存成功,但是由于網絡卡頓原因,更新數據庫異常。
- 線程2,讀取緩存由于緩存數據為空,則會查詢數據庫中的數據,查詢成功并寫入緩存,從而導致數據不一致。
此方案在實際生產中不建議采用。
先更新數據庫,再刪除緩存。
流程說明:
- 線程1寫入數據庫成功,由于網絡卡頓原因,導致刪除緩存數據失敗
- 線程2讀取數據,讀取為緩存中的數據,但是當網絡恢復正常后,緩存中的數據會被刪除,所以可能會存在短暫的數據不一致。
雖然存在短暫的數據不一致,但是在旁路緩存策略的時候,對于寫的操作:先更新數據庫,再刪除緩存。
數據庫和緩存一致性解決方案
緩存延遲雙刪
緩存延遲雙刪針對第三種場景的優化,具體的流程如下:
說明:先刪除緩存,在更新數據庫,確保數據庫事務提交成功,然后休眠一段時間在刪除緩存。我們都知道第三種情況是因為網絡卡頓導致數據庫更新失敗,當網絡恢復正常后,我們在執行更新數據庫操作,然后再刪除緩存,那么出現數據不一致的情況也就是在休眠的這短暫的時間內。
刪除緩存失敗如何處理
刪除緩存重試機制
需要刪除失敗的key存入消息隊列中,采用異步的方式來進行刪除,如果刪除失敗的次數已經超過了最大次數,發送警告郵件,需要人工介入解決。
總結
本文對于數據庫和緩存的一致性進行詳細的講解,由于數據庫和緩存一致性的場景比較復雜,每種方案都無法保證絕對的一致性,根據CAP理論我們知道緩存系統使用場景為非強一致性的場景,符合CAP中的AP,如有疑問請及時反饋。
作者:劍圣無痕
鏈接:https://juejin.cn/post/7126188464713760776
來源:稀土掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。