09丨缓存异常:如何解决缓存和数据库的数据不一致问题
生活随笔
收集整理的這篇文章主要介紹了
09丨缓存异常:如何解决缓存和数据库的数据不一致问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.緩存和數據庫的數據不一致是如何發(fā)生的?
??首先,我們得清楚“數據的一致性”具體是啥意思。其實,這里的“一致性”包含了兩種情況:
- 緩存中有數據,那么,緩存的數據值需要和數據庫中的值相同;
- 緩存中本身沒有數據,那么,數據庫中的值必須是最新值。
??對于讀寫緩存來說,如果要對數據進行增刪改,就需要在緩存中進行,同時還要根據采取的寫回策略,決定是否同步寫回到數據庫中。
同步直寫策略:寫緩存時,也同步寫數據庫,緩存和數據庫中的數據一致;
- 異步寫回策略:寫緩存時不同步寫數據庫,等到數據從緩存中淘汰時,再寫回數據庫。使用這種策略時,
- 如果數據還沒有寫回數據庫,緩存就發(fā)生了故障,那么,此時,數據庫就沒有最新的數據了。
2. 如何解決數據不一致問題?
??重試機制具體來說,可以把要刪除的緩存值或者是要更新的數據庫值暫存到消息隊列中(例如使用Kafka 消息隊列)。當應用沒有能夠成功地刪除緩存值或者是更新數據庫值時,可以從消息隊列中重新讀取這些值,然后再次進行刪除或更新。
??當有大量并發(fā)請求時,應用還是有可能讀到不一致,按照不同的刪除和更新順序,分成兩種情況來看。在這兩種情況下,我們的解決方法也有所不同。
情況一:先刪除緩存,再更新數據庫。
??假設線程 A 刪除緩存值后,還沒有來得及更新數據庫(比如說有網絡延遲),線程 B 就開始讀取數據了,那么這個時候,線程 B 會發(fā)現緩存缺失,就只能去數據庫讀取。這會帶來兩個問題:
- 線程 B 讀取到了舊值;
- 線程 B 是在緩存缺失的情況下讀取的數據庫,所以,它還會把舊值寫入緩存,這可能會導致其他線程從緩存中讀到舊值。
在線程 A 更新完數據庫值以后,我們可以讓它先 sleep 一小段時間,再進行一次緩存刪除操作。
情況二:先更新數據庫值,再刪除緩存值。
??如果線程 A 刪除了數據庫中的值,但還沒來得及刪除緩存值,線程 B 就開始讀取數據了,那么此時,線程 B 查詢緩存時,發(fā)現緩存命中,就會直接從緩存中讀取舊值。不過,在這種情況下,如果其他線程并發(fā)讀緩存的請求不多,那么,就不會有很多請求讀取到舊值。而且,線程 A 一般也會很快刪除緩存值,這樣一來,其他線程再次讀取時,就會發(fā)生緩存缺失,進而從數據庫中讀取最新值。所以,這種情況對業(yè)務的影響較小。
??對于讀寫緩存來說,如果我們采用同步寫回策略,那么可以保證緩存和數據庫中的數據一致。只讀緩存的情況比較復雜,我總結了一張表,以便于你更加清晰地了解數據不一致的問題原因、現象和應對方案。
3. 如何解決緩存雪崩、擊穿、穿透
總結
以上是生活随笔為你收集整理的09丨缓存异常:如何解决缓存和数据库的数据不一致问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 08 | 替换策略: 缓存满了怎么办?
- 下一篇: 10丨 Redis主从同步与故障切换,有