Geo-replication: 從 Copysets 到 Tiered Replication
對於分散式儲存系統,我們都會使用多副本的機制來保證資料的安全性。譬如對於 TiKV 來說,我們預設會使用 3 個副本,如果需要更高等級的安全性,譬如在銀行領域,我們則會使用 5 個副本。但無論使用幾個副本,我們都會面臨一個問題,我們如何在叢集中放置這些副本。
機器都是有壽命的,磁碟,記憶體等硬體在執行的時候也時不時會壞掉。假設現在我們使用 3 個副本,有 N 臺機器,如果同時有 3 臺機器壞掉,而悲催的是剛好 3 個副本在這 3 臺機器上面,那麼我們就會面臨資料丟失問題。所以我們需要儘量減少資料丟失的概率。
Random replication
最簡單的做法就是選擇任意 3 臺機器來放置副本,但是這個策略其實不好。假設機器壞掉的概率是 1%,對於 3 副本來說,同時壞掉的概率是 0.0001%,看起來這個是很低的,但實際中,我們不光只有一份資料。
在 TiKV 裡面我們會將資料切分成多個 region,每個 region 對應一份資料,在實際生產環境中,region 數量是非常多的,一些叢集都已經過了百萬了,這時候如果有 3 個節點同時損壞,一些 region 副本全丟掉的概率會非常的大。
下圖是 Copysets paper 裡面給出的資料,可以看到,那麼隨著節點數的增多,使用隨機複製方式的 3 副本掉資料的概率會急劇的增大:
Copysets replication
為了解決 Random replication 的問題,有人提出了 Copysets,也就是論文 Copysets: Reducing the Frequency of Data Loss in Cloud Storage,相比於使用 random 方式,Copysets 引入了 scatter width,將整個叢集節點進行分組,然後在分組的集合裡面選擇節點進行復制。
Copysets 的演算法其實比較簡單,假設叢集數量是 N,複製因子是 R(其實就是選擇幾個副本),scatter width 是 S,那麼:
- 建立
S / (R - 1)
個節點排列 - 將每個排隊分成 R 組
- 隨機選擇一個節點當成副本的 primary 副本
- 在分組的包含 primary 節點的集合裡面隨機選擇 secondary 副本
譬如,假設我們有 9 個節點,R 是 3,而 S 是 2,那麼就有 2 / (3 - 1) = 1
個排列,譬如 [1, 6, 5, 3, 4, 8, 9, 7, 2]
,然後我們分成 3 組,也就是 [1, 6, 5], [3, 4, 8], [9, 7, 2]
。
對於 3 副本,假設我們選擇 1 作為 primary 副本存放的節點,那麼剩下兩個 secondary 副本只能在 6 和 5 上面選取。
使用 Copysets,能有效的降低丟失資料的概率,根據 Paper 裡面描述,在 5000 個節點下面,如果有 1% 的節點同時掛掉,random 丟失的概率是 99.99%,而 Copysets 則是 0.15%。
Tiered Replication
當然,copysets 並不是銀彈,它並不能解決叢集動態擴容的問題,於是 copysets 的作者,繼續研究了另一個解決方案,也就是 Tiered replication,Paper 是 Tiered Replication: A Cost-effective Alternative to Full Cluster Geo-replication。
Tiered Replication 的原理其實也比較簡單,仍然有 Copysets 的概念 scatter width S,會將整個叢集分成多個 Copysets,每個 Copysets 的大小是 R,對於每個節點,必須保證它至少在 S 個 Copysets 裡面。另外,Tiered Replication 裡面也有 primary 和 backup 節點的區分,通常兩個副本會放在 primary 節點裡面,而第三個副本則會放到 backup 節點裡面。
Tiered Replication 的演算法比較簡單,大概來說:
- 所有節點開始的 scatter width 是 0,也就是沒有屬於任何 Copysets。
- 建立一個 Copysets,選擇最小 scatter width 的 R 個節點加進去。
- 重複上面的過程,直到所有的節點的 scatter width 至少是 S。
詳細的演算法可以看 Paper,而原始碼在這裡,使用起來還是很簡單的,譬如:
# not rack aware
>>> trepl.build_copysets(['node1', 'node2', 'node3'], R=2, S=1)
[['node1', 'node2'], ['node1', 'node3']]
# rack aware, node1 and node2 can not share a copyset since they're in
# the same rack
>>> rack_map = { 'node1': 'rack1', 'node2': 'rack1', 'node3': 'rack3' }
>>> trepl.build_copysets(
rack_map.keys(), R=2, S=1,
checker=trepl.checkers.rack(rack_map),
)
[['node1', 'node3'], ['node2', 'node3']]
對於叢集的動態更新,譬如新加入一個節點,就直接按照上面的演算法,將這個節點加入到不同的 Copysets 裡面,直到這個新加入的節點的 scatter width 為 S。而對於刪除節點,一個簡單的做法就是將包含這個刪除節點的 Copysets 幹掉,而在這些 Copysets 裡面的其他正常節點的 scatter with 也會減少,然後會建立新的 Copysets 替換老的。在老的 Copysets 裡面的正常副本可能會重新複製到其他節點上面。
總結
說了這麼多,對 TiKV 來說有什麼借鑑意義呢?現在 TiKV 是通過打 label 的方式來支援 Geo-replication 的,假設我有 3 個 Rack,每個 IDC 有 3 臺機器,我們會給每個啟動在機器上面的 TiKV 程式打上類似 rack = rack1, host = host11
這樣的標籤,PD 就會將 3 個副本分散到不同 Rack 的不同機器上面,但在 Rack 機器的選擇上面,我們還是一個 random 演算法。也就是說,即使能保證副本在不同的 Rack 上面,但隨著每個 Rack 機器數量的增多,我們 3 副本同時丟失的概率就會增大,所以自然需要一個更好的副本複製策略。如果你對這方面感興趣,歡迎聯絡我 tl@pingcap.com。
相關文章
- Redis 主從複製(Replication)Redis
- Redis replication主從複製原理及配置Redis
- 含有replication環境的sqlserver切換到standbySQLServer
- MySQL Group ReplicationMySql
- Build mysql replicationUIMySql
- HBase Replication詳解
- An Overview of PostgreSQL & MySQL Cross ReplicationViewMySqlROS
- How to Optimize PostgreSQL Logical ReplicationSQL
- Mysql replication check指令碼MySql指令碼
- MySQL group replication介紹MySql
- Replication (Part 2): Transactions, Consistency and Consensus
- Redis replication 中的探活Redis
- Mysql Replication學習記錄MySql
- 從2012到2021,從土木到程式設計師程式設計師
- Step by Step Data Replication Using Oracle GoldenGateOracleGo
- Setup MariaDB Master/Slave Replication for Docker MariaDBASTDocker
- MySQL基於GTIDs的MySQL ReplicationMySql
- 從DDPM到DDIM
- 從RNN到BERTRNN
- C++ 從&到&&C++
- 從HTTP到HTTPSHTTP
- 從DevOps到ContainerOpsdevAI
- 從SpringBoot到SpringMVCSpring BootSpringMVC
- 從Windows到LinuxWindowsLinux
- Overview of LiquidUI WS&Designer-Customization-Replication on iOSViewUIiOS
- MGR(MySQL Group Replication)部署搭建測試MySql
- MYSQL Group Replication搭建過程記錄MySql
- 關於意義:從現實到遊戲,從自我到自由遊戲
- MySQL8.0.16新特性:The Communication Protocol In Group ReplicationMySqlProtocol
- group_replication_bootstrap_group 用於什麼boot
- PhpRpc 從 0 到 0.7PHPRPC
- zookeeper從小白到精通
- json從立地到成佛JSON
- 從Node到Deno - DEVdev
- 從前端到全棧前端全棧
- 從synchronize到CSA和
- 前端從? 到? gRPC 框架前端RPC框架
- PHash從0到1