如何保障mysql和redis之間的資料一致性

2022-09-19 10:39:11 字數 3102 閱讀 6989

**

在高併發的業務場景下,資料庫大多數情況都是使用者併發訪問最薄弱的環節。所以,就需要使用redis做乙個緩衝操作,讓請求先訪問到redis,而不是直接訪問mysql等資料庫。這樣可以大大緩解資料庫的壓力。redis快取資料的載入可以分為懶載入和主動載入兩種模式,下面分別介紹在這兩種模式下的資料一致性如何處理。

讀取快取步驟一般沒有什麼問題,但是一旦涉及到資料更新:資料庫和快取更新,就容易出現快取和資料庫間的資料一致性問題。不管是先寫資料庫,再刪除快取;還是先刪除快取,再寫庫,都有可能出現資料不一致的情況。舉個例子:

如果刪除了快取redis,還沒有來得及寫庫mysql,另乙個執行緒就來讀取,發現快取為空,則去資料庫中讀取資料寫入快取,此時快取中為髒資料。

如果先寫了庫,在刪除快取前,寫庫的執行緒宕機了,沒有刪除掉快取,則也會出現資料不一致情況。

因為寫和讀是併發的,沒法保證順序,就會出現快取和資料庫的資料不一致的問題。如何解決?

所以結合前面例子的兩種刪除情況,我們就考慮前後雙刪加懶載入模式。那麼什麼是懶載入?就是當業務讀取資料的時候再從儲存層載入的模式,而不是更新後主動重新整理,它涉及的業務流程如下如所示:

理解了懶載入機制後,結合上面的業務流程圖,我們講解下前後雙刪如何做?

延遲雙刪

在寫庫前後都進行redis.del(key)操作,並且第二次刪除通過延遲的方式進行。

方案一(一種思路,不嚴謹)具體步驟是:

1)先刪除快取;

2)再寫資料庫;

3)休眠500毫秒(根據具體的業務時間來定);

4)再次刪除快取。

那麼,這個500毫秒怎麼確定的,具體該休眠多久呢?

需要評估自己的專案的讀資料業務邏輯的耗時。這麼做的目的,就是確保讀請求結束,寫請求可以刪除讀請求造成的快取髒資料。

方案二,非同步延遲刪除:

1)先刪除快取;

2)再寫資料庫;

3)觸發非同步寫人序列化mq(也可以採取一種key+version的分布式鎖);

4)mq接受再次刪除快取。

非同步刪除對線上業務無影響,序列化處理保障併發情況下正確刪除。

為什麼要雙刪?

雙刪失敗如何處理?

1、設定快取過期時間

從理論上來說,給快取設定過期時間,是保證最終一致性的解決方案。所有的寫操作以資料庫為準,只要到達快取過期時間,則後面的讀請求自然會從資料庫中讀取新值然後回填快取。

結合雙刪策略+快取超時設定,這樣最差的情況就是在超時時間內資料存在不一致。

2、重試方案

重試方案有兩種實現,一種在業務層做,另外一種實現中介軟體負責處理。

業務層實現重試如下:

1)更新資料庫資料;

2)快取因為種種問題刪除失敗;

3)將需要刪除的key傳送至訊息佇列;

4)自己消費訊息,獲得需要刪除的key;

5)繼續重試刪除操作,直到成功。

然而,該方案有乙個缺點,對業務線**造成大量的侵入。於是有了方案二,在方案二中,啟動乙個訂閱程式去訂閱資料庫的binlog,獲得需要操作的資料。在應用程式中,另起一段程式,獲得這個訂閱程式傳來的資訊,進行刪除快取操作。

中介軟體實現重試如下:

流程說明:

1)更新資料庫資料;

2)資料庫會將操作資訊寫入binlog日誌當中;

3)訂閱程式提取出所需要的資料以及key;

4)另起一段非業務**,獲得該資訊;

5)嘗試刪除快取操作,發現刪除失敗;

6)將這些資訊傳送至訊息佇列;

7)重新從訊息佇列中獲得該資料,重試操作。

主動載入模式就是在db更新的時候同步或者非同步進行快取更新,常見的模式如下:

寫流程:

第一步先刪除快取,刪除之後再更新db,之後再非同步將資料刷回快取。

讀流程:

第一步先讀快取,如果快取沒讀到,則去讀db,之後再非同步將資料刷回快取。

這種模式簡單易用,但是它有乙個致命的缺點就是併發會出現髒資料。

試想一下,同時有多個伺服器的多個執行緒進行』步驟1.2更新db』,更新db完成之後,它們就要進行非同步刷快取,我們都知道多伺服器的非同步操作,是無法保證順序的,所以後面的重新整理操作存在相互覆蓋的併發問題,也就是說,存在先更新的db操作,反而很晚才去重新整理快取,那這個時候,資料也是錯的。

讀寫併發:再試想一下,伺服器a在進行』讀操作』,在a伺服器剛完成2.2時,伺服器b在進行』寫操作』,假設b伺服器1.3完成之後,伺服器a的2.3才被執行,這個時候就相當於更新前的老資料寫入快取,最終資料還是錯的。

而對於這種髒資料的產生歸其原因還是在於這種模式的主動重新整理快取屬於非冪等操作,那麼要解決這個問題怎麼辦?

前面介紹的雙刪操作方案,因為刪除每次操作都是無狀態的,所以是冪等的。

將重新整理操作序列處理。

這裡把基於序列處理的重新整理操作方案介紹一下:

寫流程:

第一步先刪除快取,刪除之後再更新db,我們監聽從庫(資源少的話主庫也ok)的binlog,通過分析binlog我們解析出需要需要重新整理的資料標識,然後將資料標識寫入mq,接下來就消費mq,解析mq訊息來讀庫獲取相應的資料重新整理快取。

關於mq序列化,大家可以去了解一下 kafka partition 機制 ,這裡就不詳述了。

讀流程:

第一步先讀快取,如果快取沒讀到,則去讀db,之後再非同步將資料標識寫入mq(這裡mq與寫流程的mq是同乙個),接下來就消費mq,解析mq訊息來讀庫獲取相應的資料重新整理快取。

懶載入模式快取可採取雙刪+ttl失效來實現;

雙刪失敗情況下可採取重試措施,重試有業務通過mq重試以及元件消費mysql的binlog再寫入mq重試兩種方式;

主動載入由於操作本身不具有冪等性,所以需要考慮載入的有序性問題,採取mq的分割槽機制實現序列化處理,實現快取和mysql資料的最終一致,此時讀和寫操作的快取載入事件是走的同乙個mq。

如何保障業務安全

保障業務安全是企業發展的基礎。而面對如此複雜的安全危機,靠人力是永遠無法保障的。唯一的途徑就是完善網路自身的安全效能。通過技術保障的網路安全的同時,配合網路安全解決方案提供商的商務安全策略和技術支援服務,加強管理和安全策略的制定。乙個業務安全永續的商務藍圖完全可以實現。當然,網路業務安全,加強管理也...

如何保障資料安全

企業無需對資料中心機櫃或機架進行全面改造,即可進行更好的機架級控制和審計。選擇附件的良好試驗計畫可以為組織提供所需的實際操作,以確保在準備執行更完整的部署時取得成功。資料中心管理人員每天都會時刻關注資料中心的安全運營情況。因此無論如何,安全性是其最重要的關注事項 保持網路安全,保障資產不受網路攻擊的...

如何保障微服務安全

原文 securing microservices摘要 如何保護微服務,確保微服務的安全,作者從保護應用程式安全和保護容器的安全兩個方面進行了闡述,以下是譯文 實現乙個微服務很難。部署乙個微服務應用程式複雜性也很高。保護微服務的安全就更難更複雜。從 開始呢?腦海中首先出現的一些詞是身份驗證和授權 防...