如何解決Redis緩存和MySQL數據一致性的問題?

在高併發業務場景中,數據庫的性能瓶頸通常對於用戶的併發訪問而言太大。 因此,redis通常用作緩衝區操作,以允許請求首先訪問redis,而不是直接訪問數據庫(例如MySQL)。 這樣可以減少網絡請求的延遲響應。

數據為什麼會不一致

這類問題主要在於併發讀寫訪問,緩存和數據相互交叉執行。

一、單庫情況下

同一時間發生了併發讀寫請求,比如A(寫) ,B (讀),2個請求

如何解決Redis緩存和MySQL數據一致性的問題?


  • A請求發送一個寫的操作到服務端,第一步就會淘汰cache,然後因為各種原因卡住了,不在執行後面的大量業務(例:大量的業務操作、調用其他服務處理消耗了1s)。
  • B請求發送一個讀操作,這個時候會去讀cache,因為cache淘汰,所以為空
  • B請求繼續讀DB,讀出一個髒數據,並寫入cache
  • A請求終於執行完全,在寫入數據到DB中

總結:由於寫入數據最後已輸入到DB中,因此未同步。cache裡面就一直保持著髒數據。

髒數據是指源系統中的數據不在給定範圍內或對實際業務無意義,或者數據格式不合法,並且源系統中存在不規則性。 編碼和模糊的業務邏輯。


二、主從同步,讀寫分離的情況下,讀從庫而產生髒數據

如何解決Redis緩存和MySQL數據一致性的問題?

  • A請求發送一個寫操作到服務端,第一步就會淘汰掉cache
  • A請求寫主數據庫,往主數據庫寫了最新的數據。
  • B請求發送一個讀操作,讀cache,因為cache淘汰,所以為空
  • B請求繼續讀DB,這個時候讀的是從庫,此時主從同步還沒同步成功。讀出髒數據,然後髒數據寫入cache
  • 最後數據庫主從同步完成

總結:在這種情況下,請求A和請求B操作的時間可以。 這是主從同步(假設為1s)的延遲問題,它導致讀取請求從庫中讀取並讀取髒數據不一致

根本原因:

在單個庫中,邏輯處理消耗1s。 以1s的主從同步延遲,可以將舊數據讀入高速緩存

主從+讀寫分離。 從庫中讀取舊數據到緩存中

數據優化方案

如何解決Redis緩存和MySQL數據一致性的問題?

一、緩存雙淘汰法

  • 先淘汰緩存
  • 再寫數據庫
  • 將淘汰消息發送到消息總線esb,然後立即將其發送回。寫入請求處理時間幾乎沒有增加,並且此方法淘汰了緩存兩次。因此,被稱為“緩存雙淘汰法“,並且在消息總線的下游,有一個異步淘汰緩存的消費者,在拿到淘汰消息在1s後淘汰緩存,這樣,即使在1秒內有髒數據入緩存,也能夠被淘汰掉。

二、異步淘汰緩存

以上步驟都是在業務線中執行的,增加了一個線下的讀取binlog異步淘汰緩存模塊,在讀取binlog總的數據,然後進行異步淘汰。

如何解決Redis緩存和MySQL數據一致性的問題?

1.思路:

MySQL binlog增量發佈訂閱消耗+消息隊列+增量數據更新到redis

1)讀取請求轉到Redis:熱數據基本上在Redis

2)寫入請求轉到MySQL:增加刪除和 修改MySQL

3)更新Redis數據:MySQ數據操作binlog更新為Redis

2.Redis更新

1)數據操作主要有兩塊:

  • 一個是全量(將全部數據一次寫入到redis)
  • 一個是增量(實時更新)

這裡說的是增量,指mysql的更新,插入和刪除,以更改數據

這樣,一旦MySQL中發生新的寫入,更新,刪除和其他操作,就可以將與Binlog相關的消息推送到Redis,然後Redis會根據binlog中的記錄來更新Redis。 無需處理業務線中的緩存內容。


以上是本文的全部內容,希望對大家的學習有幫助,也希望大家多多支持

php自學中心


分享到:


相關文章: