在日常開發過程中,對於Redis和MySQL的使用想必是不陌生的。當面對一些較為簡單的使用場景時,貌似也不會很困難。但是在涉及到緩存和數據庫之間的數據同步問題的時候,一個考慮不慎,也許就該准備簡歷了。今天小楊就和大家聊一聊這點。
大多數我們操作Redis的時候,一般的使用場景:1、寫少讀多,修改性較低的場景,2、或者存儲一些熱點的數據或者配置 ,從而緩解數據庫的壓力。但是,當我們將緩存搭配數據庫一起使用到一些較為復雜的使用場景時,數據的一致性問題就顯得比較突出,尤其是在請求較多的情況下。接下來我們分析一些常見的方案,並分析其優缺點,供大家選擇。
首先對於緩存,是刪除呢還是更新呢
對於緩存,我覺得較為正確的做法是:先刪除緩存,而不是更新。較為常見的做法:先刪除緩存,當下一次請求查詢緩存不在的時候,就去查數據庫,再將結果寫入緩存。原因如下:
1、假如是寫比讀多的情況下,每次操作更新的時候會比較浪費性能,尤其是數據是經過一系列復雜計算或者操作的時候,尤為明顯。
2、當兩個線程通過更新數據庫再更新緩存的時候,如果出現網絡延遲或者卡頓等情況下,有可能會造成前后更新緩存的順序不一樣,結果導致緩存出現臟數據。
那是先刪除緩存,再更新數據庫,還是先更新數據庫,再更新緩存呢
對於先刪除緩存,再更新數據庫這種情況,我們會發現存在數據不一致的情況。如:
- 當第一個請求進來的時候,先刪除了緩存
- 此時第二個請求發現沒有緩存,於是到數據庫去讀取並將數據寫入到緩存中
- 第一個請求再將數據寫入到數據庫中
先更新數據庫,再更新緩存
對於這種情況下,如果不是很嚴格的一致性的問題,可以采用這種方式,但是在一些高並發,依舊會存在一些問題,如下面這種例子:
- 在更新數據庫之前有查詢請求,並且剛好緩存失效了,於是進行查詢了數據庫,得到數據
- 此時,發生了寫的操作請求,將新的值更新了數據庫並刪除了緩存
- 第一個請求將值寫入緩存 (此時的數據為舊的數據,也就是發生了數據不一致的情況)
基於上面的分析:為什么還是可以得到推薦呢,原因在於,發生上面的情況的條件在於第一步的查詢數據庫會比第二部寫數據庫慢,才會發生先刪除再寫入的情況 這種情況相對較小。大部分數據庫做了讀寫分離的架構,讀的速度會相對寫更快。
緩存延時雙刪
這個是最為推薦的方案,其方案是在第一種的基礎上進行改善優化,流程如下:
-
先刪除緩存
-
再寫數據庫
-
休眠x秒,再刪除緩存
這個休眠是為什么呢,為了解決數據庫寫入時主從庫之間同步的時間差異,確保讀請求結束,寫請求可以刪除讀請求造成的緩存臟數據。這個休眠的時間取決於項目讀數據業務邏輯的耗時
針對上面的延遲雙刪的情況,還可以進行一些優化:
1、針對第三步的刪除緩存的可以進行異步刪除,這樣的話就無需每次進行休眠,從而提高吞吐量,提高性能。
2、如果擔心刪除失敗的話,可以考慮添加重試機制,如:重新測試三次失敗后,如果還不行的話,可以再丟進隊列,等下次的重試。
歡迎下方交流討論。如果本篇博客有任何錯誤,請批評指教,不勝感激 !
共同進步,學習分享
覺得寫的還不錯的就點個贊,加個關注唄!持續更新 !!! 點關注,不迷路,小楊帶你上高速
已經為大家整理好了幾百本各類技術電子書和5T的資源、最新的面試題,注公眾號【寫代碼的小楊】回復【資料】無套路領取