在高並發的場景下,數據庫處理數據增刪改查很是薄弱。有一些數據查詢的頻率遠大於修改頻率,就需要使用緩存技術,讓先去請求redis,redis存在返回緩存數據,redis不存在就查詢數據庫,返回數據的同時將數據緩存到redis中。
問題
讀取緩存一般沒有什么問題,一旦涉及到數據更新:數據庫或者緩存更新,就容易出現緩存和數據庫數據不一致情況。首先,數據“一致性”包含兩種情況:
- 緩存有數據,那么緩存的值和數據庫中的值相同。
- 緩存沒有數據,那么,數據庫中的值必須是最新值。
在高並發的情況下,不管是先寫數據庫,再刪緩存;還是先刪緩存,再寫數據庫,都有可能出現數據不一致的情況,比如:
- 如果刪除了緩存redis,還沒來得及寫庫mysql,另一個線程就讀取,發現緩存為空,則去數據庫讀取數據寫入緩存,此時緩存中的數據為臟數據。
- 如果寫了庫,在刪除緩存前,寫庫的線程宕機了,也會出現數據不一致的情況。
解決辦法
延遲雙刪策略
1、先刪除緩存
2、再寫數據庫
3、休眠500ms(根據統計線程讀取數據和寫緩存的時間)
(休眠的作用是當前線程等其他線程讀完了數據后寫入緩存后,刪除緩存)
4、再刪除緩存
設置緩存過期時間
總結
先清除緩存,然后再寫入數據庫。有可能存在刪除緩存以后,另一個線程讀取數據,發現沒有數據,就去數據讀取數據,然后寫入緩存中,此時緩存中的數據為臟數據;
解決辦法:
- 先刪除緩存
- 再寫入數據庫
- 休眠500ms
- 刪除緩存
其中第三步驟的500ms,是根據業務讀取數據平均耗時,這樣做的目的是確保讀請求可以結束,寫請求可以刪除讀請求造成的臟數據的問題。
