欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MySQL和Redis的數(shù)據(jù)一致性問題

 更新時間:2022年04月02日 09:08:19   作者:蟬沐風_  
這篇文章主要介紹了MySQL和Redis的數(shù)據(jù)一致性問題,下面文章圍繞Redis大的相關資料展開詳情,需要的小伙伴可以參考一下

前言:

在數(shù)據(jù)讀多寫少的情況下作為緩存來使用,恐怕是Redis使用最普遍的場景了。當使用Redis作為緩存的時候,一般流程是這樣的。

  • 如果緩存在Redis中存在,即緩存命中,則直接返回數(shù)據(jù)

MySQL和Redis的數(shù)據(jù)一致性問題_數(shù)據(jù)

  • 如果Redis中沒有對應緩存,則需要直接查詢數(shù)據(jù)庫,然后存入Redis,最后把數(shù)據(jù)返回

MySQL和Redis的數(shù)據(jù)一致性問題_數(shù)據(jù)_02

通常情況下,我們會為某個緩存設置一個key值,并針對key值設置一個過期時間,如果被查詢的數(shù)據(jù)對應的key過期了,則直接查詢數(shù)據(jù)庫,并將查詢得到的數(shù)據(jù)存入Redis,然后重置過期時間,最后將數(shù)據(jù)返回,偽代碼如下:

/**
 * 根據(jù)用戶名獲取用戶詳細信息
 * @author 公眾號【蟬沐風】
 */
public User getUserInfo(String userName) {
      User user = redisCache.getName("user:" + userName);
      if (user != null) {
          return user;
      }

      // 從數(shù)據(jù)庫中直接搜索
      user = selectUserByUserName(userName);
      // 將數(shù)據(jù)寫入Redis,并設置過期時間
      redisCache.set("user:" + userName, user, 30000);
      // 返回數(shù)據(jù)
      return user;
}

一、一致性問題

但是,在Redis的key值未過期的情況下,用戶修改了個人信息,我們此時既要操作數(shù)據(jù)庫數(shù)據(jù),也要操作Redis數(shù)據(jù)?,F(xiàn)在我們面臨了兩種選擇:

  • 先操作Redis的數(shù)據(jù),再操作數(shù)據(jù)庫的數(shù)據(jù)
  • 先操作數(shù)據(jù)庫的數(shù)據(jù),再操作Redis的數(shù)據(jù)

如論選擇哪種方法,最理想的情況下,兩個操作要么同時成功,要么同時失敗,否則就會出現(xiàn)Redis和數(shù)據(jù)庫數(shù)據(jù)不一致的情況。

遺憾的是,目前沒有什么框架能夠保證Redis的數(shù)據(jù)和數(shù)據(jù)庫的數(shù)據(jù)的完全一致性。我們只能根據(jù)場景和所需要付出的代碼來采取一定的措施降低數(shù)據(jù)不一致出現(xiàn)的概率,在一致性和性能之間取得一個折中。

下面我們來討論一下關于Redis和數(shù)據(jù)庫質檢數(shù)據(jù)一致性的一些方案。

二、方案選擇

1、是刪除緩存還是更新緩存?

當數(shù)據(jù)庫數(shù)據(jù)發(fā)生變化的時候,Redis的數(shù)據(jù)也需要進行相應的操作,那么這個「操作」到底是用「更新」還是用「刪除」呢?

「更新」的話調用Redis的set方法,新值替換舊值;「刪除」直接刪除原來的緩存,下次查詢的時候重新讀取數(shù)據(jù)庫,然后再更新Redis。

結論:推薦直接使用「刪除」操作。

因為使用「更新」操作的話,你會面臨兩種選擇

  • 先更新緩存,再更新數(shù)據(jù)庫
  • 先更新數(shù)據(jù)庫,再更新緩存

第1種不用考慮了,下面討論一下「先更新數(shù)據(jù)庫,再更新緩存」這種方案。

MySQL和Redis的數(shù)據(jù)一致性問題_redis_03

如果線程1和線程2同時進行更新操作,但是每個線程的執(zhí)行順序如上圖所示,此時就會導致數(shù)據(jù)不一致,因此從這個角度上我們推薦直接使用刪除緩存的方式。

此外,推薦使用「刪除緩存」還有兩點原因。

  • 如果寫數(shù)據(jù)庫的場景比讀數(shù)據(jù)場景多,采用這種方案就會導致緩存就被頻繁寫入,浪費性能;
  • 如果緩存要經過一系列復雜的計算才能得到,那么每次寫入數(shù)據(jù)庫后,都再次計算寫入的緩存無疑也是浪費性能的。

明確這個問題之后,擺在我們面前的就只有兩個選擇了:

  • 先更新數(shù)據(jù)庫,再刪除緩存
  • 先刪除緩存,再更新數(shù)據(jù)庫

2、先更新數(shù)據(jù)庫,再刪除緩存

這種方式可能存在以下兩種異常情況

  • 更新數(shù)據(jù)庫失敗,這時可以通過程序捕獲異常,直接返回結果,不再繼續(xù)刪除緩存,所以不會出現(xiàn)數(shù)據(jù)不一致的問題
  • 更新數(shù)據(jù)庫成功,刪除緩存失敗。導致數(shù)據(jù)庫是最新數(shù)據(jù),緩存中的是舊數(shù)據(jù),數(shù)據(jù)不一致

第2種情況應該怎么辦呢?我們有兩種方式:失敗重試異步更新。

3、失敗重試

如果刪除緩存失敗,我們可以捕獲這個異常,把需要刪除的 key 發(fā)送到消息隊列。自己創(chuàng)建一個消費者消費,嘗試再次刪除這個 key,直到刪除成功為止。

MySQL和Redis的數(shù)據(jù)一致性問題_一致性問題_04

這種方式有個缺點,首先會對業(yè)務代碼造成入侵,其次引入了消息隊列,增加了系統(tǒng)的不確定性。

4、異步更新緩存

因為更新數(shù)據(jù)庫時會往 binlog 中寫入日志,所以我們可以啟動一個監(jiān)聽 binlog變化的服務(比如使用阿里的 canal開源組件),然后在客戶端完成刪除 key 的操作。如果刪除失敗的話,再發(fā)送到消息隊列。

總結

總之,對于刪除緩存失敗的情況,我們的做法是不斷地重試刪除操作,直到成功。無論是重試還是異步刪除,都是最終一致性的思想。

5、、先刪除緩存,再更新數(shù)據(jù)庫

這種方式可能存在以下兩種異常情況:

  • 刪除緩存失敗,這時可以通過程序捕獲異常,直接返回結果,不再繼續(xù)更新數(shù)據(jù)庫,所以不會出現(xiàn)數(shù)據(jù)不一致的問題
  • 刪除緩存成功,更新數(shù)據(jù)庫失敗。在多線程下可能會出現(xiàn)數(shù)據(jù)不一致的問題

MySQL和Redis的數(shù)據(jù)一致性問題_緩存_05

這時,Redis中存儲的舊數(shù)據(jù),數(shù)據(jù)庫的值是新數(shù)據(jù),導致數(shù)據(jù)不一致。這時我們可以采用延時雙刪的策略,即更新數(shù)據(jù)庫數(shù)據(jù)之后,再刪除一次緩存。

MySQL和Redis的數(shù)據(jù)一致性問題_緩存_06

用偽代碼表示就是:

/**
 * 延時雙刪
 * @author 公眾號【蟬沐風】
 */
public void update(String key, Object data) {
    // 首先刪除緩存
    redisCache.delKey(key);
    // 更新數(shù)據(jù)庫
    db.updateData(data);
    // 休眠一段時間,時間依據(jù)數(shù)據(jù)的讀取耗費的時間而定
    Thread.sleep(500);
    // 再次刪除緩存
    redisCache.delKey(key);
}

到此這篇關于MySQL和Redis的數(shù)據(jù)一致性問題的文章就介紹到這了,更多相關MySQL和Redis內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • MySQL的重裝問題解決方法

    MySQL的重裝問題解決方法

    最近在工作上遇到了MySQL重裝的問題,今天記錄一下我的解決過程。不論我用控制面板的卸載刪除程序方式還是安全衛(wèi)士的卸載,都會遇到一個問題,就是安裝到如下圖位置,server start時就程序無響應了,一直死在那里
    2013-04-04
  • MySQL5.6.22安裝配置方法圖文教程

    MySQL5.6.22安裝配置方法圖文教程

    這篇文章主要為大家詳細介紹了MySQL5.6.22安裝配置方法圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Mysql外鍵設置中的CASCADE、NO ACTION、RESTRICT、SET NULL

    Mysql外鍵設置中的CASCADE、NO ACTION、RESTRICT、SET NULL

    本文主要介紹了Mysql外鍵設置中的CASCADE、NO ACTION、RESTRICT、SET NULL,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • mysql的sql語句特殊處理語句總結(必看)

    mysql的sql語句特殊處理語句總結(必看)

    下面小編就為大家?guī)硪黄猰ysql的sql語句特殊處理語句總結(必看)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • 利用frm和ibd文件恢復mysql表數(shù)據(jù)的詳細過程

    利用frm和ibd文件恢復mysql表數(shù)據(jù)的詳細過程

    總是遇到mysql服務意外斷開之后導致mysql服務無法正常運行的情況,使用Navicat工具查看能夠看到里面的庫和表,但是無法獲取數(shù)據(jù)記錄,提示數(shù)據(jù)表不存在,所以本文給大家介紹了利用frm和ibd文件恢復mysql表數(shù)據(jù)的詳細過程,需要的朋友可以參考下
    2024-04-04
  • MYSQL的binary解決mysql數(shù)據(jù)大小寫敏感問題的方法

    MYSQL的binary解決mysql數(shù)據(jù)大小寫敏感問題的方法

    BINARY不是函數(shù),是類型轉換運算符,它用來強制它后面的字符串為一個二進制字符串,可以理解為在字符串比較的時候區(qū)分大小寫
    2013-09-09
  • MySQL由淺入深探究存儲過程

    MySQL由淺入深探究存儲過程

    這篇文章主要介紹了MySQL存儲過程,存儲過程,也叫做存儲程序,是一條或者多條SQL語句的集合,可以視為批量處理,但是其作用不僅僅局限于批量處理
    2022-11-11
  • MacOS下mysql 8.0.18 安裝配置方法圖文教程

    MacOS下mysql 8.0.18 安裝配置方法圖文教程

    這篇文章主要介紹了MacOS下mysql 8.0.18 安裝配置方法圖文教程,并成功命令行操作,文中安裝步驟介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • php中如何將圖片儲存在數(shù)據(jù)庫里

    php中如何將圖片儲存在數(shù)據(jù)庫里

    php中如何將圖片儲存在數(shù)據(jù)庫里...
    2007-03-03
  • MySQL中datetime和timestamp的區(qū)別及使用詳解

    MySQL中datetime和timestamp的區(qū)別及使用詳解

    這篇文章主要介紹了MySQL中datetime和timestamp的區(qū)別及使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-11-11

最新評論