58沈劍架構系列 主從DB與cache一致性

2022-01-18 01:50:22 字數 2562 閱讀 7085

(1)資料庫主從延時為何會導致快取資料不一致

(2)優化思路與方案

為什麼會讀到髒資料,有這麼幾種情況:

(1)單庫情況下,服務層的併發讀寫,快取與資料庫的操作交叉進行

雖然只有乙個db,在上述詭異異常時序下,也可能髒資料入快取:

1)請求a發起乙個寫操作,第一步淘汰了cache,然後這個請求因為各種原因在服務層卡住了(進行大量的業務邏輯計算,例如計算了1秒鐘),如上圖步驟1

2)請求b發起乙個讀操作,讀cache,cache miss,如上圖步驟2

3)請求b繼續讀db,讀出來乙個髒資料,然後髒資料入cache,如上圖步驟3

4)請求a卡了很久後終於寫資料庫了,寫入了最新的資料,如上圖步驟4

這種情況雖然少見,但理論上是存在的, 後發起的請求b在先發起的請求a中間完成了。

(2)主從同步,讀寫分離的情況下,讀從庫讀到舊資料

1)請求a發起乙個寫操作,第一步淘汰了cache,如上圖步驟1

2)請求a寫資料庫了,寫入了最新的資料,如上圖步驟2

3)請求b發起乙個讀操作,讀cache,cache miss,如上圖步驟3

4)請求b繼續讀db,讀的是從庫,此時主從同步還沒有完成,讀出來乙個髒資料,然後髒資料入cache,如上圖步4

5)最後資料庫的主從同步完成了,如上圖步驟5

這種情況請求a和請求b的時序是完全沒有問題的,是主動同步的時延(假設延時1秒鐘)中間有讀請求讀從庫讀到髒資料導致的不一致。

那怎麼來進行優化呢?

有同學說「那能不能先運算元據庫,再淘汰快取」,這個是不行的,在《快取和資料庫先操作誰》的文章中介紹過。

出現不一致的根本原因:

(1)單庫情況下,服務層在進行1s的邏輯計算過程中,可能讀到舊資料入快取

(2)主從庫+讀寫分離情況下,在1s鐘主從同步延時過程中,可能讀到舊資料入快取

既然舊資料就是在那1s的間隙中入快取的,是不是可以在寫請求完成後,再休眠1s,再次淘汰快取,就能將這1s內寫入的髒資料再次淘汰掉呢?

答案是可以的。

寫請求的步驟由2步公升級為3步:

(1)先淘汰快取

(2)再寫資料庫(這兩步和原來一樣)

(3)休眠1秒,再次淘汰快取

這樣的話,1秒內有髒資料如快取,也會被再次淘汰掉,但帶來的問題是:

(1)所有的寫請求都阻塞了1秒,大大降低了寫請求的吞吐量,增長了處理時間,業務上是接受不了的

再次分析,其實第二次淘汰快取是「為了保證快取一致」而做的操作,而不是「業務要求」,所以其實無需等待,用乙個非同步的timer,或者利用訊息匯流排非同步的來做這個事情即可

寫請求由2步公升級為2.5步:

(1)先淘汰快取

(2)再寫資料庫(這兩步和原來一樣)

(2.5)不再休眠1s,而是往訊息匯流排esb傳送乙個訊息,傳送完成之後馬上就能返回

這樣的話,寫請求的處理時間幾乎沒有增加,這個方法淘汰了快取兩次,因此被稱為「快取雙淘汰」法。這個方法付出的代價是,快取會增加1次cache miss(代價幾乎可以忽略)。

而在下游,有乙個非同步淘汰快取的消費者,在接收到訊息之後,asy-expire在1s之後淘汰快取。這樣,即使1s內有髒資料入快取,也有機會再次被淘汰掉。

上述方案有乙個缺點,需要業務線的寫操作增加乙個步驟,有沒有方案對業務線的**沒有任何入侵呢,是有的,這個方案在《細聊冗餘表資料一致性》中也提到過,通過分析線下的binlog來非同步淘汰快取:

業務線的**就不需要動了,新增乙個線下的讀binlog的非同步淘汰模組,讀取到binlog中的資料,非同步的淘汰快取。

提問:為什麼上文總是說1s,這個1s是怎麼來的?

回答:1s只是乙個舉例,需要根據業務的資料量與併發量,觀察主從同步的時延來設定這個值。例如主從同步的時延為200ms,這個非同步淘汰cache設定為258ms就是ok的。

在「異常時序」或者「讀從庫」導致髒資料入快取時,可以用二次非同步淘汰的「快取雙淘汰」法來解決快取與資料庫中資料不一致的問題,具體實施至少有三種方案:

(1)timer非同步淘汰(本文沒有細講,本質就是起個執行緒專門非同步二次淘汰快取)

(2)匯流排非同步淘汰

(3)讀binlog非同步淘汰

58沈劍架構系列 資料庫秒級平滑擴容架構方案

一 緣起 1 併發量大,流量大的網際網路架構,一般來說,資料庫上層都有乙個服務層,服務層記錄了 業務庫名 與 資料庫例項 的對映關係,通過資料庫連線池向資料庫路由sql語句以執行 如上圖 服務層配置使用者庫user對應的資料庫例項物理位置為ip 其實是乙個內網網域名稱 2 隨著資料量的增大,資料要進...

MySql資料庫 58沈劍 架構師之路

innodb,5項最佳實踐,知其所以然?innodb行鎖,如何鎖住一條不存在的記錄?innodb併發如此高,原因竟然在這?innodb,能將資料儲存在 裡?挖坑,innodb的七種鎖 插入innodb自增列,居然是表鎖?innodb併發插入,居然使用意向鎖?innodb,select為啥會阻塞ins...

58沈劍架構系列 一分鐘寫好連線池

一 如何通過連線訪問下游 工程架構中有很多訪問下游的需求,下游包括但不限於服務 資料庫 快取,其通訊步驟是為 1 與下游建立乙個連線 2 通過這個連線,收發請求 3 互動結束,關閉連線,釋放資源 這個連線是什麼呢,通過連線怎麼呼叫下游介面?服務 資料庫 快取,官方會提供不同語言的driver doc...