最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL與Redis如何保證雙寫一致性詳解

 更新時間:2025年10月29日 11:29:21   作者:程序員小假  
雙寫一致性是指在系統(tǒng)中同時使用緩存(如Redis)和數(shù)據(jù)庫(如MySQL)時,如何確保兩者的數(shù)據(jù)保持一致,這篇文章主要介紹了MySQL與Redis如何保證雙寫一致性的相關(guān)資料,需要的朋友可以參考下

前言

首先,我們必須明確一個核心觀點:在分布式環(huán)境下,要實現(xiàn)強一致性(在任何時刻讀取的數(shù)據(jù)都是最新的)是極其困難且代價高昂的,通常會嚴(yán)重犧牲性能。因此,在實踐中,我們通常追求最終一致性,即允許在短暫的時間內(nèi)數(shù)據(jù)不一致,但通過一些手段保證數(shù)據(jù)最終會保持一致。

下面我將從基礎(chǔ)概念、各種策略、最佳實踐到最新方案,為你詳細(xì)講解。

一、基礎(chǔ)概念:為什么會有不一致?

在一個包含 MySQL(作為可靠數(shù)據(jù)源)和 Redis(作為緩存)的系統(tǒng)中,所有的寫操作(增、刪、改)都必須同時處理這兩個地方。

這個過程中,任何一步失敗或延遲都會導(dǎo)致不一致:

  1. 寫 MySQL 成功,寫 Redis 失敗:導(dǎo)致 Redis 中是舊數(shù)據(jù)。
  2. 寫 Redis 成功,寫 MySQL 失敗:導(dǎo)致 Redis 中是“臟數(shù)據(jù)”,數(shù)據(jù)庫中不存在。
  3. 并發(fā)讀寫:一個線程在更新數(shù)據(jù)庫,但還沒更新緩存時,另一個線程讀取了舊的緩存數(shù)據(jù)。

二、核心策略與模式

解決雙寫一致性有多種策略,我們需要根據(jù)業(yè)務(wù)場景(對一致性的要求、讀寫的比例等)進(jìn)行選擇。

策略一:Cache-Aside Pattern(旁路緩存模式)

這是最常用、最經(jīng)典的緩存模式。核心原則是:應(yīng)用程序直接與數(shù)據(jù)庫和緩存交互,緩存不作為寫入的必經(jīng)之路。

  • 讀流程
    1. 收到讀請求。
    2. 首先查詢 Redis,如果數(shù)據(jù)存在(緩存命中),直接返回。
    3. 如果 Redis 中沒有數(shù)據(jù)(緩存未命中),則從 MySQL 中查詢。
    4. 將從 MySQL 查詢到的數(shù)據(jù)寫入 Redis(以便后續(xù)讀?。缓蠓祷財?shù)據(jù)。
  • 寫流程
    1. 收到寫請求。
    2. 更新 MySQL 中的數(shù)據(jù)。
    3. 刪除 Redis 中對應(yīng)的緩存。

為什么是刪除(Invalidate)緩存,而不是更新緩存?
這是一個關(guān)鍵設(shè)計點!

  • 性能:如果更新緩存,每次數(shù)據(jù)庫寫操作都要伴隨一次緩存寫操作,如果該數(shù)據(jù)并不經(jīng)常被讀取,那么這次緩存寫入就是浪費資源的。
  • 并發(fā)安全:在并發(fā)寫場景下,更新緩存的順序可能與更新數(shù)據(jù)庫的順序不一致,導(dǎo)致緩存中是舊數(shù)據(jù)。而刪除操作是冪等的,更為安全。

Cache-Aside 如何保證一致性?
它通過“先更新數(shù)據(jù)庫,再刪除緩存”來盡力保證。但它依然存在不一致的窗口期:

  1. 線程 A 更新數(shù)據(jù)庫。
  2. 線程 B 讀取數(shù)據(jù),發(fā)現(xiàn)緩存不存在,從數(shù)據(jù)庫讀取舊數(shù)據(jù)(因為 A 還沒提交或剛提交)。
  3. 線程 B 將舊數(shù)據(jù)寫入緩存。
  4. 線程 A 刪除緩存。

這種情況發(fā)生的概率較低,因為通常數(shù)據(jù)庫寫操作(步驟1)會比讀操作(步驟2)耗時更長(因為涉及鎖、日志等),所以步驟2在步驟1之前完成的概率很小。但這是一種理論上的可能。

策略二:Write-Through / Read-Through Pattern(穿透讀寫模式)

在這種模式下,緩存層(或一個獨立的服務(wù))自己負(fù)責(zé)與數(shù)據(jù)庫交互。對應(yīng)用來說,它只與緩存交互。

  • 寫流程:應(yīng)用寫入緩存,緩存組件同步地寫入數(shù)據(jù)庫。只有兩個都成功后才會返回成功。
  • 讀流程:應(yīng)用讀取緩存,如果未命中,緩存組件自己從數(shù)據(jù)庫加載并填充緩存,然后返回。

優(yōu)點:邏輯對應(yīng)用透明,一致性比 Cache-Aside 更好。
缺點:性能較差,因為每次寫操作都必然涉及一次數(shù)據(jù)庫寫入。通常需要成熟的緩存中間件支持。

策略三:Write-Behind Pattern(異步寫回模式)

Write-Through 的異步版本。應(yīng)用寫入緩存后立即返回,緩存組件在之后某個時間點(例如攢夠一批數(shù)據(jù)或定時)批量異步地更新到數(shù)據(jù)庫。

優(yōu)點:寫性能極高。
缺點:有數(shù)據(jù)丟失風(fēng)險(緩存宕機),一致性最弱。適用于允許少量數(shù)據(jù)丟失的場景,如計數(shù)、點贊等。

三、保證最終一致性的進(jìn)階方案

為了彌補 Cache-Aside 模式中的缺陷,我們可以引入一些額外的機制。

方案一:延遲雙刪

針對 Cache-Aside 中提到的“先更新數(shù)據(jù)庫,再刪除緩存”可能帶來的并發(fā)問題,可以引入一個延遲刪除。

  1. 線程 A 更新數(shù)據(jù)庫。
  2. 線程 A 刪除緩存。
  3. 線程 A 休眠一個特定的時間(如 500ms - 1s)。
  4. 線程 A 再次刪除緩存。

第二次刪除是為了清理掉在第1次刪除后、其他線程可能寫入的舊數(shù)據(jù)。這個休眠時間需要根據(jù)業(yè)務(wù)讀寫耗時來估算。

優(yōu)點:簡單有效,能很大程度上解決并發(fā)讀寫導(dǎo)致的不一致。
缺點:降低了寫入吞吐量,休眠時間難以精確設(shè)定。

方案二:通過消息隊列異步刪除

為了解耦和重試,可以將刪除緩存的操作作為消息發(fā)送到消息隊列(如 RocketMQ, Kafka)。

  1. 更新數(shù)據(jù)庫。
  2. 向消息隊列發(fā)送一條刪除緩存的消息。
  3. 消費者消費該消息,執(zhí)行刪除 Redis 的操作。如果刪除失敗,消息會重試。

這保證了刪除緩存的操作至少會被執(zhí)行一次,大大提高了可靠性。

方案三:通過數(shù)據(jù)庫 Binlog 同步(最優(yōu)解)

這是目前最成熟、對業(yè)務(wù)侵入性最小、一致性最好的方案。其核心是利用 MySQL 的二進(jìn)制日志(Binlog)進(jìn)行增量數(shù)據(jù)同步。

工作原理

  1. 業(yè)務(wù)系統(tǒng)正常寫入 MySQL。
  2. 由一個中間件(如 Canal, Debezium)偽裝成 MySQL 的從庫,訂閱 Binlog。
  3. 中間件解析 Binlog,獲取數(shù)據(jù)的變更詳情(增、刪、改)。
  4. 中間件根據(jù)變更,調(diào)用 Redis 的 API 來更新或刪除對應(yīng)的緩存。

優(yōu)點

  • 業(yè)務(wù)無侵入:業(yè)務(wù)代碼只關(guān)心寫數(shù)據(jù)庫,完全不知道緩存的存在。
  • 高性能:數(shù)據(jù)庫和緩存的同步是異步的,不影響主業(yè)務(wù)鏈路的性能。
  • 強保證:由于基于 Binlog,它能保證只要數(shù)據(jù)庫變了,緩存最終一定會被同步。順序也與數(shù)據(jù)庫一致。

缺點

  • 架構(gòu)復(fù)雜,需要維護(hù)額外的同步組件。
  • 同步有毫秒級到秒級的延遲。

四、總結(jié)與最佳實踐選擇

策略

一致性保證

性能

復(fù)雜度

適用場景

Cache-Aside + 刪除

最終一致性(有微弱不一致風(fēng)險)

絕大多數(shù)場景的首選,讀多寫少

Cache-Aside + 延遲雙刪

更好的最終一致性

對一致性要求稍高,且能接受一定延遲的寫操作

Write-Through

強一致性

寫多讀少,且對一致性要求非常高的場景

Binlog 同步

最終一致性(推薦)

大型、高要求項目的最佳實踐,對業(yè)務(wù)無侵入

通用建議

  1. 首選方案:對于大多數(shù)應(yīng)用,從 Cache-Aside(先更新數(shù)據(jù)庫,再刪除緩存) 開始。它簡單、有效,在大多數(shù)情況下已經(jīng)足夠。
  2. 進(jìn)階保障:如果 Cache-Aside 的不一致窗口無法接受,可以引入延遲雙刪消息隊列異步刪除來增強。
  3. 終極方案:當(dāng)業(yè)務(wù)發(fā)展到一定規(guī)模,對一致性和系統(tǒng)解耦有更高要求時,投入資源搭建基于 Binlog 的異步同步方案。這是業(yè)界證明最可靠的方案。
  4. 設(shè)置合理的過期時間:無論如何,都給 Redis 中的緩存設(shè)置一個過期時間(TTL)。這是一個安全網(wǎng),即使同步邏輯出現(xiàn)問題,舊數(shù)據(jù)也會自動失效,最終從數(shù)據(jù)庫加載新數(shù)據(jù),保證最終一致性。
  5. 業(yè)務(wù)容忍度:最重要的是,與產(chǎn)品經(jīng)理確認(rèn)業(yè)務(wù)對一致性的容忍度。很多時候,1-2秒內(nèi)的數(shù)據(jù)不一致用戶是感知不到的,不需要為此付出巨大的架構(gòu)和性能代價。

總結(jié)

到此這篇關(guān)于MySQL與Redis如何保證雙寫一致性的文章就介紹到這了,更多相關(guān)MySQL與Redis保證雙寫一致性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 簡單了解操作mysql數(shù)據(jù)庫的命令行神器mycli

    簡單了解操作mysql數(shù)據(jù)庫的命令行神器mycli

    這篇文章主要介紹了簡單了解操作mysql數(shù)據(jù)庫的命令行神器mycli,今天發(fā)現(xiàn)一個操作數(shù)據(jù)庫的命令行工具,可以自動補全和語法高亮,,需要的朋友可以參考下
    2019-06-06
  • MySQL二進(jìn)制日志(bin_log)的作用與使用方法

    MySQL二進(jìn)制日志(bin_log)的作用與使用方法

    BinLog又稱為二進(jìn)制日志,是MySQL服務(wù)層的數(shù)據(jù)日志,MySQL所有的存儲引擎都支持BinLog,這篇文章主要給大家介紹了關(guān)于MySQL二進(jìn)制日志(bin_log)的作用與使用方法的相關(guān)資料,需要的朋友可以參考下
    2024-06-06
  • MySQL查看和修改時區(qū)的方法

    MySQL查看和修改時區(qū)的方法

    這篇文章主要給大家介紹了關(guān)于MySQL查看和修改時區(qū)的方法,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用MySQL具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • 修改Mysql索引長度限制解決767?byte限制問題

    修改Mysql索引長度限制解決767?byte限制問題

    這篇文章主要介紹了修改Mysql索引長度限制解決767?byte限制問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • 解讀sql中timestamp和datetime之間的轉(zhuǎn)換

    解讀sql中timestamp和datetime之間的轉(zhuǎn)換

    這篇文章主要介紹了解讀sql中timestamp和datetime之間的轉(zhuǎn)換方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • MySQL從庫維護(hù)經(jīng)驗分享

    MySQL從庫維護(hù)經(jīng)驗分享

    這篇文章主要介紹了MySQL從庫維護(hù)經(jīng)驗分享,幫助大家更好的理解和使用MySQL數(shù)據(jù)庫,感興趣的朋友可以了解下
    2020-11-11
  • MySQL GTID全面總結(jié)

    MySQL GTID全面總結(jié)

    這篇文章主要介紹了MySQL GTID的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用MySQL數(shù)據(jù)庫,感興趣的朋友可以了解下
    2021-03-03
  • MySQL CHECK約束(5.7和8.0)的使用

    MySQL CHECK約束(5.7和8.0)的使用

    CHECK約束用于確保數(shù)據(jù)表中的某列或多列的數(shù)據(jù)符合特定的條件,本文主要介紹了MySQL CHECK約束(5.7和8.0)的使用,具有一定的參考價值,感興趣的可以了解一下
    2024-08-08
  • MySQL數(shù)據(jù)庫查詢排序方式

    MySQL數(shù)據(jù)庫查詢排序方式

    這篇文章主要介紹了MySQL數(shù)據(jù)庫查詢排序方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 關(guān)于MySQL的存儲函數(shù)(自定義函數(shù))的定義和使用方法詳解

    關(guān)于MySQL的存儲函數(shù)(自定義函數(shù))的定義和使用方法詳解

    本文主要講解了關(guān)于MySQL的存儲函數(shù)(自定義函數(shù))的定義和使用方法詳解與存儲函數(shù)與存儲過程的區(qū)別
    2018-03-03

最新評論

秦安县| 金坛市| 建水县| 临夏县| 通城县| 孟村| 嘉荫县| 二连浩特市| 大余县| 张家港市| 房山区| 义马市| 萨嘎县| 合山市| 长兴县| 九龙县| 兰西县| 巴林右旗| 共和县| 仪陇县| 卢湾区| 沈丘县| 隆回县| 高雄市| 嘉荫县| 图们市| 开平市| 汉中市| 玉田县| 精河县| 白银市| 三都| 三河市| 屏边| 永清县| 龙口市| 会同县| 来凤县| 舟山市| 桦川县| 察雅县|