MySQL與Redis如何保證數據的一致性

文章目錄

  • MySQL與Redis如何保證數據的一致性?
    • 不好的方案
      • 1. 先寫 MySQL,再寫 Redis
      • 2. 先寫 Redis,再寫 MySQL
      • 3. 先刪除 Redis,再寫 MySQL
    • 好的方案
      • 4. 先刪除 Redis,再寫 MySQL,再刪除 Redis
      • 5. 先寫 MySQL,再刪除 Redis
      • 6. 先寫 MySQL,通過 Binlog,異步更新 Redis
    • 幾種方案比較

MySQL與Redis如何保證數據的一致性?

之前也看了很多相關的文章,但是感覺講的都不好,很多文章都會去講各種策略,比如(旁路緩存)策略、(讀穿 / 寫穿)策略和(寫回)策略等,感覺意義真的不大,然后有的文章也只講了部分情況,也沒有告訴最優解。

我直接先拋一下結論:在滿足實時性的條件下,不存在兩者完全保存一致的方案,只有最終一致性方案。 根據網上的眾多解決方案,總結出 6 種,直接看目錄:

在這里插入圖片描述

不好的方案

1. 先寫 MySQL,再寫 Redis

在這里插入圖片描述

圖解說明:

  • 這是一副時序圖,描述請求的先后調用順序;
  • 橘黃色的線是請求 A,黑色的線是請求 B;
  • 橘黃色的文字,是 MySQL 和 Redis 最終不一致的數據;
  • 數據是從 10 更新為 11;
  • 后面所有的圖,都是這個含義,不再贅述。

請求 A、B 都是先寫 MySQL,然后再寫 Redis,在高并發情況下,如果請求 A 在寫 Redis 時卡了一會,請求 B 已經依次完成數據的更新,就會出現圖中的問題。

這個圖已經畫的很清晰了,我就不用再去啰嗦了吧,不過這里有個前提,就是對于讀請求,先去讀 Redis,如果沒有,再去讀 DB,但是讀請求不會再回寫 Redis。 大白話說一下,就是讀請求不會更新 Redis。

2. 先寫 Redis,再寫 MySQL

在這里插入圖片描述

3. 先刪除 Redis,再寫 MySQL

這幅圖和上面有些不一樣,前面的請求 A 和 B 都是更新請求,這里的請求 A 是更新請求,但是請求 B 是讀請求,且請求 B 的讀請求會回寫 Redis。 在這里插入圖片描述

請求 A 先刪除緩存,可能因為卡頓,數據一直沒有更新到 MySQL,導致兩者數據不一致。

這種情況出現的概率比較大,因為請求 A 更新 MySQL 可能耗時會比較長,而請求 B 的前兩步都是查詢,會非常快。

好的方案

4. 先刪除 Redis,再寫 MySQL,再刪除 Redis

對于“先刪除 Redis,再寫 MySQL”,如果要解決最后的不一致問題,其實再對 Redis 重新刪除即可,這個也是大家常說的“緩存雙刪”。

在這里插入圖片描述

為了便于大家看圖,對于藍色的文字,“刪除緩存 10”必須在“回寫緩存10”后面,那如何才能保證一定是在后面呢?網上給出的第一個方案是,讓請求 A 的最后一次刪除,等待 500ms。

對于這種方案,看看就行,反正我是不會用,太 Low 了,風險也不可控。

那有沒有更好的方案呢,我建議異步串行化刪除,即刪除請求入隊列

在這里插入圖片描述

異步刪除對線上業務無影響,串行化處理保障并發情況下正確刪除。

如果雙刪失敗怎么辦,網上有給 Redis 加一個緩存過期時間的方案,這個不敢茍同。個人建議整個重試機制,可以借助消息隊列的重試機制,也可以自己整個表,記錄重試次數,方法很多。

簡單小結一下:

  • “緩存雙刪”不要用無腦的 sleep 500 ms;
  • 通過消息隊列的異步&串行,實現最后一次緩存刪除;
  • 緩存刪除失敗,增加重試機制。

5. 先寫 MySQL,再刪除 Redis

在這里插入圖片描述

對于上面這種情況,對于第一次查詢,請求 B 查詢的數據是 10,但是 MySQL 的數據是 11,只存在這一次不一致的情況,對于不是強一致性要求的業務,可以容忍。(那什么情況下不能容忍呢,比如秒殺業務、庫存服務等。)

當請求 B 進行第二次查詢時,因為沒有命中 Redis,會重新查一次 DB,然后再回寫到 Reids。

那什么情況下會出現不一致的情況呢?

在這里插入圖片描述

這里需要滿足 2 個條件:

  • 緩存剛好自動失效;
  • 請求 B 從數據庫查出 10,回寫緩存的耗時,比請求 A 寫數據庫,并且刪除緩存的還長。

對于第二個條件,我們都知道更新 DB 肯定比查詢耗時要長,所以出現這個情況的概率很小,同時滿足上述條件的情況更小。

6. 先寫 MySQL,通過 Binlog,異步更新 Redis

這種方案,主要是監聽 MySQL 的 Binlog,然后通過異步的方式,將數據更新到 Redis,這種方案有個前提,查詢的請求,不會回寫 Redis。

在這里插入圖片描述

這個方案,會保證 MySQL 和 Redis 的最終一致性,但是如果中途請求 B 需要查詢數據,如果緩存無數據,就直接查 DB;如果緩存有數據,查詢的數據也會存在不一致的情況。

所以這個方案,是實現最終一致性的終極解決方案,但是不能保證實時性。

幾種方案比較

我們對比上面討論的 6 種方案:

1、先寫 Redis,再寫 MySQL

這種方案,我肯定不會用,萬一 DB 掛了,你把數據寫到緩存,DB 無數據,這個是災難性的;

我之前也見同學這么用過,如果寫 DB 失敗,對 Redis 進行逆操作,那如果逆操作失敗呢,是不是還要搞個重試?

2、先寫 MySQL,再寫 Redis

對于并發量、一致性要求不高的項目,很多就是這么用的,我之前也經常這么搞,但是不建議這么做;

當 Redis 瞬間不可用的情況,需要報警出來,然后線下處理。

3、先刪除 Redis,再寫 MySQL

這種方式,我還真沒用過,直接忽略吧。

4、先刪除 Redis,再寫 MySQL,再刪除 Redis

這種方式雖然可行,但是感覺好復雜,還要搞個消息隊列去異步刪除 Redis。

5、先寫 MySQL,再刪除 Redis

比較推薦這種方式,刪除 Redis 如果失敗,可以再多重試幾次,否則報警出來;

這個方案,是實時性中最好的方案,在一些高并發場景中,推薦這種。

6、先寫 MySQL,通過 Binlog,異步更新 Redis

對于異地容災、數據匯總等,建議會用這種方式,比如 binlog + kafka,數據的一致性也可以達到秒級;

純粹的高并發場景,不建議用這種方案,比如搶購、秒殺等。

個人結論:

  • 實時一致性方案:采用“先寫 MySQL,再刪除 Redis”的策略,這種情況雖然也會存在兩者不一致,但是需要滿足的條件有點苛刻,所以是滿足實時性條件下,能盡量滿足一致性的最優解。
  • 最終一致性方案:采用“先寫 MySQL,通過 Binlog,異步更新 Redis”,可以通過 Binlog,結合消息隊列異步更新 Redis,是最終一致性的最優解。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/165330.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/165330.shtml
英文地址,請注明出處:http://en.pswp.cn/news/165330.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C# 數據庫封裝

最近有些地方用到c#,研究了一下,也有數據庫方面的操作,那就繼續封裝,自己用起來好用一點。 數據庫連接 using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Text; using Sys…

Leetcode算法系列| 1. 兩數之和(四種解法)

目錄 1.題目2.題解解法一:暴力枚舉解法二:哈希表解法解法三:雙指針(有序狀態)解法四:二分查找(有序狀態) 1.題目 給定一個整數數組 nums 和一個整數目標值 target,請你在該數組中找出 和為目標值 target 的那 兩個 整數…

『RabbitMQ』入門指南(安裝,配置,應用)

前言 RabbitMQ 是在 AMQP(Advanced Message Queuing Protocol) 協議標準基礎上完整的,可復用的企業消息系統。它遵循 Mozilla Public License 開源協議,采用 Erlang 實現的工業級的消息隊列(MQ)服務器,建立在 Erlang …

產品經理提問常用的ChatGPT通用提示詞模板

如何評估產品市場的潛力和可行性? 如何定義和明確產品的目標用戶和需求? 如何進行競品分析和比較,制定產品的差異化策略? 如何設計產品的功能和特性,滿足用戶需求? 如何制定產品的定價策略和銷售計劃&a…

qml View3D使用介紹

在Qt Quick 3D中,View3D 是一個用于展示 3D 內容的 QML 類型。View3D 允許你將 3D 場景集成到 Qt Quick 2D 用戶界面中,這意味著你可以在傳統的 2D UI 元素(如按鈕、文本和圖像)與 3D 圖形之間無縫地進行整合。 View3D 提供了一個視口,用于渲染 3D 場景。它可以包括多個 …

HTTPS攻擊怎么防御?

HTTPS 簡介 超文本傳輸安全協議( HTTPS )是一種通過計算機網絡進行安全通信的傳輸協議。HTTPS 經由 HTTP 進行通信,但利用 SSL/TLS 來加密數據包。 HTTPS 開發的主要目的,是提供對網站服務器的身份認證,保護交換數據的…

批量將本地N個英文Html文檔進行中文翻譯-操作篇

Unity3D特效百例案例項目實戰源碼Android-Unity實戰問題匯總游戲腳本-輔助自動化Android控件全解手冊再戰Android系列Scratch編程案例軟考全系列Unity3D學習專欄藍橋系列ChatGPT和AIGC 👉關于作者 專注于Android/Unity和各種游戲開發技巧,以及各種資源分…

QtCreator9.02不支持JDK11解決

最終效果 使用Android Studio 下載Android SDK Platform 31與Sources for Android 31 下載Android SDK Build Tools 31.0.0 下載NDK 25.1 ,23.1 ,21.3 重要: 下載Android SDK Command-Line Tools ,選擇10.0或者9.0其中一個版本 其它版本不支持JDK11 ,本例選擇10.0 下載CMak…

如何進行MySQL的主從復制(MySQL5.7)

背景:在一些Web服務器開發中,系統用戶在進行數據訪問時,基本都是直接操作數據庫MySQL進行訪問,而這種情況下,若只有一臺MySQL服務器,可能會存在如下問題 數據的讀和寫的所有壓力都會由一臺數據庫獨…

淺析jdk8所包含的主要特性

至今Java 8仍然是許多開發者首選的JDK版本,Java 8的生態系統非常成熟,許多庫和框架都已經適配了Java 8。遷移到新的Java版本可能需要重新評估和調整現有的依賴關系,這對于一些大型項目可能是一個挑戰。那么Java 8有哪些特性讓多數開發者鐘愛呢…

西米支付:如何設計和構建游戲支付系統?

如何設計和構建游戲支付系統? 目前,游戲開發中最常見的支付方式包括微信支付、支付寶支付和蘋果支付等。今天,我將與大家分享游戲支付系統的架構和設計。 游戲支付的主要業務流程是指游戲玩家在游戲中購買虛擬物品或服務所進行的支付過程。一…

ElasticSearch 7 SQL 詳解

平時使用Elasticsearch的時候,會在Kibana中使用Query DSL來查詢數據.每次要用到Query DSL時都基本忘光了,需要重新在回顧一遍,最近發現Elasticsearch已經支持SQL查詢了(6.3版本以后),整理了下一些用法. 簡介 Elasticsearch SQL是一個X-Pack組件,它允許針對Elasticsearch實時執…

ESP32之避障

ESP32之避障 圖片 程序 int Led27;//定義LED 接口 int buttonpin4; //定義光遮斷傳感器接口 int val;//定義數字變量val void setup() { pinMode(Led,OUTPUT);//定義LED 為輸出接口 pinMode(buttonpin,INPUT);//定義避障傳感器為輸出接口 } void loop() {Serial.begin(9600);…

保姆級 Keras 實現 YOLO v3 一

保姆級 Keras 實現 YOLO v3 一 一. YOLO v3 總覽二. 特征提取網絡特征提取網絡代碼實現 三. 特征融合特征融合代碼實現 四. 網絡輸出模型輸出代碼實現 五. 網絡模型代碼實現六. 代碼下載 如果要給 YOLO 目標檢測算法一個評價的話, 就是快和準, 現在已經到了 v8, 但是我為什么還…

如何開啟MySQL的慢查詢日志

說明:如果需要查看某一條SQL查詢速度慢,并對慢的SQL進行優化,那么開啟MySQL慢查詢日志是一定要做的事情,本文介紹如何開啟MySQL的慢查詢日志; 查看MySQL慢查詢是否開啟 首先,輸入下面的命令,查…

為什么 x86 操作系統從 0x7c00 處開始

0x00:x86 架構 BIOS 引導加載程序中的"0x7C00"之謎 你知道 x86 操作系統中的"0x7C00"這個神奇數字嗎 ? "0x7C00" 是BIOS加載MBR(主引導記錄,磁盤中的第一個扇區)的內存地址。操作系統或引導加載…

2-Linux學習環境搭建

1 Linux學習環境搭建 1.1 虛擬化介紹 # win 機器----》裝一個虛擬化軟件----》虛擬化出linux操作系統# kvm vmware openstack docker k8s # kvm vmware 虛擬化軟件 -運行在linux上,做虛擬化的軟件 -vmware運行在win,linux,商業軟件…

AMEYA360:瑞薩面向高端工業傳感器系統推出高精度模擬前端的32位RX MCU

全球半導體解決方案供應商瑞薩電子(TSE:6723)宣布面向高端工業傳感器系統推出一款全新RX產品——RX23E-B,擴展32位微控制器(MCU)產品線。新產品作為廣受歡迎的RX產品家族的一員,具有高精度模擬前…

hadoop2.x linux集群部署

hadoop2.x 集群部署 下載hadoop需要提前準備好jdk1.8 和rsync 和ssl集群信息解壓安裝配置環境變量配置site配置文件(/hadoop/etc/hadoop目錄下)core-site.xmlhdfs-site.xmlyarn-site.xmlmapred-site.xmlhadoop-env.sh要追加java_home!配置節點slaves 配置免密ssh訪問沒有ssh-co…

【計算方法與科學建模】矩陣特征值與特征向量的計算(四):乘冪法及其python實現

文章目錄 一、Jacobi 旋轉法二、Jacobi 過關法三、Householder 方法四、乘冪法 矩陣的特征值(eigenvalue)和特征向量(eigenvector)在很多應用中都具有重要的數學和物理意義。 本文將詳細介紹乘冪法的基本原理和步驟,并…