OpenMLDB 跨機房容災方案

openmldb發表於2023-02-14

背景

在單叢集部署環境下,OpenMLDB 具備叢集內節點級別的高可用能力。但若受到機房斷電或者自然災害等不可抗拒因素,則將造成的機房或大部分節點無法正常運轉的情況,從而引發該叢集狀態異常,導致線上服務中斷。為此,OpenMLDB 提供了一個跨機房容災方案來解決該問題。在該方案中,使用者可以在多個異地機房,分別部署獨立的 OpenMLDB 叢集,並且將這多套 OpenMLDB 叢集設定成為主從複製模式。在這種部署架構下,如果主叢集無法提供服務,使用者可以進行主從切換,從而保證業務不中斷。

架構

名詞定義

  • 主叢集:能支援讀寫的叢集,並且可以給從叢集同步資料。一個主叢集可以有多個從叢集。
  • 從叢集:只提供讀請求的叢集,資料和主叢集保持一致;可以在需要的時候切換為主叢集;可以部署多個。
  • 分片 leader:主分片,接收讀寫資料。
  • 分片 follower:從分片,只接受分片 leader 同步過來的資料,目前不接受客戶端的直接寫請求。
  • offset:本文 offset 特指 OpenMLDB 的 binlog 所儲存的資料偏移量,該值越大,說明儲存有更多的新鮮資料。

關於名詞的進一步解釋可以檢視 OpenMLDB 的線上模組架構文件:

目標

  • 主叢集支援寫操作,主從叢集都可以支援讀操作
  • 一個主叢集可以有多個從叢集作為備份
  • 主叢集出現意外不可用時能夠手動切換,讓其中一個從叢集提升為主叢集
  • 能夠自動處理主叢集或者從叢集內部節點下線不可用(包括 nameserver 和 tablet)的情況

技術方案

主從叢集的整體技術架構如下圖所示:
file
主從叢集之間的同步資訊,主要包含資料同步和元資訊同步兩部分。

初始狀態

對於主從叢集的初始狀態,可以為以下狀態之一:

  • 主叢集和從叢集的資料均為空
  • 主或從叢集不為空,主從叢集的表名以及 schema 一致,並且主叢集 offset 大於等於從叢集的 offset,否則會報錯。

元資訊同步

元資訊同步發生在主從叢集的 nameserver 之間。具體的過程如下:

  • 建立好主從關係之後,主叢集的 nameserver 會向從叢集同步主叢集的表資訊,從叢集建立相應的表。注意,主從叢集節點數不需要一致,但是每張表的分片數需要保持一致。
  • 主叢集的 nameserver 每隔一段時間獲取從叢集的表拓撲資訊

資料同步

主從叢集之間的資料同步主要透過 binlog 進行,其總體的同步邏輯如下:

  • 單叢集內部:leader → followers 同步資料
  • 主從叢集之間:主叢集 leader → 從叢集 leader 同步資料
    下圖視覺化列舉了該同步邏輯和資料流方向。
    file
    假設有一個從叢集,表為三副本。其具體過程為:主叢集分片的 leader 會建立兩個 replicator 執行緒來負責叢集內部資料同步,以及 1 個 replicator 執行緒來負責同步資料到從叢集的 leader;從叢集的 leader 會建立兩個 replicator 執行緒,分別給從叢集內部的 followers 同步資料。
    replicator 的具體同步邏輯如下:
  • 讀取 binlog 並把資料傳給 follower
  • follower 收到資料,新增到本地 binlog,同時寫到本地分片表中
    預設情況下,replicator 會不斷讀取最新的 binlog,如果沒有最新資料寫入就會等待一小段時間(預設為 100ms),再嘗試讀取。在同步時效性要求比較高的場景下,可以修改預設配置(引數 binlog_sync_wait_time,詳見文件配置檔案),減少等待時間,但是可能會增加 CPU 的資源消耗。

叢集內部自動故障轉移

主叢集 nameserver 離線

  • 主叢集中主 namserver 離線之後,主叢集中的備 nameserver 就會升級為主 nameserver,更新從叢集中表的拓撲資訊到新的主 nameserver
  • 主叢集中備 nameserver 離線,不做任何操作

從叢集 nameserver 離線

  • 從叢集中主 nameserver 離線之後,從叢集中的備 nameserver 就會升級為主 nameserver。主叢集向從叢集獲取表拓撲資訊時,返回錯誤,主叢集就會讀取從叢集的 ZooKeeper 資訊,以獲取最新的主 nameserver,然後更新表拓撲資訊
  • 從叢集中備 nameserver 離線之後不做任何操作

主叢集 tablet 離線

  • 主叢集內做故障轉移,相應的分片選出新的 leader
  • 新的 leader 重新和從叢集中分片所在的 tablet 建立資料同步關係

從叢集 tablet 離線

  • 從叢集做故障轉移,相應的分片選出新的 leader
  • 主叢集 nameserver 獲取從叢集表拓撲結構發現已經有變化,刪除對應變化分片的資料同步關係並重新建立

主從叢集間手動故障轉移

主叢集不可用
透過運維命令,提升從叢集為主叢集。同時,業務方的寫流量和讀流量需要切換到當前的新的主叢集下,該流量的切換過程需要由業務方系統來完成。
從叢集不可用
業務方原有在從叢集上的讀流量(如果有),需要全部切換到主叢集下。該流量的切換過程需要由業務方系統來完成。

主從叢集搭建實踐

叢集啟動後預設為主叢集。透過命令可以將一個叢集新增為另一個叢集的從叢集,或者進行切換、移除。

啟動 NS client

主從叢集的管理在 NS client 下進行操作,可以使用如下命令啟動 NS client。

$ ./bin/openmldb --zk_cluster=172.27.2.52:12200 --zk_root_path=/onebox --role=ns_client

其中  zk_cluster 是 ZooKeeper 地址, zk_root_path 是叢集在 ZooKeeper 的根路徑, role 是啟動的角色需指定為  ns_client

關於 NS client 的更多資訊,可以參考運維 CLI。

新增從叢集

可以使用命令  addrepcluster 來新增一個從叢集,其使用格式為:

addrepcluster $zk_cluster_follower $zk_root_path_follower $cluster_alias

比如需要新增的從叢集的 ZooKeeper 地址為  10.1.1.1:2181,OpenMLDB 在該 ZooKeeper 上的根路徑為  10.1.1.2:2181 /openmldb_cluster,新增以後的從叢集別名為  prod_dc01,則可以在主叢集的 NS client 上執行如下命令進行從叢集的新增:

addrepcluster 10.1.1.1:2181,10.1.1.2:2181 /openmldb_cluster  prod_dc01

移除從叢集

可以執行命令  removerepcluster 來刪除一個從叢集,比如刪除上面新增的從叢集  prod_dc01

removerepcluster prod_dc01

切換叢集角色

switchmode 命令可以修改叢集的角色。引數可以為  leader 或者  normal。如果需要把從叢集提升成主叢集,引數設定為 leader。如果要修改為普通的叢集,引數設定為 normal。

switchmode leader

檢視從叢集

showrepcluster 命令可以查詢所有從叢集,輸出結果類似:
file

FAQ

Q1: 如何解決分散式的“腦裂”問題?

A1:在分散式環境中,經常會遇到“腦裂”問題。所謂腦裂,簡單來說就是在某些非正常狀態下(比如由於網路阻塞),兩個叢集選舉出了不同的 leader。Raft 之類的一致性協議能很好的解決類似問題,如要求 leader 必須獲取半數以上的投票。
OpenMLDB 的選主和這些協議不太一樣,OpenMLDB 是由 ZooKeeper 和 nameserver 來選主的。節點是否下線透過 ZooKeeper 中 ephemeral node 實現,nameserver 選主的時候從該叢集的所有 follower 中選擇 offset 最大的一個作為新的 leader,所以本質上來說 OpenMLDB 的主從叢集方案不會出現腦裂的問題。

Q2: 如何判斷主叢集不可用,需要進行主從切換?

A2: 目前 OpenMLDB 在叢集整體不可用的狀態上並不會自動判斷或自動切換,設計主從叢集方案主要是為了應對如機房斷電等重大事故。
因此目前需要人為主觀去判斷主叢集是否處於不可用狀態,從而需要進行主從切換。造成主叢集不可用的常見原因如:整個叢集的伺服器不可抗拒原因無法訪問、ZooKeeper 無法恢復、部分 tablet 下線導致無法恢復或者恢復時間過長等。

Q3: 是否可能在某些情況下會資料丟失?

A3: 雖然主從叢集方案增加了多一層的高可用機制,但是也不能保證資料完全不丟失,以下情況依然會出現資料丟失,相關問題均會在後續版本進行修復或者最佳化:

  • 主叢集內部 tablets failover 後,新選出來的 leader 的 offset 比從叢集中的 leader 的 offset 小,會造成兩者 offset 差值之間的這部分資料丟失
  • 主從切換過程中,如果主叢集有寫流量,那麼可能會造成部分未及時從原有主叢集同步到從叢集的資料丟失
  • 從叢集表格拓撲發生變化,並且主叢集尚未捕獲,此時如果執行主從切換,會造成從拓撲結構發生變化到切換成功之間的資料丟失

Q4: 是否可以支援多個從叢集

A4: 一個主叢集可以支援多個從叢集,只要在主叢集上執行新增從叢集命令 addrepcluster 進行新增即可。

Q5: 和業界其他主從叢集方案的比較?

A5file
file
列舉了兩個業界常用資料庫作為比較 —— TiDB 和 MySQL,OpenMLDB 的做法和這兩個在架構上比較相似。TiDB 將資料從 TiKV 傳到 TiFlash 也是透過類似方式完成的,TiFlash 有一個 Learner 的概念類似於 OpenMLDB 從叢集的 leader。TiKV 會把資料同步到 Learner 上面,然後再由 Learner 去做叢集內的資料同步。MySQL 的主從複製,跟我們做法也是類似的,它也是透過 binlog,將資料定期地同步到從叢集上面,從叢集再進行 binlog 的叢集內讀取和同步。

開發進度

目前主從叢集方案在實驗階段,其核心功能都已經開發完畢,並且進行了充分的測試。目前主要遺留問題為:

  • SQL 命令目前只有建立表、刪除表、以及資料插入操作可以主從叢集自動同步,其餘命令(比如 SQL 上線,修改 TTL 等)目前尚不支援自動同步,需要手動在主從叢集上分別執行。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70026745/viewspace-2935255/,如需轉載,請註明出處,否則將追究法律責任。

相關文章