Designing-Data-Intensive-Applications Ch5 Note

Ngchiwa Ng
9 min readAug 18, 2021

--

ref: https://github.com/Vonng/ddia/blob/master/zh-tw/ch5.md

複制

  • 使得資料與使用者在地理上接近(從而減少延遲)
  • 即使系統的一部分出現故障,系統也能繼續工作(從而提高可用性)
  • 伸縮可以接受讀請求的機器數量(從而提高讀取吞吐量)

三種流行的變更復制演算法:

  • 單領導者(single leader)
  • 多領導者(multi leader)
  • 無領導者(leaderless)

— —

master/slave 工作原理如下:

  1. client 寫在主庫,主庫replicate log 到從庫
  2. 當客戶想要從資料庫中讀取資料時,它可以向領導者或追隨者查詢。 但只有領導者才能接受寫操作

同步複製 / 非同步複製

一般來說 ,多個slave ,可以設一個slave 為同步複製,其他為非同步複製。(如果全部slave 都設為同步,只有一個salve 有問題就變得不可用了)

主庫和同步從庫。 這種配置有時也被稱為 半同步(semi-synchronous)

  • 好處: 主庫壞了,還有一個從庫是和主庫一樣的資料

設定新從庫

​ 有時候需要設定一個新的從庫,為了:

  • 增加副本的數量
  • 換失敗的節點

COPY原理是怎樣?

​ 概念:

  1. 在某個時刻獲取主庫的一致性快照(如果可能),而不必鎖定整個資料庫。
  2. 將快照複製到新的從庫節點。
  3. 從庫連線到主庫,並拉取快照之後發生的所有資料變更。
  4. 當從庫處理完快照之後積壓的資料變更,我們說它 趕上(caught up) 了主庫。現在它可以繼續處理主庫產生的資料變化了。

— — —

處理節點宕機

​ 資料庫是如何實現高可用,我們可以分為 從庫失效和主庫失效

  • 從庫失效:追趕恢復

從庫可以從日誌中知道,在發生故障之前處理的最後一個事務。因此,從庫可以連線到主庫,並請求在從庫斷開連線時發生的所有資料變更。當應用完所有這些變化後,它就趕上了主庫,並可以像以前一樣繼續接收資料變更流。

  • 主庫失效:故障切換

其中一個從庫需要被提升為新的主庫,需要重新配置客戶端,以將它們的寫操作傳送給新的主庫,其他從庫需要開始拉取來自新主庫的資料變更。這個過程被稱為故障切換(failover)。

通常由以下步驟組成:

1.確認主庫失效。

2.選擇一個新的主庫。(主庫的最佳人選通常是擁有舊主庫最新資料副本的從庫(最小化資料損失))

3.重新配置系統以啟用新的主庫。

故障切換會出現很多大麻煩:

  • 如果使用非同步複製,則新主庫可能沒有收到老主庫最後的寫入操作。在選出新主庫後,如果老主庫重新加入叢集,新主庫在此期間可能會收到衝突的寫入,那這些寫入該如何處理?
    -> 最常見的解決方案是簡單丟棄老主庫未複製的寫入,這很可能打破客戶對於資料永續性的期望。
  • 如果資料庫需要和其他外部儲存相協調,那麼丟棄寫入內容是極其危險的操作。EX 舊資料庫有 id 002(沒送到slave),slave 變主庫又生了一個id002
  • 發生某些故障時,可能會出現兩個節點都以為自己是主庫的情況
  • 設定heart beat 時間多久?

— —

實際是怎樣同步到其他資料庫?

複製日誌的實現

  • 基於語句的複製 — ex: send “INSERT xxx” 到 從庫
    問題: 如果用到函數 就有問題(RAND(), NOW()…)
  • 傳輸預寫式日誌(WAL) — 之前提到的 日誌結構儲存引擎 的日誌或B樹 預寫式日誌(Write Ahead Log, WAL)
    問題:
    - 日誌記錄的資料非常底層,有時和資料庫版本 也會影響
  • 邏輯日誌複製(基於行) — 另一種日誌,比較易parse 和操作
  • 基於觸發器的複製 — 資料庫可以註冊程式,只要資料修改都會觸發
    問題: ​ 基於觸發器的複製通常比其他複製方法具有更高的開銷,並且比資料庫的內建複製更容易出錯

— — — —

複製延遲問題

解決方法

  • 讀己之寫
  • 單調讀

讀己之寫

使用者可以看到自己寫的最新內容,但其他用者是從 slave 來讀(比較慢),方法:

  1. 讀使用者可能已經修改過的內容時,都從主庫讀。EX USER看自己的個人資料,都是從主庫,其他人看則是從 Slave
  2. 系統 記住 最後一次的更新時間,如果在1分鐘內,則全部都改到主庫讀。
  3. client 記住最後一次的更新時間,系統從某個資料庫讀到的更新時間 < 最後一次的更新時間, 就從其他資料庫讀

如果user 使用多裝置,一邊更新完,另一邊要看到更新就更麻煩:

  1. client 記住最後一次的更新時間 ,不同裝置不一樣
  2. 如果副本分佈在不同的資料中心,很難保證來自不同裝置的連線會路由到同一資料中心。
  • 單調讀
    就是按user id 來分配,只能固定到某一個slave

以下是是其他人從 SLAVE讀有問題,單調讀就是可以解決下面的問題

user 2345 都是從slave 讀,有時某個slave 比較慢,就會遇到有時看到資料更新,但有時還是舊的情狀

— — — —

如果是分多個partion 時,可能會遇到 上述的 情況(可能網路延遲)

observer 就會先聽到後面的內容

這種有因果順序的資料,可以用都寫在同一個 partion 來解決

/*一致字首讀(consistent prefix reads)。 這個保證說:如果一系列寫入按某個順序發生,那麼任何人讀取這些寫入時,也會看見它們以同樣的順序出現。 */

— — —

多主複製

之前討論的都是單一個master , 缺點就是如果掛了,就無法寫入 或者有多個data center

  • 多領導者配置中可以在每個資料中心都有主庫。

/*在單個數據中心內部使用多個主庫很少是有意義的,因為好處很少超過複雜性的代價。/

好處:

效能: 因為使用者不知道有異步 sync 資料到另一個DATA center ,無差別

容忍資料中心停機: 一邊壞了還可以寫入

容忍網路問題:如果和同一個data center , 因為是另一個DATA center 所以使用非同步,所以容忍度更高

需要離線操作的客戶端:試想手機的LOCLA DATA(也比喻為一個DATA center) 可以讓使用者在沒有網路下使用

— —

​ 多領導者複製的最大問題是可能發生寫衝突,這意味著需要解決衝突。

同步衝突檢測: 要等到全部副本OK,才和使用者說,但這樣就沒有義意

避免衝突: 都由某一個data center 的主庫做寫入(最常做的方法)

收斂至一致的狀態:

實現衝突合併解決有多種途徑:

  • 給每個寫入一個唯一的ID,挑選最高ID的寫入作為勝利者,並丟棄其他寫入。如果使用時間戳,這種技術被稱為最後寫入勝利(LWW, last write wins)。雖然這種方法很流行,但是很容易造成資料丟失
  • 為每個副本分配一個唯一的ID,ID編號更高的寫入具有更高的優先順序。這種方法也意味著資料丟失。
  • 以某種方式將這些值合併在一起 — 例如,按字母順序排序,然後連線它們(在圖5–7中,合併的標題可能類似於“B/C”)。
  • 用一種可保留所有資訊的顯式資料結構來記錄衝突,並編寫解決衝突的應用程式程式碼(也許透過提示使用者的方式)。

自定義衝突解決邏輯

太部分多主的資料庫,有一些設定程式碼來解決衝突。該程式碼可以在寫入讀取時執行

寫入執行:檢測到複製更改日誌中存在衝突,就會呼叫衝突處理程式。

讀取時執行:當檢測到衝突時,所有衝突寫入被儲存。 然後使用者讀的使用,會跳出來不同的版本選擇更新。

— — —

多主複製拓撲

在描述如果有多個master 時,要怎樣傳送消息

一般使用一個unique id 來決定有沒有收過那樣的訊息防止LOOP

— — — — — — — — — — — -

無master mode

如果有些update where xxx= ? 因為網路問題會遇到以下問題:

insert x=1

update x=2 where x=1
update x=3 where x=2 //< 這個就會遇到其他主庫還沒update為2 就update 不成功

因為主庫update 有不一樣的棘手的問題, 所以有 無主庫的概念

— -

那無主庫怎樣handel 資料

讀修復和反熵

​ 複製方案應確保最終將所有資料複製到每個副本。在一個不可用的節點重新聯機之後,它如何趕上它錯過的寫入?

​ 在Dynamo風格的資料儲存中經常使用兩種機制:

- 讀修復(Read repair)

當client 對全部replica 讀取資料,只要有一個不符時,則比較那個比較新,主動發起update

反熵過程(Anti-entropy process)

某些資料庫會不斷查詢其他replica 有沒有不一樣

— —

如果有三個副本,只要有兩個成功寫入就叫成功。那大於三個時怎樣決定?

讀寫的法定人數

如果有n個副本,每個寫入必須由w節點確認才能被認為是成功的,並且我們必須至少為每個讀取查詢r個節點。

只要$w + r> n

ex: 5(n) 個節點,寫入時至少3 個寫入成功的話,則讀時要至少向r=2 個副本來讀

但這種還有一定的風險

— -

--

--

Ngchiwa Ng
Ngchiwa Ng

Written by Ngchiwa Ng

Backend/iOS Engineer, rock the world

No responses yet