目錄
寫在前面
三種讀寫快取策略
Cache-Aside Pattern(旁路快取模式)
Read-Through/Write-Through(讀寫穿透)
Write Behind Pattern(非同步快取寫入)
旁路快取模式解析
Cache Aside Pattern 的一些問題
Cache Aside Pattern 的缺陷
首頁 資料庫 mysql教程 Redis跟MySQL的雙寫問題怎麼解決

Redis跟MySQL的雙寫問題怎麼解決

May 27, 2023 pm 12:53 PM
mysql redis

寫在前面

嚴格意義上任何非原子操作都不可能保證一致性,除非用阻塞讀寫實現強一致性,所以快取架構我們追求的目標是最終一致性。
快取就是透過犧牲強一致性來提高效能的。

這是由CAP理論決定的。快取系統適用的場景就是非強一致性的場景,它屬於CAP中的AP。

以下3 種快取讀寫策略各有優劣,不存在最佳。

三種讀寫快取策略

Cache-Aside Pattern(旁路快取模式)

Cache-Aside Pattern,即旁路快取模式,它的提議是為了盡可能解決快取與資料庫的資料不一致問題。

讀取 :從快取讀取數據,讀到直接返回。如果讀取不到的話,從資料庫加載,寫入快取後,再回傳回應。
:更新的時候,先更新資料庫,然後再刪除快取

Read-Through/Write-Through(讀寫穿透)

Read/Write Through Pattern 中服務端把cache 視為主要資料存儲,從中讀取資料並將資料寫入其中。 Cache服務的職責是讀取和寫入DB數據,從而減輕應用程式的負擔。

因為我們常用的分散式快取 Redis 並沒有提供 cache 將資料寫入DB的功能,所以使用並不多。

寫入:先查 cache,cache 中不存在,直接更新 DB。 cache 中存在,則先更新 cache,然後 cache 服務會自行更新 DB(同步更新 cache和DB)。

讀取:從 cache 讀取數據,讀取到就直接回傳 。讀取不到的話,先從 DB 加載,寫入到 cache 後回傳回應。

Write Behind Pattern(非同步快取寫入)

Write Behind Pattern 和 Read/Write Through Pattern 很相似,兩者都是由 cache 服務來負責 cache 和 DB 的讀寫。

但是,兩個又有很大的不同:Read/Write Through 是同步更新cache 和DB,而Write Behind Caching 則是只更新緩存,不直接更新DB,而是改為異步批量的方式來更新DB。

很明顯,這種方式對資料一致性帶來了更大的挑戰,例如cache資料可能還沒非同步更新DB的話,cache服務可能就掛掉了,反而會帶來更大的災難。

這種策略在我們平時開發過程中也非常非常少見,但是不代表它的應用場景少,例如訊息佇列中訊息的非同步寫入磁碟、MySQL 的InnoDB Buffer Pool 機制都用到了這種策略。

Write Behind Pattern 下 DB 的寫入效能非常高,非常適合一些資料經常變化又對資料一致性要求沒那麼高的場景,例如瀏覽量、按讚量。

旁路快取模式解析

Cache Aside Pattern 的一些問題

旁路快取模式是我們平常使用最多的。以下根據上面介紹的旁路快取模式,我們可以有以下幾個問題。

為什麼寫入作業是刪除緩存,而不是更新快取

#:執行緒A先發起一個寫入操作,第一步先更新資料庫.線程B再發起一個寫入操作,第二步更新了資料庫,由於網路等原因,線程B先更新了緩存,線程A更新快取。

這時候,快取保存的是A的資料(老數據),資料庫保存的是B的資料(新資料),資料不一致了,髒資料出現囉。如果是刪除快取取代更新快取則不會出現這個髒資料問題。

實際上要寫操作的時候更新快取也是可以的,不過我們需要加一個鎖/分散式鎖來保證更新cache的時候不存在執行緒安全性問題。

在寫資料的過程中,為什麼要先更新DB在刪除快取

#:比如說請求1 是寫入操作,要是先刪除快取A,請求2是讀取操作,先讀快取A,發現快取被刪除了(被請求1刪除了),然後去讀資料庫,但是此時請求1還沒來得及把資料及時更新,那麼請求2讀的就是舊數據,請求2還會把讀到的舊數據放到快取中,造成了數據的不一致。

其實要先刪緩存,再更新資料庫也是可以,如採用延時雙刪策略
休眠1秒,再次淘汰緩存這麼做,可以將1秒內所造成的快取髒數據,再次刪除。不一定是1秒,看你業務決定的,不過不推薦這種做法,因為在這1秒內可能發生因素很多,它的不確定性太大。

在寫資料的過程中,先更新DB,後刪除cache就沒問題了麼?

答案: 理論上還是可能會出現資料不一致性的問題,不過機率非常小。

假設這會有兩個請求,一個請求A做查詢操作,一個請求B做更新操作,那麼會有下列情形產生

(1)快取剛好失效
(2)請求A查詢資料庫,得一個舊值
(3)請求B將新值寫入資料庫
(4)請求B刪除快取
(5)請求A將查到的舊值寫入快取ok,如果發生上述情況,確實是會發生髒資料。

然而,發生這種情況的機率並不高

發生上述情況有一個先天性條件,就是步驟(3)的寫入資料庫操作比步驟( 2)的讀取資料庫操作耗時更短,才有可能使得步驟(4)先於步驟(5)。

可是,仔細想想,資料庫的讀取操作的速度遠快於寫操作的(不然做讀寫分離幹嘛,做讀寫分離的意義就是因為讀操作比較快,耗資源少) ,因此步驟(3)耗時比步驟(2)更短,此情況很難出現。

還有其他造成不一致的原因麼?

答案: 如果刪除快取過程中失敗了就會造成不一致問題

如何解決?
使用Canal去訂閱資料庫的binlog,取得需要操作的資料。另起一個程序,獲得這個訂閱程序傳來的信息,進行刪除快取操作。

Cache Aside Pattern 的缺陷

缺陷1:第一次請求資料一定不在cache 的問題

解決方法:可以提前將熱點資料放入cache 中。

缺陷2:寫入操作比較頻繁的話導致cache中的資料會被頻繁被刪除,這樣會影響快取命中率 。

資料庫與快取資料強一致場景 :更新DB的時候同樣更新cache,不過我們需要加一個鎖定/分散式鎖定來保證更新cache的時候不存在執行緒安全性問題。可以短暫地允許資料庫和快取資料不一致的場景 :更新DB的時候同樣更新cache,但是給快取加一個比較短的過期時間,這樣的話就可以保證即使資料不一致的話影響也比較小。

以上是Redis跟MySQL的雙寫問題怎麼解決的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1657
14
CakePHP 教程
1415
52
Laravel 教程
1309
25
PHP教程
1257
29
C# 教程
1231
24
MySQL和PhpMyAdmin:核心功能和功能 MySQL和PhpMyAdmin:核心功能和功能 Apr 22, 2025 am 12:12 AM

MySQL和phpMyAdmin是強大的數據庫管理工具。 1)MySQL用於創建數據庫和表、執行DML和SQL查詢。 2)phpMyAdmin提供直觀界面進行數據庫管理、表結構管理、數據操作和用戶權限管理。

如何利用Redis緩存方案高效實現產品排行榜列表的需求? 如何利用Redis緩存方案高效實現產品排行榜列表的需求? Apr 19, 2025 pm 11:36 PM

Redis緩存方案如何實現產品排行榜列表的需求?在開發過程中,我們常常需要處理排行榜的需求,例如展示一個�...

REDIS的角色:探索數據存儲和管理功能 REDIS的角色:探索數據存儲和管理功能 Apr 22, 2025 am 12:10 AM

Redis在數據存儲和管理中扮演著關鍵角色,通過其多種數據結構和持久化機製成為現代應用的核心。 1)Redis支持字符串、列表、集合、有序集合和哈希表等數據結構,適用於緩存和復雜業務邏輯。 2)通過RDB和AOF兩種持久化方式,Redis確保數據的可靠存儲和快速恢復。

Spring Boot中OAuth2Authorization對象Redis緩存失敗怎麼辦? Spring Boot中OAuth2Authorization對象Redis緩存失敗怎麼辦? Apr 19, 2025 pm 08:03 PM

SpringBoot中使用Redis緩存OAuth2Authorization對像在SpringBoot應用中,使用SpringSecurityOAuth2AuthorizationServer...

在MySQL中解釋外鍵的目的。 在MySQL中解釋外鍵的目的。 Apr 25, 2025 am 12:17 AM

在MySQL中,外鍵的作用是建立表與表之間的關係,確保數據的一致性和完整性。外鍵通過引用完整性檢查和級聯操作維護數據的有效性,使用時需注意性能優化和避免常見錯誤。

如何安全地將包含函數和正則表達式的JavaScript對象存儲到數據庫並恢復? 如何安全地將包含函數和正則表達式的JavaScript對象存儲到數據庫並恢復? Apr 19, 2025 pm 11:09 PM

安全地處理JSON中的函數和正則表達式在前端開發中,經常需要將JavaScript...

在多節點環境下,如何確保Spring Boot的@Scheduled定時任務只在一個節點上執行? 在多節點環境下,如何確保Spring Boot的@Scheduled定時任務只在一個節點上執行? Apr 19, 2025 pm 10:57 PM

SpringBoot定時任務在多節點環境下的優化方案在開發Spring...

比較和對比Mysql和Mariadb。 比較和對比Mysql和Mariadb。 Apr 26, 2025 am 12:08 AM

MySQL和MariaDB的主要區別在於性能、功能和許可證:1.MySQL由Oracle開發,MariaDB是其分支。 2.MariaDB在高負載環境中性能可能更好。 3.MariaDB提供了更多的存儲引擎和功能。 4.MySQL採用雙重許可證,MariaDB完全開源。選擇時應考慮現有基礎設施、性能需求、功能需求和許可證成本。

See all articles