TiDB 6.0 實戰分享丨冷熱儲存分離解決方案

語言: CN / TW / HK

結論先行

TiDB 6.0 正式提供了資料放置框架(Placement Rules in SQL )功能,使用者通過 SQL 配置資料在 TiKV 叢集中的放置位置,可以對資料進行直接的管理,滿足不同的業務場景需要。如:

1.冷熱分離儲存,降低儲存成本

  • TiDB 6.0 正式支援資料冷熱儲存分離,可以降低 SSD 使用成本。使用 TiDB 6.0 的資料放置功能,可以在同一個叢集實現海量資料的冷熱儲存,將新的熱資料存入 SSD,歷史冷資料存入 HDD,降低歷史歸檔資料儲存成本。
  • 將熱資料從 ssd 遷移到 hdd,每小時可歸檔約 3000 萬行,總體來看效率還是比較高的
  • 將冷資料從 hdd 遷移到 ssd,每小時可遷移約 6300 萬行,大約是從 ssd 遷移到 hdd 速度的 2 倍
  • 分離儲存過程,ssd 和 hdd 用於歸檔的 IO 消耗都在 10%以內,叢集訪問 QPS 表現平穩,對業務訪問的影響較小
  • 在補寫冷資料場景,每小時寫入約 1500 萬行到 hdd,資料可正確地直接寫入 hdd,不會經過 ssd

2.業務底層物理隔離,實現同一叢集不同儲存

  • 通過放置規則管理將不同資料庫下的資料排程到不同的硬體節點上,實現業務間資料的物理資源隔離,避免因資源爭搶,硬體故障等問題造成的相互干擾
  • 通過賬號許可權管理避免跨業務資料訪問,提升資料質量和資料安全

3.合併MySQL業務,降低運維壓力,提升管理效率

  • 使用少數 TiDB 叢集替換大量的 MySQL 例項,根據不同業務底層設定不同的物理儲存隔離需求,讓資料庫數量大大減少,原本的升級、備份、引數設定等日常運維工作將大幅縮減,在資源隔離和價效比上達到平衡,大幅減少 DBA 日常的運維管理成本

我們的 HTAP 叢集目前有一個數據歸檔需求,整個叢集共約 330TB,考慮到成本和訪問頻率、效能等各方面需求,要求至少儲存 3 個月共約 80TB 到 ssd,250TB 存到 hdd,現在基於我們的大資料冷熱分離歸檔業務場景,本文重點探討冷熱資料歸檔儲存的功能和特性,以方便下一步我們正式應用到生產環境。

概述

TiDB 叢集通過 PD 節點(Placement Driver 元件)在系統內基於熱點、儲存容量等策略自動完成 region 的排程,從而實現叢集資料均衡、分散儲存在各個節點的目標,這些排程操作是叢集的自身管理行為,對使用者而已幾乎是透明的,在之前的版本使用者無法精確控制資料的儲存方式和位置。

TiDB 6.0 正式提供了資料放置框架(Placement Rules in SQL )功能,使用者通過 SQL 配置資料在 TiKV 叢集中的放置位置,可以對資料進行直接的管理,以滿足不同的業務場景需要。使用者可以將庫、表和分割槽指定部署至不同的地域、機房、機櫃、主機。還支援針對任意資料提供副本數、角色型別等維度的靈活排程管理能力,這使得在多業務共享叢集、跨中心部署、冷熱資料歸檔儲存等場景下,TiDB 得以提供更靈活更強大的資料管理能力。

該功能可以實現以下業務場景:

  • 動態指定重要資料的副本數,提高業務可用性和資料可靠性
  • 將最新資料存入 SSD,歷史資料存入 HDD,降低歸檔資料儲存成本
  • 把熱點資料的 leader 放到高效能的 TiKV 例項上,提供高效訪問
  • 不同業務共用一個叢集,而底層按業務實現儲存物理隔離,互不干擾,極大提升業務穩定性
  • 合併大量不同業務的 MySQL 例項到統一叢集,底層實現儲存隔離,減少管理大量資料庫的成本

原理簡介

早期版本的 Placement rule 使用時需要通過 pd-ctl 工具設定和檢視,操作繁瑣且晦澀難懂。經過幾個版本的迭代和優化,推出的 PlacementRules in SQL 對使用者更加友好,到了 v6.0.0 總體來說還是很方便理解和使用的,避免了使用 pd-ctl 工具配置的複雜性,大大降低使用門檻。

放置策略的實現依賴於 TiKV 叢集 label 標籤配置,需提前做好規劃(設定 TiKV 的 labels)。可通過show placement labels檢視當前叢集所有可用的標籤。

```sql mysql> show placement labels ; +------+-----------------------------------------------------------------+ | Key | Values | +------+-----------------------------------------------------------------+ | disk | ["ssd"] | | host | ["tikv1", "tikv2", "tikv3"] | | rack | ["r1"] | | zone | ["guangzhou"] | +------+-----------------------------------------------------------------+ 4 rows in set (0.00 sec)

```

使用時有基礎用法和高階用法兩種方式。

(1) 基礎放置策略

基礎放置策略主要是控制 Raft leader 和 followers 的排程。

```sql #建立放置策略 CREATE PLACEMENT POLICY myplacementpolicy PRIMARY_REGION="guangzhou" REGIONS="guangzhou,shenzhen";

#將規則繫結至表或分割槽表,這樣指定了放置規則 CREATE TABLE t1 (a INT) PLACEMENT POLICY=myplacementpolicy; CREATE TABLE t2 (a INT); ALTER TABLE t2 PLACEMENT POLICY=myplacementpolicy;

#檢視放置規則的排程進度,所有繫結規則的物件都是非同步排程的。 SHOW PLACEMENT;

#檢視放置策略 SHOW CREATE PLACEMENT POLICY myplacementpolicy\G select * from information_schema.placement_policies\G

#修改放置策略,修改後會傳播到所有繫結此放置策略的物件 ALTER PLACEMENT POLICY myplacementpolicy FOLLOWERS=5;

#刪除沒有繫結任何物件的放置策略 DROP PLACEMENT POLICY myplacementpolicy;

```

(2) 高階放置策略

基礎放置策略主要是針對 Raft leader 、Raft followers 的排程策略,如果需要更加靈活的方式,如不區分 region 角色將資料指定儲存在 hdd,需要使用高階放置策略。使用高階放置策略主要有兩個步驟,首先建立策略,然後在庫、表或分割槽上應用策略。

```sql # 建立策略,指定資料只儲存在ssd CREATE PLACEMENT POLICY storeonfastssd CONSTRAINTS="[+disk=ssd]";

# 建立策略,指定資料只儲存在hdd CREATE PLACEMENT POLICY storeonhdd CONSTRAINTS="[+disk=hdd]";

# 在分割槽表應用高階放置策略,指定分割槽儲存在hdd或者ssd上,未指定的分割槽由系統自動排程 CREATE TABLE t1 (id INT, name VARCHAR(50), purchased DATE) PARTITION BY RANGE( YEAR(purchased) ) ( PARTITION p0 VALUES LESS THAN (2000) PLACEMENT POLICY=storeonhdd, PARTITION p1 VALUES LESS THAN (2005), PARTITION p2 VALUES LESS THAN (2010), PARTITION p3 VALUES LESS THAN (2015), PARTITION p4 VALUES LESS THAN MAXVALUE PLACEMENT POLICY=storeonfastssd );

```

高階放置策略具體內容,請看官網介紹http://docs.pingcap.com/zh/tidb/stable/placement-rules-in-sql#%E9%AB%98%E7%BA%A7%E6%94%BE%E7%BD%AE

環境

| 角色 | 機器數 | 記憶體 | 資料盤 | CPU | OS | | --------- | ------ | ---- | ------------------ | ------------------------- | ----------------------------------------------- | | TiDB&TiPD | 3 | 256G | 1TB hdd | 40 cpu (20 core2 thread) | Debian 4.19.208-1 (2021-09-29) x86_64 GNU/Linux | | TiKV | 3 | 256G | 800GB ssd,1TB hdd | 40 cpu (20 core2 thread) | Debian 4.19.208-1 (2021-09-29) x86_64 GNU/Linux |

冷熱歸檔儲存

  • 目標:對給定的表按日期分割槽,將最新分割槽的資料存入 SSD,歷史資料存入 HDD

功能驗證

1.部署叢集並建立放置策略

  • 部署 TiDB v6.0.0 叢集,具體參考部署叢集操作

  • 建立資料落盤策略,以備使用

```sql # 應用該策略的庫、表、分割槽,資料會儲存在ssd上 CREATE PLACEMENT POLICY storeonssd CONSTRAINTS="[+disk=ssd]" ;

# 應用該策略的庫、表、分割槽,資料會儲存在hdd上 CREATE PLACEMENT POLICY storeonhdd CONSTRAINTS="[+disk=hdd]";

#檢視叢集已有策略 mysql> show placement \G ***** 1. row **** Target: POLICY storeonhdd Placement: CONSTRAINTS="[+disk=hdd]" Scheduling_State: NULL *** 2. row ****** Target: POLICY storeonssd Placement: CONSTRAINTS="[+disk=ssd]" Scheduling_State: NULL 2 rows in set (0.02 sec)

```

2.建立庫表並應有放置策略

建立目標表為TiDB分割槽表並且按 Range 分割槽。

```sql # 建立資料庫tidb_ssd_hdd_test,並設定該庫預設落盤策略,設定後新建的表都會預設繼承該策略 create database tidb_ssd_hdd_test PLACEMENT POLICY=storeonssd;

# 檢視策略已經應用到指定庫上 mysql> show placement \G ***** 1. row **** Target: POLICY storeonhdd Placement: CONSTRAINTS="[+disk=hdd]" Scheduling_State: NULL *** 2. row *** Target: POLICY storeonssd Placement: CONSTRAINTS="[+disk=ssd]" Scheduling_State: NULL *** 3. row ****** Target: DATABASE tidb_ssd_hdd_test Placement: CONSTRAINTS="[+disk=ssd]" Scheduling_State: SCHEDULED 3 rows in set (0.02 sec)

# 建立分割槽表,可以看到表建立後預設繼承和庫一樣的落盤策略,關鍵標識為“/T![placement] PLACEMENT POLICY=storeonssd /” CREATE TABLE logoutrole_log ( doc_id varchar(255) NOT NULL, gameid varchar(255) DEFAULT NULL , -- some fields logdt timestamp DEFAULT '1970-01-01 08:00:00' , updatetime varchar(255) DEFAULT NULL , UNIQUE KEY doc_id (doc_id,logdt), -- some index KEY logdt_gameid (logdt,gameid) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /T![placement] PLACEMENT POLICY=storeonssd / PARTITION BY RANGE ( UNIX_TIMESTAMP(logdt) ) ( PARTITION p20220416 VALUES LESS THAN (UNIX_TIMESTAMP('2022-04-17 00:00:00')), PARTITION p20220417 VALUES LESS THAN (UNIX_TIMESTAMP('2022-04-18 00:00:00')), PARTITION p20220418 VALUES LESS THAN (UNIX_TIMESTAMP('2022-04-19 00:00:00')), PARTITION p20220419 VALUES LESS THAN (UNIX_TIMESTAMP('2022-04-20 00:00:00')), PARTITION p20220420 VALUES LESS THAN (UNIX_TIMESTAMP('2022-04-21 00:00:00')), PARTITION p20220421 VALUES LESS THAN (UNIX_TIMESTAMP('2022-04-22 00:00:00')), PARTITION p20220422 VALUES LESS THAN (UNIX_TIMESTAMP('2022-04-23 00:00:00')) );

```

3.寫入熱資料到 ssd 盤並擴容 hdd 儲存節點

  • 叢集只有 3 個 ssd 的 tikv 節點,啟動 flink 流往目標表匯入資料,可以看到這 3 個 ssd 節點的 region 數和空間使用在不斷增長

1650964998281.png

1650965222072.png

  • 在原有基礎上再擴容 3 個 hdd tikv 例項

1650965633758.png

4.冷熱分離

為了方便模擬資料的遷移,flink 匯入的資料是全部落在 2022-04-16 這一天:

```sql mysql> select date(logdt) as day,count(0) from logoutrole_log group by day order by day ;
+------------+----------+ | day | count(0) | +------------+----------+ | 2022-04-16 | 1109819 | +------------+----------+ 1 row in set (1.09 sec)

```

停止 Flink 寫入後,設定資料分離放置策略,將儲存在 ssd 上的 2022-04-16 這一天的資料,轉存到 hdd 上,模擬冷資料歸檔操作:

sql mysql> alter table tidb_ssd_hdd_test.logoutrole_log partition p20220416 placement policy storeonhdd; Query OK, 0 rows affected (0.52 sec)

在應用 hdd 轉存策略後,如下圖可以看到排程規則裡 2022-04-16 這一天的分割槽 Placement 由 ssd 變為了 hdd,即叢集已經知曉最新的排程策略是將這一天的分割槽資料排程到 hdd 去,Scheduling_State 處於 PENDING 狀態,表示 Follower 的 raft log 與 Leader 有較大差距,在這裡可以理解為是正在處於排程的過程。

1650341702179.png

隨著時間的推移,資料在不斷從 ssd 遷移到 hdd 上。從叢集 grafana 監控面板可以看到 ssd 節點上的 region 資料在不斷下降,直到降到接近於 0;相反,hdd 上的 region 數不斷上升,直到資料全部遷出 ssd 節點。110 萬行資料從 ssd 遷移到 hdd,大約耗時 3min 。

1650342094048.png

在資料全部遷如 hdd 節點後,檢視排程進度,此時 Scheduling_State 處於 SCHEDULED 完成排程狀態:

1650342133243.png

結論:

  • 證明冷熱資料隔離儲存策略已經生效,ssd 上的資料完成遷移到 hdd 上,且 ssd 的空間得以釋放,符合資料歸檔的目標。

靜態叢集冷熱儲存分離(無外部訪問)

ssd->hdd

繼續通過 flink 寫入資料到 2022-04-17 分割槽,然後停流使叢集沒有外部訪問流量,將此分割槽上 ssd 資料遷移到 hdd。

alter table tidb_ssd_hdd_test.logoutrole_log partition p20220417 placement policy storeonhdd;

1650970144694.png

ssd 上的 region 全部遷移到 hdd 上,ssd 空間被釋放,hdd 空間使用逐漸增加,遷移過程中 ssd 和 hdd 的 IO 消耗都在 5%左右,記憶體和網路頻寬使用不變、保持平穩。 約 6 千萬行 130GB 資料從 ssd 資料遷移到 hdd 大概需要 2 個小時

結論:

  • 在將大規模資料從 ssd 資料遷移到 hdd 過程,叢集資源消耗比較低,可以有效避免過多佔用叢集資源。
  • 在叢集沒有外部訪問壓力時,在預設配置下,叢集以每小時約 3000 萬行的速度從 ssd 遷移到 hdd 節點。

hdd->ssd

在沒有外部流量訪問時,將資料從 hdd 遷移回 ssd,從監控圖可以看到,hdd 節點的 tikv 的 leader 數、region 數在此期間都在下降,分別從 850、2500 逐漸下降直到為 0,磁碟空間也從 62GB 下降為 0,表示資料在持續遷移出 hdd 節點;

1652425488812.png

1652425944226.png

相反地,由於資料不斷遷入到 ssd 中,ssd 節點的 tikv 的 leader 數、region 數在此期間都在上升,分別從 1500、4200 逐漸上升到 2200、6700,直到資料遷入完成,然後保持數量不變,ssd 的磁碟空間消耗也從 100GB 上升到 161GB。

遷移的過程中,ssd 和 hdd 節點的 IO 使用率都比較低,如下圖:

1652426155311.png

結論:

  • 將冷資料從 hdd 遷移至 ssd,遷移 1.7 億行共約 200GB 資料,大約耗時 2 小時 40 分鐘,平均每小時遷移 6300 萬行,速度約為將熱資料從 ssd 遷到 hdd 的 2 倍(每小時約 3000 萬行)
  • 將資料從 hdd 遷移至 ssd 的過程,不管是對 ssd 還是 hdd,其平均 IO 使用率都不高,不會佔用過多叢集的資源,可以認為資料遷移過程對叢集正在執行的業務影響不大

熱叢集冷熱儲存分離(外部持續訪問)

繼續持續寫入資料到 2022-04-18 和 2022-04-19 的 ssd 分割槽,然後不停流保持持續的寫入壓力,遷移 2022-04-18 資料從 ssd 到 hdd,觀察叢集表現。

```sql

應用放置策略將2022-04-18資料從ssd歸檔到hdd

alter table tidb_ssd_hdd_test.logoutrole_log partition p20220418 placement policy storeonhdd; ```

在歸檔過程,flink 同時持續以 2100 的 QPS 寫入熱資料,期間 ssd IO 接近 100%,hdd 的 IO 消耗在 10%以下,各節點 CPU 在 500%以下,網路頻寬在 200MB/s 以下,記憶體使用保持平穩。

從 region 數變化的角度來看:

  • 在歸檔資料時,ssd 的 tikv region 數從 6300 下降到 3500 左右,當遷移完成後是淨寫入資料,此時 ssd 節點的 region 數量又持續上升;
  • hdd 節點的 region 數從開始的 2600 上升到 6500 左右,隨著資料遷移完成,hdd 的 region 數不再增加,一直保持 6500 不變。

1650971789523.png

從磁碟使用空間變化的角度來看:

  • 歸檔資料時,ssd 節點的磁碟使用空間從 152GB 下降到 88GB,當遷移完成後,此時是淨寫入資料,ssd 空間開始上升;
  • 資料在不斷寫入到 hdd 節點,所以其使用空間從 61GB 上升到 154GB,隨著資料遷移完成,一直保持不變

1650593578630.png

1650593565818.png

1650593789799.png

結論:

  • 在有外部幾乎是滿 IO 的寫入壓力時,歸檔約 2 億行、400GB 資料從 ssd 到 hdd 節點,大概需要 6 個小時,即約 3300 萬行/小時,可以說冷資料的歸檔效率還是比較高的
  • 集群后臺在進行資料歸檔時,flink 的 sink QPS 變化不大,可以認為歸檔的過程對叢集正常寫入影響不大

歸檔資料補寫

業務上有補全歷史資料的場景,比如資料重算等,這裡模擬補全歷史冷資料,寫入到 hdd。

  • 2022-04-16 這一天的資料已經全部轉存到 hdd 冷盤中。啟動 flink 流,繼續對 2022-04-16 分割槽寫入資料,這些只會寫 hdd,不會寫入 ssd。flink 流以 2000 左右的 sink QPS 補全冷資料,hdd tikv 節點 IO 打滿,SSD 的 IO 使用率比較低。

1650969265594.png

從下圖可以看到,在補全冷資料的時候, hdd 節點的 region 數在不斷上升,hdd tikv 的空間消耗也在不斷增加,而 ssd 的空間使用和 region 數均保持不變,說明資料並不會寫入 ssd 中,符合預期。

1650969430703.png

結論:

  • 說明 TiDB 冷熱資料分離儲存功能,在補全歷史冷資料的場景,即歸檔資料補寫,資料可以正確地直接寫入到 hdd,期間資料不會經過 ssd
  • 補全冷資料,hdd tikv 節點 IO 打滿,ssd 的 IO 使用率比較低,也說明資料不會經過 ssd

同一叢集業務隔離

除了冷熱資料歸檔外,我們線上不同的業務線通常採用一套或多套 MySQL 來管理,但因為業務多導致 MySQL 有數百個,日常的監控、診斷、版本升級、安全防護等工作對運維團隊造成了巨大的壓力,且隨著業務規模越來越大,管理的成本不斷上升。

使用 Placement rule 功能可以很容易靈活的叢集共享規則。可以將不同 MySQL 上的業務遷移到同一個 TiDB 叢集,實現多個不同業務的共用一個叢集而底層提供物理儲存隔離,有效減少大量 MySQL 的管理成本。這個也是我們接下來會繼續推進優化的地方。

舉例說明,業務 A和B 共享資源,降低儲存和管理成本,而業務 C 和 D 獨佔資源,提供最高的隔離性。由於多個業務共享一套 TiDB 叢集,升級、打補丁、備份計劃、擴縮容等日常運維管理頻率可以大幅縮減,降低管理負擔提升效率

1651723818212.png

```sql CREATE PLACEMENT POLICY 'shared_nodes' CONSTRAINTS = "[+region=shared_nodes]"; CREATE PLACEMENT POLICY 'business_c' CONSTRAINTS = "[+region=business_c]"; CREATE PLACEMENT POLICY 'business_d' CONSTRAINTS = "[+region=business_d]";

ALTER DATABASE a POLICY=shared_nodes; ALTER DATABASE b POLICY=shared_nodes; ALTER DATABASE c POLICY=business_c; ALTER DATABASE d POLICY=business_d; ```

基於 SQL 介面的資料放置規則,你僅僅使用少數 TiDB 叢集管理大量的 MySQL 例項,不同業務的資料放置到不同的 DB,並通過放置規則管理將不同 DB 下的資料排程到不同的硬體節點上,實現業務間資料的物理資源隔離,避免因資源爭搶,硬體故障等問題造成的相互干擾。通過賬號許可權管理避免跨業務資料訪問,提升資料質量和資料安全。在這種部署方式下,叢集數量大大減小,原本的升級,監控告警設定等日常運維工作將大幅縮減,在資源隔離和價效比上達到平衡,大幅減少日常的 DBA 運維管理成本

總結

1.冷熱分離儲存,降低儲存成本

  • TiDB 6.0 正式支援資料冷熱儲存分離,可以降低 SSD 使用成本。使用 TiDB 6.0 的資料放置功能,可以在同一個叢集實現海量資料的冷熱儲存,將新的熱資料存入 SSD,歷史冷資料存入 HDD,降低歷史歸檔資料儲存成本。
  • 將熱資料從 ssd 遷移到 hdd,每小時可歸檔約 3000 萬行,總體來看效率還是比較高的
  • 分離儲存過程,ssd 和 hdd 用於歸檔的 IO 消耗都在 10%以內,叢集訪問 QPS 表現平穩,對業務訪問的影響較小
  • 在補寫冷資料到 hdd 場景,資料可正確地直接寫入 hdd,不會經過 ssd。flink 補寫冷資料時滿 IO 每秒寫入約 4000 行,每小時寫入約 1500 萬行。

2.業務底層物理隔離,實現同一叢集不同儲存

  • 通過放置規則管理將不同資料庫下的資料排程到不同的硬體節點上,實現業務間資料的物理資源隔離,避免因資源爭搶,硬體故障等問題造成的相互干擾
  • 通過賬號許可權管理避免跨業務資料訪問,提升資料質量和資料安全

3.合併MySQL業務,降低運維壓力,提升管理效率

  • 使用少數 TiDB 叢集替換大量的 MySQL 例項,根據不同業務底層設定不同的物理儲存隔離需求,讓資料庫數量大大減少,原本的升級、備份、引數設定等日常運維工作將大幅縮減,在資源隔離和價效比上達到平衡,大幅減少 DBA 日常的運維管理成本

4.放置策略應用操作步驟

  • 對已有叢集應用 Placement Rules
  • 將叢集升級到 6.0.0 版本
  • 建立預設 SSD 策略
  • 開啟放置策略預設開關,使得叢集已有庫表都預設儲存在 ssd 上 (該功能依賴官方釋出新版本支援)
  • 目前只能用指令碼 alter 全部庫設定這個預設策略,如果有新增的庫也需要提前進行設定
  • 申請新機器並擴容新的 hdd tikv
  • 建立 hdd 放置策略
  • 在目標表的目標分割槽上指定 ssd 或 hdd 策略
  • 定期將過期分割槽宣告 hhd 放置策略

  • 對新建的叢集應用 Placement Rules

  • 部署 6.0.0 叢集版本
  • 建立預設 SSD 策略
  • 建立的全部庫都先設定這個預設策略
  • 申請新機器並擴容新的 hdd tikv
  • 建立 hdd 放置策略
  • 在目標表或目標分割槽上指定 ssd 或 hdd 策略
  • 定期將過期分割槽宣告 hhd 放置策略