詳解GaussDB(for MySQL)服務:複製策略與可用性分析

華為雲開發者社群發表於2020-08-06
摘要:本文通過介紹GaussDB(for MySQL)讀寫路徑,分析其可用性。

簡介

資料永續性服務可用性是資料庫服務的關鍵特徵。

在實踐中,通常認為擁有 3 份資料副本,就足以保證永續性。

但是 3 份副本,對於可用性的要求是不夠的。維護 3 份一致的副本意味著,這些副本必須同時線上,系統才能保證可用。當資料庫跨多個節點分片時,某些節點不可用的概率會隨著節點數量的增加而呈指數增長。

在 GaussDB(for MySQL) 中,我們針對日誌和資料採用不同副本策略,並採用一種新穎的恢復演算法,來解決可用性的問題。

下面首先介紹寫路徑,然後介紹讀路徑,最後分析理論上的可用性估計,並與其它副本策略進行比較。

寫路徑

寫路徑如上圖所示,下面對每一個步驟進行說明。

1)使用者事務導致對資料庫頁面的更改,從而生成描述更改的日誌記錄(redo log,下面簡稱 redo)。

2)將 redo 寫入到 Log Stores。寫入 3 份副本,並且採用強一致性,即 3 份均寫入成功才算成功。

3)將事務標記為已提交(committed)。

只要叢集中有三個或以上的 Log Stores 可用,該資料庫就可以進行寫操作(因為寫入只需要選擇可用的節點即可,並不規定一定要寫入某個節點)。對於成千上萬個節點的群集,這實際上意味著 100% 的寫入可用性。

4)redo 寫入 Log Stores 之後,會將此 redo 放入到 SAL 的 write buffer 中,之後將此 buffer 寫入到管理對應 slice 的 Page Store 上。

5)當任何一個 Page Store 副本返回成功,此寫入成功,SAL 的 write buffer 被釋放。

6)不同的 Page Store 副本之間使用 gossip 協議檢測和修復缺失的日誌。

空間回收

資料庫執行過程中,會源源不斷地產生 redo 日誌。如果不將不需要的 redo 刪除,可以預見,最終肯定會耗盡磁碟空間。在成功將 redo 寫入所有 Slice 副本,並且所有資料庫的讀副本(read replica)都可以看到該記錄之後,就可以將該日誌從 Log Store 中刪除。獨立地跟蹤每條 redo 的永續性很費資源,因此我們選擇基於 LSN 來跟蹤永續性。

對於 Page Store 的每個 slice,都有一個 persistent LSN,它的含義是 slice 接收到的所有日誌記錄中,保證連續(沒有空洞)的最大 LSN。(譬如某個 slice 接收到 LSN 為 1 的 redo log 後,persistent LSN 變為 1,此時如果接收到 LSN 為 3 的 redo log,persistent LSN 依然為 1。之後如果接收到 LSN 為 2 的 redo log,即補齊了空洞之後, persistent LSN 變為 3)。

7)SAL 可以通過定期呼叫 api 或者在讀寫介面中獲取每個 slice 的 persistent LSN(在恢復中也會使用)。

8)SAL 也會跟蹤每個 PLog 的 LSN 範圍。如果 PLog 中的所有 redo 的 LSN 都小於資料庫 persistent LSN(3 副本中最小 persistent LSN),該 PLog 可被刪除。

通過上面的機制,我們能夠保證每條 redo 都至少會有三個節點上存在副本(一開始在 Plog Store 節點上有 3 副本,保證在 Page Store 節點上有 3 副本之後,將 Plog Store 節點上的副本刪除,以回收磁碟資源)。

讀路徑

資料庫前端以 page 粒度讀取資料。

讀取或者修改資料時,相應的 page 必須在 buffer pool 中。當 buffer pool 已滿,我們又需要引入一個 page 時,必須將某些頁面從 buffer pool 中淘汰。

我們對淘汰演算法進行了修改,保證只有當所有相關 redo 日誌都寫入至少 1 個 Page Store 副本後,髒頁才能被淘汰。因此,在最新的 redo 記錄到達 Page Store 之前,保證相應的頁面可從 buffer pool 中獲得。 之後,可以從 Page Store 中讀取頁面。

對於每一個 slice,SAL 儲存最新 redo log 的 LSN。主節點讀取 page 時,讀請求首先到達 SAL,SAL 會使用上述 LSN 下發讀請求。讀請求會被路由到時延最低的 Page Store。如果被選擇的 Page Store 不可用或者還沒有收到提供 LSN 之前的所有 redo,會返回錯誤。之後 SAL 會嘗試下一個 Page Store,遍歷所有副本,直到讀請求可以被正確響應。

可用性分析

quorum replication

目前業界最廣泛使用的強一致性複製技術基於 quorum replication。如果每份資料在 N 個節點上存在副本,每個讀取操作必須從NR個節點接收響應,並寫入NW個節點。

為了保證強一致性,必須滿足 NR + NW > N 。業界許多系統使用 quorum replication 的不同組合方式。 例如,

1)RAID1 磁碟陣列中通常使用 N = 3,NR = 1,NW = 3;

2)PolarDB 中,N = 3,NR = 2,NW = 2;

3)Aurora 中,N = 6,NR = 3,NW = 4。

下面的分析中,僅考慮節點單獨出現不可用的場景(不考慮譬如因為斷點導致所有節點不可用的場景)。

假設 1 個節點不可用的概率為 x,則當 N - NW + 1 到 N 個節點同時不可用時,寫請求會失敗。 即一個寫請求失敗的概率可用如下公式計算:

同理,一個讀請求失敗的概率計算公式如下:

GaussDB(for MySQL)

在前面的寫路徑一節中已經提到,GaussDB(for MySQL) 的寫 redo,不需要寫到特定的 Log Store 上,所以公式 (1) 並不適用。對於寫請求,只有當所有 PLog Store 都不可用時,才會失敗。如果叢集中 Log Store 足夠多,這個概率幾乎接近於 0。

對於讀,每個 Page Store 節點都可以基於其 persistent LSN 決定是否可以為讀提供服務。如果不能,它將返回錯誤,告訴 SAL 嘗試另一個節點。在極少數情況下,由於級聯故障,沒有節點可以提供讀服務(並非節點不可用),SAL 會識別這種情況並使用 Log Store 來修復資料。在這種情況下,效能可能下降,但是儲存層仍然可用。

SAL 無法恢復的唯一情況是,包含 Slice 副本的所有 Page Store 都不可用,這樣的概率是 x^3。

下表對比了 GaussDB(for MySQL) 和幾種典型 quorum replication 場景的可用性:

結論

1)對於寫,GaussDB(for MySQL) 總是可用的,優於 quorum replication 方案;

2)對於讀,除了 x = 0.01 且 quorum 的節點個數為 6 的情況,GaussDB(for MySQL) 總是能提供比 quorum replication 相同或更好的的可用性。並且在上面的場景下,提供的可用性已經足夠高,與 quorum replication 相差並不遠。

點選關注,第一時間瞭解華為雲新鮮技術~

相關文章