快取與資料庫的一致性

2021-09-16 13:58:02 字數 1276 閱讀 5762

快取就是資料交換的緩衝區,針對服務物件的不同(本質就是不同的硬體)都可以構建快取。

目的是,把讀寫速度慢的介質的資料儲存在讀寫速度快的介質中,從而提高讀寫速度,減少時間消耗。例如:

磁碟快取:磁碟快取其實就把常用的磁碟資料儲存在記憶體中,記憶體讀寫速度也是遠高於磁碟的。

讀資料時,從記憶體讀取。

寫資料時,可先寫到記憶體,定時或定量回寫到磁碟,或者是同步回寫。

使用快取的目的,就是提公升讀寫效能。而實際業務場景下,更多的是為了提公升讀效能,帶來更好的效能,更高的併發量。

日常業務中,我們使用比較多的資料庫是 mysql,快取是 redis 。redis 比 mysql 的讀寫效能好很多。那麼,我們將 mysql 的熱點資料,快取到 redis 中,提公升讀取效能,也減小 mysql 的讀取壓力。例如說:

一致性問題是分布式常見的問題,分為最終一致性和強一致性。如果對資料有強一致性要求,不能放快取,我們只能保證最終一致性。

問題的產生

併發場景下,讀取舊的 db 資料並更新到快取中。

快取和 db 的操作不在乙個事務中,可能只有乙個操作成功,另乙個操作失敗,導致不一致。

解決方案

1.先淘汰快取,再更新資料庫

先淘汰快取,即使寫資料庫發生異常,也就是下次快取讀取時,多讀取一次資料庫,這樣理論上來說保證了資料的

一致性。但是實際在併發環境下仍然會出現資料不一致的情況。

首先來說寫流程:先淘汰快取,再寫 db;

然後是讀流程:先讀快取,如果未命中再讀 db,然後將 db 中讀出來的資料更新到快取中。併發環境下,在資料庫層面併發的讀寫並不能保證完全順序,也就是說後發出的讀請求可能先完成。舉例來說

這種情況下,可以引入分布式鎖實現「序列化」來解決。

2.先寫資料庫,再更新快取

由於操作快取和運算元據庫不是原子的,則第一步寫資料庫操作成功,第二步淘汰快取失敗,就會出現 db 中是新資料,快取中是舊資料,資料不一致的情況。在這種邏輯下,只***寫資料庫和更新快取在同乙個事務中,才能保證最終一致性。

a.基於定時任務來實現

b.基於訊息佇列實現

基於資料庫的 binlog 日誌

可以看到這種方案對研發人員來說比較輕量,不用關心快取層面,而且這個方案雖然比較重,但是卻容易形成統一的解決方案。

備註說明: 上述的訂閱 binlog 程式在 mysql 中有現成的中介軟體叫 canal,可以完成訂閱 binlog 日誌的功能。

快取與資料庫一致性

此時系統的讀寫流量很小,這個時候所有的讀寫操作都在主庫 此時,從庫的角色只是作為災備。風險分析 從資料一致性的角度來看沒有任何問題,所有讀寫操作都在主庫 隨著業務的前進和流量的激增,會出現大表和資料庫寫入效能下降的問題。我們可以通過分庫的方式,提公升資料庫單機的qps壓下來 通過分表的方式,降低單錶...

快取與資料庫的一致性

參考文章 快取適用於讀多寫少的場景,並且能極大地提公升效能和效率 但是讓快取的資料與資料庫保持一致是乙個難題 當資料更新時,先更新快取,如果快取更新成功,再更新資料庫 當資料更新時,先刪除快取,如果快取刪除成功,再更新資料庫 不考慮策略1,以下將深入 策略2 在高併發的情況下,假設請求1 更新操作 ...

快取與資料庫一致性保證

本文主要討論這麼幾個問題 1 啥時候資料庫和快取中的資料會不一致 2 不一致優化思路 3 如何保證資料庫與快取的一致性 當資料發生變化時,先淘汰快取,再修改資料庫 這個點是大家討論的最多的。上篇文章得出這個結論的依據是,由於操作快取與運算元據庫不是原子的,非常有可能出現執行失敗。假設先寫資料庫,再淘...