精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

先操作緩存還是先操作數據庫?

jf_78858299 ? 來源:蟬沐風的碼場 ? 作者:蟬沐風 ? 2023-03-03 10:28 ? 次閱讀

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

  • 如果緩存在Redis中存在,即緩存命中,則直接返回數據

圖片

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

圖片

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

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

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

一致性問題

但是,在Redis的key值未過期的情況下,用戶修改了個人信息,我們此時既要操作數據庫數據,也要操作Redis數據。現在我們面臨了兩種選擇:

  1. 先操作Redis的數據,再操作數據庫的數據
  2. 先操作數據庫的數據,再操作Redis的數據

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

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

下面我們來討論一下關于Redis和數據庫之間數據一致性的一些方案。

方案選擇

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

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

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

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

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

  1. 先更新緩存,再更新數據庫
  2. 先更新數據庫,再更新緩存

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

圖片

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

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

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

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

  • 先更新數據庫,再刪除緩存
  • 先刪除緩存,再更新數據庫

先更新數據庫,再刪除緩存

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

  1. 更新數據庫失敗,這時可以通過程序捕獲異常,直接返回結果,不再繼續刪除緩存,所以不會出現數據不一致的問題
  2. 更新數據庫成功,刪除緩存失敗。導致數據庫是最新數據,緩存中的是舊數據,數據不一致

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

失敗重試

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

圖片

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

異步更新緩存

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

總結

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

先刪除緩存,再更新數據庫

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

  1. 刪除緩存失敗,這時可以通過程序捕獲異常,直接返回結果,不再繼續更新數據庫,所以不會出現數據不一致的問題
  2. 刪除緩存成功,更新數據庫失敗。在多線程下可能會出現數據不一致的問題

圖片

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

圖片

用偽代碼表示就是:

/**
 * 延時雙刪
 * @author 公眾號【蟬沐風】
 */
public void update(String key, Object data) {
    // 首先刪除緩存
    redisCache.delKey(key);
    // 更新數據庫
    db.updateData(data);
    // 休眠一段時間,時間依據數據的讀取耗費的時間而定
    Thread.sleep(500);
    // 再次刪除緩存
    redisCache.delKey(key);
}
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數據
    +關注

    關注

    8

    文章

    6893

    瀏覽量

    88830
  • 緩存
    +關注

    關注

    1

    文章

    233

    瀏覽量

    26649
  • 數據庫
    +關注

    關注

    7

    文章

    3765

    瀏覽量

    64276
  • Redis
    +關注

    關注

    0

    文章

    371

    瀏覽量

    10846
收藏 人收藏

    評論

    相關推薦

    使用ADO操作數據庫

    使用ADO操作數據庫要運行程序必須將數據庫文件demo.mdb與可執行文件放在一起,如果在vc開發環境中運行,則需要將該數據庫文件放在工程目錄下
    發表于 10-15 11:41

    使用OLE DB操作數據庫

    使用OLE DB操作數據庫 要運行程序必須將數據庫文件students.mdb與可執行文件放在一起,如果在vc開發環境中運行,則需要將該數據庫文件放在工程目錄下
    發表于 10-15 11:41

    使用DAO操作數據庫

    使用DAO操作數據庫要運行程序必須將數據庫文件course.mdb與可執行文件放在一起,如果在vc開發環境中運行,則需要將該數據庫文件放在工程目錄下
    發表于 10-15 11:42

    labview遠程訪問數據庫操作數據庫

    各位高手:多指教,小弟請教一個問題:數據庫的基本操作現在已經實現。我現在想這樣做,想遠程連接數據庫并且操作數據庫文件,就是在同一局域網內的
    發表于 07-28 12:17

    《Dot.NET數據庫開發技術》操作數據庫.pdf

    《Dot.NET數據庫開發技術》操作數據庫.pdf[hide][/hide]
    發表于 06-23 16:27

    pymysql怎么簡單的操作數據庫

    pymysql簡單操作數據庫
    發表于 05-01 07:33

    python的操作數據庫

    python操作數據庫
    發表于 05-20 12:11

    Labsql不能操作數據庫連接池嗎

    如圖,好像連接字符串也只能指定provider才行,指定了max pool還是不會報錯。C#里for循環是會報錯的。還有一個問題,我要多線程操作數據庫,應該怎么玩?數據庫會錯亂嗎?有好多個工位會在不定時間里讀寫。請問應該怎么
    發表于 09-09 14:44

    使用SQL語句操作數據庫

    第一步:Linux開發環境搭建第二步:安裝sqlite數據庫第三步:sqlite數據庫使用1.sqlite部分命令2.使用SQL語句操作數據庫(1)創建一個數據表:student(2)
    發表于 11-04 06:23

    《Dot.NET數據庫開發技術》操作數據庫

    《Dot.NET數據庫開發技術》操作數據庫
    發表于 02-07 15:11 ?0次下載

    PHP的使用教程之操作數據庫的詳細資料說明

    本文檔的主要內容詳細介紹的是PHP的使用教程之操作數據庫的詳細資料說明包括了:1.掌握PHP連接數據庫的方法,2.掌握PHP創建一個數據庫以及表的方法,3.掌握PHP插入和讀取數據的方
    發表于 05-29 16:51 ?12次下載
    PHP的使用教程之<b class='flag-5'>操作數據庫</b>的詳細資料說明

    分布式系統中的數據庫緩存操作順序

    在分布式系統中,緩存數據庫同時存在時,如果有寫操作的時候,操作數據庫還是
    的頭像 發表于 05-03 14:36 ?2199次閱讀
    分布式系統中的<b class='flag-5'>數據庫</b>和<b class='flag-5'>緩存</b><b class='flag-5'>操作</b>順序

    操作數據庫還是操作緩存

    來源:撿田螺的小男孩 前言 在分布式系統中,緩存數據庫同時存在時,如果有寫操作操作數據庫還是
    的頭像 發表于 10-30 11:09 ?1985次閱讀
    <b class='flag-5'>先</b><b class='flag-5'>操作數據庫</b><b class='flag-5'>還是</b><b class='flag-5'>先</b><b class='flag-5'>操作</b><b class='flag-5'>緩存</b>?

    分布式系統中操作數據庫還是操作緩存

    前言 在分布式系統中,緩存數據庫同時存在時,如果有寫操作操作數據庫還是
    的頭像 發表于 09-30 14:46 ?1580次閱讀

    掃描操作數的信號上升沿

    使用“掃描操作數的信號上升沿”指令,可以確定所指定操作數)的信號狀態是否從“0”變為“1”。
    的頭像 發表于 06-27 09:39 ?2642次閱讀
    掃描<b class='flag-5'>操作數</b>的信號上升沿