Redis跟MySQL的雙寫問題怎麼解決
寫在前面
嚴格意義上任何非原子操作都不可能保證一致性,除非用阻塞讀寫實現強一致性,所以快取架構我們追求的目標是最終一致性。
快取就是透過犧牲強一致性來提高效能的。
這是由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中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

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

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

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

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

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

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

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

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

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