Redis和數據庫如何保證數據一致性


一.問題簡

在並發低、用戶少的情況下,每次查詢都能去Mysql查詢數據返回,但在高並發情況下,每一個讀請求都到Mysql去查詢會導致數據庫壓力太大。

所以一般會使用Redis做一個緩沖,減輕數據庫的壓力:

正常情況下,使用Redis緩存數據流程如下:

正常的讀請求該模式不會有問題,但是如果數據庫信息有改動,那么數據庫和Redis的數據一致性如何保證?

按我們常規的邏輯,數據庫修改后去刪除Redis的key即可。

其實不管是先刪Redis再修改庫,還是先修改庫再刪Redis都會有問題,因為讀線程和寫線程是並發的,無法保證其執行順序。

1.如果先刪Redis緩存,再寫庫。在刪除Redis緩存后,寫線程還沒來得及修改數據,這時讀線程發現緩存為空,則取讀取了臟數據。

2.如果先修改數據,在刪Redis緩存。在修改數據后如果線程宕機,那么Redis緩存刪除失敗,也會出現臟數據。

二.延時雙刪策略+設置緩存過期時間

所謂雙刪策略,就是在更新庫的前后都進行Redis緩存的刪除,但是更新后的刪除時延時刪除,偽代碼如下:

public void update(){
  //1.刪除Redis緩存
  redisTemplate.delete(key);
  //2.更新數據庫
  mysqlConnection.update();
  //3.延時刪除
  Thread.sleep(200);
  redisTemplate.delete(key);
}

 等待的時間如何確定

等待的時間為讀線程讀取數據的一個耗時,包括Redis主從同步,網絡耗時等。

為什么要使用延時刪除

為了防止在更新數據的過程中有讀線程進來緩存數據,所以更新后估算一個時間再刪除Redis緩存。

為什么要設置緩存過期時間

設置緩存時間是保證數據一致性的最終解決方案,因為在最壞情況下,臟數據的時間最多為設置的過期時間。過期后讀線程會到數據庫讀取新數據。

該方案有什么弊端

1. 最壞情況是在一個過期時間內會存在臟數據。

2. 因為有延時,所以增加的寫線程的執行時間。

三.基於訂閱binglog的同步機制

后續完善


免責聲明!

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



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