MySQL和Redis的數據一致性問題與業界常見解法

一、為什么會出現數據不一致?

根本原因在于:這是一個涉及兩個獨立存儲系統的數據更新操作,它無法被包裝成一個原子操作(分布式事務)。更新數據庫和更新緩存是兩個獨立的步驟,無論在代碼中如何排列這兩個步驟,都可能因為并發、失敗重試等原因導致不一致。

主要的不一致場景可以歸結為以下兩類順序問題:

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

    • 成功更新 DB -> 刪除 Cache -> 數據一致(下次讀取會回種緩存)。
    • 失敗
      • 更新 DB 成功,刪除 Cache 失敗:數據庫是新數據,緩存是舊數據,發生不一致。
      • 并發讀寫:在更新 DB 后、刪除 Cache 前,另一個線程來讀取,發現緩存是舊的并加載,隨后 Cache 被刪除,但里面已經是臟數據了。
  2. 先刪除緩存,再更新數據庫

    • 成功刪除 Cache -> 更新 DB -> 數據一致。
    • 失敗
      • 刪除 Cache 成功,更新 DB 失敗:緩存是空的,數據庫是舊數據,數據一致(但緩存miss,會從DB讀舊數據回種,仍是舊數據)。
      • 并發讀寫(更嚴重)
        1. 線程A 刪除緩存
        2. 線程B 發現緩存不存在,從數據庫讀取舊數據
        3. 線程B 將舊數據回種到緩存
        4. 線程A 更新數據庫為新數據
        • 結果:數據庫是新數據,緩存是舊數據,發生不一致。

二、常見的解決方案與策略

沒有一種完美的銀彈方案,需要根據業務場景(對一致性的要求、讀寫比例、性能要求等)進行權衡和選擇。

1. Cache-Aside (旁路緩存) + 延遲雙刪

這是最常用的模式,其讀/寫邏輯如下:

  • 讀流程

    1. 從 Redis 讀取數據。
    2. 如果命中,直接返回。
    3. 如果未命中,從 MySQL 讀取數據。
    4. 將 MySQL 的數據寫入 Redis(回種緩存),然后返回。
  • 寫流程(關鍵)

    1. 更新 MySQL 中的數據。
    2. 刪除 Redis 中的對應緩存。
    3. (延遲雙刪的關鍵步驟) 等待一小段時間(如幾百毫秒),再次刪除 Redis 緩存。

為什么需要“延遲雙刪”?
它旨在解決上述“先更新數據庫,再刪除緩存”模式下的并發問題。第二次刪除是為了清除在“更新DB”和“第一次刪除Cache”這個時間間隙內,可能被其他讀請求回種的舊數據。

優點

  • 實現相對簡單,適用性廣。
  • 延遲雙刪能解決大部分并發導致的不一致。

缺點

  • 等待時間(延遲)需要估算,不好設置。
  • 第二次刪除可能仍會失敗(需要重試機制)。
  • 在延遲期間,可能仍有短暫的不一致。

改進:為第二次刪除增加重試機制。可以將失敗的刪除操作寫入一個消息隊列,由專門的服務消費重試,確保最終一定刪除成功。

2. Write-Through (穿透寫) / Write-Behind

這類方案通常需要依賴一個獨立的服務或中間件來統一管理緩存和數據庫的寫入。

  • Write-Through

    • 應用層只寫入緩存(由一個中間件來管理)。
    • 中間件同步地寫入緩存和數據庫。
    • 保證了強一致性,但性能很差,因為每次寫操作都要等待兩個存儲系統都完成。
  • Write-Behind (也叫Write-Back)

    • 應用層只寫入緩存(由一個中間件來管理)。
    • 中間件先寫緩存,然后異步地批量更新到數據庫。
    • 性能極高,但存在數據丟失風險(如果緩存宕機,未持久化的數據會丟失)。一致性最弱。

優點

  • Write-Through 強一致。
  • Write-Behind 性能極高。

缺點

  • 架構復雜,需要引入和維護額外的中間件。
  • Write-Through 性能低。
  • Write-Behind 有丟失數據風險。
3. 基于 MySQL Binlog 的最終一致性方案(推薦)

這是目前最流行、最可靠的大型項目方案。其核心是利用 MySQL 的二進制日志(Binlog)進行增量數據同步。

工作原理

  1. 業務代碼正常更新 MySQL。
  2. 一個數據同步服務(如 Canal, Maxwell, Debezium)偽裝成 MySQL 的從庫,訂閱并解析 Binlog。
  3. 同步服務獲取到數據的變更事件(增、刪、改)后,發送到一個消息隊列(如 Kafka/RocketMQ)。
  4. 一個緩存更新服務消費 MQ 中的消息,然后刪除 Redis 中對應的緩存。

優點

  • 徹底解耦:業務代碼只關心數據庫,完全不知道緩存的存在。代碼簡潔。
  • 高可靠性:Binlog 是 MySQL 自帶的高可靠機制,保證了數據變更不會丟失。
  • 最終一致性:通過 MQ 的異步消費,保證了數據最終會一致,延遲低。
  • 通用性:一套系統可以為多種業務服務。

缺點

  • 架構最復雜,技術門檻高,需要維護多個組件(同步服務、MQ、消費服務)。

三、方案選擇與最佳實踐總結

策略一致性強度復雜度性能適用場景
Cache-Aside + 延遲雙刪最終一致(可能有短暫不一致)中等通用方案,適合大多數中小型項目
Write-Through強一致對一致性要求極高,可接受寫性能差的場景
Write-Behind弱一致(可能丟失數據)極高寫入巨大,對性能要求極高,能容忍數據丟失的場景(如計數、日志)
Binlog 同步最終一致(可靠性高)非常高大型互聯網項目,架構完善,需要高可靠性和解耦

通用最佳實踐建議

  1. 優先選擇刪除緩存,而不是更新緩存

    • 更新緩存可能帶來并發問題、浪費資源(多次更新可能只有最后一次被讀到)。直接刪除讓下一次讀請求來回種緩存,是更 lazy 和高效的做法。
  2. Key 的過期時間

    • 即使一切正常,也一定要給 Redis 的 Key 設置一個過期時間。這是最后一道防線,即使同步失敗,舊緩存也會自動失效,最終達到一致。
  3. 保證刪除操作的重試

    • 無論是哪種方案,刪除緩存都可能失敗。必須要有重試機制(如通過消息隊列),確保刪除最終成功。
  4. 讀操作是否回種緩存?

    • 在高并發場景下,如果緩存缺失(Cache Miss),可能會導致大量請求穿透到數據庫(緩存擊穿)。可以考慮使用互斥鎖(Mutex Lock),只讓一個請求去數據庫回種緩存,其他請求等待。
  5. 根據業務容忍度選擇策略

    • 對于用戶信息、商品價格等對一致性要求較高的數據,推薦使用 Binlog 同步方案延遲雙刪
    • 對于點贊數、瀏覽量等對一致性要求不高的數據,甚至可以設置短一點的過期時間,容忍短暫不一致。

結論:

對于追求穩定和可靠性的大型項目基于 Binlog 的異步同步方案是最佳選擇。對于中小型項目,從簡單有效出發,Cache-Aside + 延遲雙刪 + 失敗重試機制 是一個不錯的起點,同時務必為緩存設置過期時間

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

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

相關文章

coolshell文章閱讀摘抄

coolshell文章閱讀摘抄打好基礎學好英語限制你的不是其它人,也不是環境,而是自己Java打好基礎 程序語言:語言的原理,類庫的實現,編程技術(并發、異步等),編程范式,設計模…

數據庫造神計劃第六天---增刪改查(CRUD)(2)

🔥個人主頁:尋星探路 🎬作者簡介:Java研發方向學習者 📖個人專欄:《從青銅到王者,就差這講數據結構!!!》、 《JAVA(SE)----如此簡單&a…

使用Rust實現服務配置/注冊中心

Conreg 使用 Rust 實現的配置與注冊中心,參考了 Nacos 的設計,簡單易用,使用 Raft 保證集群節點數據一致性。 支持的平臺: UbuntuCentOS其他常見的 Linux 發行版(我們使用 musl 編譯,理論上支持所有主流…

三色標記算法

在 JVM 并發垃圾收集(GC)中,三色標記算法是實現 “GC 線程與用戶線程并行執行” 的關鍵技術,它解決了并發場景下 “如何準確標記存活對象” 的核心問題,是 CMS、G1 等現代收集器的底層基礎。一、三色標記的核心&#x…

OpenStack 管理與基礎操作學習筆記(一):角色、用戶及項目管理實踐

OpenStack實驗 OpenStack命令 admin-openrc.sh 進入管理員視圖查看當前 OpenStack 中的項目列表,驗證是否已經登錄成功切換用戶 修改文件切換用戶上傳文件切換用戶OpenStack 認證管理 實驗介紹 通過 OpenStack Dashboard 和 OpenStack CLI 兩種方式創建角色、用戶、…

直接查找試卷且可以免費下載

有什么網站可以直接查找試卷且可以免費下載? SearXNG開源元搜索引擎 This website shows the SearXNG public instances searx一個可定制的搜索引擎 分享一個基于Blockstack的DApp-searx,一個可定制的搜索引擎。 1- 鏈接 官網地址:https://searx.worl…

【獨立版】智創云享知識付費小程序 v5.0.23+小程序 搭建教程

介紹智創云享知識付費小程序v5.0.23 含PC、小程序、H5 、前端,系統獨立版已修復已知bug問題。框架是一款基于ThinkPHP框架開發的虛擬資源知識付費小程序,為廣大創業者、自媒體及培訓機構提供知識付費、內容付費、資源變現等領域的行業解決方案&#xff1…

布爾運算-區間dp

面試題 08.14. 布爾運算 - 力扣(LeetCode) Solution 這題的思路比較直接,就是枚舉最后一個進行計算的運算符,但是在實現過程中需要注意,定義范式f(l,r)表示l到r范圍,l和r必須為數字,l1,r-1為運…

MyBatis-Plus 擴展全局方法

1.文件內容package com.ruoyi.business.mybatisplus.base;import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.extension.service.IService;import java.util.List;/*** 擴展的 Service 接口* 所有自定義 Service 接口都需要繼承此接口…

13.Linux OpenSSH 服務管理

文章目錄Linux OpenSSH 服務管理環境準備OpenSSH 服務介紹SSH 介紹SSH 建立連接的過程加密類型雙向加密過程使用 ssh 訪問遠端CLIssh 工具演示ssh工具配置文件配置 ssh 密鑰認證ssh 故障模擬故障模擬排故故障自定義 SSH 服務配置文件禁止 root 登錄禁止密碼登錄只允許特定用戶登…

速通ACM省銅第五天 賦源碼(MEX Count)

目錄 引言: MEX Count 題意分析 邏輯梳理 代碼實現 結語: 引言: 本來,今天我是想著出倆題或三題題解的,但是在打第一題的時候就天塌了,導致今天就只搓了一道題,這題的難度在CF中為1300的水準&…

【數據結構與算法-Day 27】堆的應用:從堆排序到 Top K 問題,一文徹底搞定!

Langchain系列文章目錄 01-玩轉LangChain:從模型調用到Prompt模板與輸出解析的完整指南 02-玩轉 LangChain Memory 模塊:四種記憶類型詳解及應用場景全覆蓋 03-全面掌握 LangChain:從核心鏈條構建到動態任務分配的實戰指南 04-玩轉 LangChai…

企業即時通訊保障企業通訊安全,提升企業部門協作效率

在當今數字化轉型的大潮中,企業即時通訊軟件已從單純的溝通工具,逐步演變為保障企業數據安全的核心基礎設施。吱吱企業即時通訊軟件通過“私有化部署全流程加密”的雙重機制,為企業構建了一套集“通訊安全”與“部門協作”于一體的數字化解決…

《華為變革法:打造可持續進步的組織》讀書筆記

推薦序一:變革是企業活下去的基礎(胡彥平)華為前常務副總裁、變革指導委員會成員胡彥平在序言中強調,企業存續的核心命題是應對不確定性,而變革能力是破解這一命題的唯一答案。他以華為 30 余年的發展歷程為例&#xf…

第二篇:排序算法的簡單認識【數據結構入門】

排序算法的分類標準 時間復雜度分類 a. 簡單排序算法:時間復雜度O(n),冒泡排序、選擇排序、插入排序; b. 高級排序算法:時間復雜度O(n logn),快速排序、歸并排序、堆排序; c. 線性排序算法:時間…

快速掌握Dify+Chrome MCP:打造網頁操控AI助手

你是否曾經希望那些強大的開源大模型能更貼合你的專業領域,或者學會模仿你的行文風格?其實,實現這個目標的關鍵就在于“微調”。曾幾何時,微調模型是大公司的專屬游戲——動不動就需要幾十張GPU和復雜的分布式訓練技術。 而現在&…

單詞記憶-輕松記憶10個實用英語單詞(15)

1. repaint含義:重新油漆 讀音標注:/?ri??pe?nt/ 例句:We need to repaint the walls after the repairs. 譯文:修理完成后需要重新粉刷墻壁。 衍生含義:重新繪制(圖像場景);翻新…

visual studio快捷鍵

1.visual studio代碼格式化快捷鍵 1.CtrlA(全選) 2.CtrlK 3.CtrlF2.多行注釋 1.Ctrlk 2.Ctrlc2.多行取消注釋 1.Ctrlk 2.Ctrlu

Django全棧班v1.04 Python基礎語法 20250913 下午

練習:個人信息收集器 任務:創建一個個人信息收集和展示程序 要求: 收集用戶的姓名,年齡,城市,愛好驗證年齡輸入,必須是正數格式化輸出用戶信息計算用戶出生年份 name input("請輸入姓名&a…

學習海康VisionMaster之字符缺陷檢測

前言:差不多三個月沒更新了,天天碼代碼,實在是太忙了,有時候也在想這么忙到底是不是工作方法的問題,怎么樣才能變成大師呢! 一:進一步學習 今天學習下VisionMaster中的字符缺陷檢測&#xff1…