保持MySQL和Redis中的資料一致

山有木xi發表於2020-04-02

在高併發的業務場景下,MySQL和Redis的資料一致性就顯得很重要了,多次訪問MySQL就會導致奔潰或者延緩速度,而快取Redis過多也會出問題,那就是丟資料,存著存著,資料就丟了

Redis 在網際網路行業中使用最為廣泛。在很多時候也被稱為“記憶體資料庫”,它集合了快取和資料庫的優勢,但並非開啟持久化和主備同步機制就可以高枕無憂。

寫入資料庫成功,即讓快取失效,下一次讀取時再快取。這是快取的實時策略。

從架構設計的角度思考:快取就是快取,快取資料會隨時丟失,快取存在的目的是攔截到資料庫的請求,相比資料的可靠性、一致性,還是吞吐量、穩定性優先。

在考慮資料一致性的問題上由三種重新整理策略

  1. 實時策略

  2. 非同步策略

  3. 定時策略

實時策略是最常用的策略,能夠讓使用者有最好的體驗,但是一旦資料量過大就會出現,資料苦往往會受不了

非同步策略適用於,資料量大,但是資料並不重要,因為可能會導致髒資料或者資料丟失

定時策略適用於,資料量大,資料也很重要的情況下,這也是最穩定的方案

讀取的過程,應用程式先從 cache 取資料,沒有得到,則從資料庫中取資料,成功後,放到快取中。如果命中,應用程式從 cache 中取資料,取到後返回。

寫入的過程,把資料存到資料庫中,成功後,再刪除快取,刪除後下次讀取的時候,會被寫入快取。

從使用者體驗的角度,應該資料庫有了寫入,就馬上廢棄快取,觸發一次資料庫的讀取,從而更新快取。

然而,這和高併發就矛盾了——如果所有的都實時從資料庫裡面讀取,高併發場景下,資料庫往往受不了。

在讀取寫入資料時,適用定時策略一般不會出問題

  1. MySQL持久化資料,Redis只讀資料

  2. MySQL和Redis處理不同的資料型別
    MySQL處理實時性資料,Redis處理對實時性要求並不是很高的資料。在併發不高的情況下,讀取操作優先讀取redis,不存在的話再去訪問MySQL,並把讀取到的資料寫回Redis中;寫入操作直接寫MySQL,然後後再寫入Redis。在併發高的情況下,讀取操作和上面一樣,寫入操作則使用非同步寫入,先寫入Redis後直接返回,然後定時定期的寫入MySQL

而一旦涉及到更新資料,就容易出現快取和資料庫之間的資料一致性的問題,不管是先寫入資料庫再刪除快取,還是先刪除快取再寫入資料庫,都有可能出現資料不一致的情況,例如:

  • 先寫入資料庫,再刪除快取前,執行緒當機了,沒有刪除掉快取,就會出現資料不一致的情況

  • 先刪除Redis,還沒來得及寫入資料庫,另外一個執行緒就來讀取,發現快取為空,這個時候就會跑去資料庫讀取資料寫入快取,這個時候快取中的資料就是髒資料

因為寫入和讀取是併發的,沒有辦法保證順序,就會出現快取和資料庫的資料是不一致的問題,這時候就可以使用

延時雙刪策略

在寫庫前後都進行Redis.del(key)操作,並且設定合理地超時時間

  1. 先刪快取

  2. 再寫資料庫

  3. 休眠一段時間

  4. 再刪快取

設定快取的過期時間

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




來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69917874/viewspace-2684139/,如需轉載,請註明出處,否則將追究法律責任。

相關文章