隨着金融行業的不斷髮展,多個業務系統的整合成為了趨勢,分佈式數據庫的應用也愈發廣泛。為了應對多業務融合帶來的複雜性,金融機構需要在保障各業務系統高效運行的同時,確保 IT 系統的高可用性和穩定性。本文將介紹 TiDB 如何通過多租户資源管控與容災技術,助力金融機構在分佈式環境中實現高效的業務整合與容災能力,並探討 TiCDC 工具在跨區域數據同步中的應用。
金融機構越來越多的選擇將多套業務系統融合到一套分佈式數據庫集羣來支撐,一方面可以節約硬件成本,另一方面可以簡化運維複雜性。多租户能力及資源管控技術是數據庫中實現多業務融合的最常用及有效手段。容災是金融機構 IT 系統滿足高可用性必需的一個能力,金融機構的容災能力根據高可用程度劃分為多個等級,較常用的一種容災部署方式是採用主備庫的方案,在分佈式數據庫中也稱為主備集羣方案。金融機構每年都有容災切換演練的場景,根據系統重要等級不同,切換演練的頻次也有所不同。對於 A 類業務系統,一般是每年覆蓋一次;對於 B 類或 C 類系統,則可能是 2 年或更長時間循環覆蓋一次。在多業務融合的場景中,為了縮小切換演練的範圍,避免切換演練對所有業務產生影響,金融企業期望底層數據庫產品能支持單個租户 (應用) 的容災切換能力。
資源管控 TiDB 資源管控提供了兩層資源管理能力,包括在 TiDB 層的流控能力和 TiKV 層的優先級調度的能力。通過流控和調度這兩層控制,可以實現應用的資源隔離,滿足服務質量 (QoS) 要求。當把數據庫當成一個資源池來使用時,數據庫通常會被劃分為 N 個資源單元。TiDB 中的資源單元 Request Unit (RU) 是對 CPU、IO 等系統資源的統一抽象的計量單位,用於表示對數據庫的單個請求消耗的資源量。以下表格為 TiDB 資源管控對比其它資源管控或多租户方案:
TiCDCTiCDC 是一款 TiDB 增量數據同步工具,通過拉取上游 TiKV 的數據變更日誌,TiCDC 可以將數據解析為有序的行級變更數據輸出到下游。通過 TiCDC 可以實現多 TiDB 集羣跨區域數據高可用和容災方案,保證在災難發生時保證主備集羣數據的最終一致性。
TiDB 支持基於 RU (Request Unit,資源單元) 的資源管控能力,方便解決多業務融合共享集羣資源的場景。TiDB 也支持基於 TiCDC 的實時同步,可以實現 TiDB 集羣間的容災方案。基於 TiDB 的資源管控及 TiCDC 實時同步工具,理論上可以實現一套多業務融合的容災方案,滿足單個租户 (應用) 容災切換而不影響其他租户的要求。以下通過實際測試步驟來驗證方案的可行性。1. 準備集羣環境。搭建 2 套相同節點數的 TiDB 測試環境,命名為 tidb-A 和 tidb-B,並分別安裝部署 TiCDC 組件。[tidb@host-xx-xx-x-151 packages]$ tiup cluster display tidb-Atiup is checking updates for component cluster ...Starting component cluster: /home/tidb/.tiup/components/cluster/v1.14.1/tiup-cluster display tidb-ACluster type: tidbCluster name: tidb-ACluster version: v7.5.1Deploy user: tidbSSH type: builtinDashboard URL: http://xx.xx.x.152:2379/dashboardGrafana URL: http://xx.xx.x.151:3000ID Role Host Ports OS/Arch Status Data Dir Deploy Dir-- ---- ---- ----- ------- ------ -------- ----------xx.xx.x.151:9093 alertmanager xx.xx.x.151 9093/9094 linux/aarch64 Up /data1/tidb-data/alertmanager-9093 /data1/tidb-deploy/alertmanager-9093xx.xx.x.151:8300 cdc xx.xx.x.151 8300 linux/aarch64 Up /data1/cdc-free /data1/tidb-deploy/cdc-8300xx.xx.x.152:8300 cdc xx.xx.x.152 8300 linux/aarch64 Up /data1/cdc-free /data1/tidb-deploy/cdc-8300xx.xx.x.151:3000 grafana xx.xx.x.151 3000 linux/aarch64 Up - /data1/tidb-deploy/grafana-3000xx.xx.x.151:2379 pd xx.xx.x.151 2379/2380 linux/aarch64 Up /data1/tidb-data/pd-2379 /data1/tidb-deploy/pd-2379xx.xx.x.152:2379 pd xx.xx.x.152 2379/2380 linux/aarch64 Up|UI /data1/tidb-data/pd-2379 /data1/tidb-deploy/pd-2379xx.xx.x.153:2379 pd xx.xx.x.153 2379/2380 linux/aarch64 Up|L /data1/tidb-data/pd-2379 /data1/tidb-deploy/pd-2379xx.xx.x.151:9095 prometheus xx.xx.x.151 9095/12020 linux/aarch64 Up /data1/tidb-data/prometheus-9095 /data1/tidb-deploy/prometheus-9095xx.xx.x.151:4000 tidb xx.xx.x.151 4000/10080 linux/aarch64 Up - /data1/tidb-deploy/tidb-4000xx.xx.x.152:4000 tidb xx.xx.x.152 4000/10080 linux/aarch64 Up - /data1/tidb-deploy/tidb-4000xx.xx.x.153:4000 tidb xx.xx.x.153 4000/10080 linux/aarch64 Up - /data1/tidb-deploy/tidb-4000xx.xx.x.151:20160 tikv xx.xx.x.151 20160/20180 linux/aarch64 Up /data1/tidb-data/tikv-20160 /data1/tidb-deploy/tikv-20160xx.xx.x.152:20160 tikv xx.xx.x.152 20160/20180 linux/aarch64 Up /data1/tidb-data/tikv-20160 /data1/tidb-deploy/tikv-20160xx.xx.x.153:20160 tikv xx.xx.x.153 20160/20180 linux/aarch64 Up /data1/tidb-data/tikv-20160 /data1/tidb-deploy/tikv-20160Total nodes: 14[tidb@host-xx-xx-x-151 packages]$ tiup cluster display tidb-Btiup is checking updates for component cluster ...Starting component cluster: /home/tidb/.tiup/components/cluster/v1.14.1/tiup-cluster display tidb-BCluster type: tidbCluster name: tidb-BCluster version: v7.5.1Deploy user: tidbSSH type: builtinDashboard URL: http://xx.xx.x.151:12399/dashboardGrafana URL: http://xx.xx.x.151:13009ID Role Host Ports OS/Arch Status Data Dir Deploy Dir-- ---- ---- ----- ------- ------ -------- ----------xx.xx.x.151:19089 alertmanager xx.xx.x.151 19089/19084 linux/aarch64 Up /data1/tidb-re-data/alertmanager-19089 /data1/tidb-re-deploy/alertmanager-19089xx.xx.x.151:8400 cdc xx.xx.x.151 8400 linux/aarch64 Up /data1/cdc-recover /data1/tidb-re-deploy/cdc-8400xx.xx.x.152:8400 cdc xx.xx.x.152 8400 linux/aarch64 Up /data1/cdc-recover /data1/tidb-re-deploy/cdc-8400xx.xx.x.151:13009 grafana xx.xx.x.151 13009 linux/aarch64 Up - /data1/tidb-re-deploy/grafana-13009xx.xx.x.151:12399 pd xx.xx.x.151 12399/12390 linux/aarch64 Up|UI /data1/tidb-re-data/pd-12399 /data1/tidb-re-deploy/pd-12399xx.xx.x.152:12399 pd xx.xx.x.152 12399/12390 linux/aarch64 Up|L /data1/tidb-re-data/pd-12399 /data1/tidb-re-deploy/pd-12399xx.xx.x.153:12399 pd xx.xx.x.153 12399/12390 linux/aarch64 Up /data1/tidb-re-data/pd-12399 /data1/tidb-re-deploy/pd-12399xx.xx.x.151:19099 prometheus xx.xx.x.151 19099/22029 linux/aarch64 Up /data1/tidb-re-data/prometheus-19099 /data1/tidb-re-deploy/prometheus-19099xx.xx.x.151:24000 tidb xx.xx.x.151 24000/20090 linux/aarch64 Up - /data1/tidb-re-deploy/tidb-24000xx.xx.x.152:24000 tidb xx.xx.x.152 24000/20090 linux/aarch64 Up - /data1/tidb-re-deploy/tidb-24000xx.xx.x.153:24000 tidb xx.xx.x.153 24000/20090 linux/aarch64 Up - /data1/tidb-re-deploy/tidb-24000xx.xx.x.151:30169 tikv xx.xx.x.151 30169/30190 linux/aarch64 Up /data1/tidb-re-data/tikv-30169 /data1/tidb-re-deploy/tikv-30169xx.xx.x.152:30169 tikv xx.xx.x.152 30169/30190 linux/aarch64 Up /data1/tidb-re-data/tikv-30169 /data1/tidb-re-deploy/tikv-30169xx.xx.x.153:30169 tikv xx.xx.x.153 30169/30190 linux/aarch64 Up /data1/tidb-re-data/tikv-30169 /data1/tidb-re-deploy/tikv-30169Total nodes: 142. 創建用户並綁定資源組。分別在兩套集羣中創建 3 個用户 (userA、userB、userC) 及 3 個資源組 (rgA 1000RU、rgB 2000RU、rgC 3000RU),用户和資源組一一綁定。分別使用不同用户在數據庫中創建各自的 database(sbtest_a、sbtest_b、sbtest_c),它們代表不同業務系統的後台數據庫。
mysql> create user userA;Query OK, 0 rows affected (0.06 sec)mysql> create user userB;Query OK, 0 rows affected (0.05 sec)mysql> create user userC;Query OK, 0 rows affected (0.03 sec)mysql> create resource group rgA RU_PER_SEC=1000;Query OK, 0 rows affected (0.54 sec)mysql> create resource group rgB RU_PER_SEC=2000;Query OK, 0 rows affected (0.55 sec)mysql> create resource group rgC RU_PER_SEC=3000;Query OK, 0 rows affected (0.54 sec)mysql> alter user userA resource group rgA;Query OK, 0 rows affected (0.04 sec)mysql> alter user userB resource group rgB;Query OK, 0 rows affected (0.04 sec)mysql> alter user userC resource group rgC;Query OK, 0 rows affected (0.04 sec)mysql> select user, user_attributes from mysql.user;+-------+---------------------------+| user | user_attributes |+-------+---------------------------+| root | NULL || userA | {"resource_group": "rga"} || userB | {"resource_group": "rgb"} || userC | {"resource_group": "rgc"} |+-------+---------------------------+4 rows in set (0.01 sec)mysql> alter user userA identified by 'userA123';Query OK, 0 rows affected (0.05 sec)mysql> alter user userB identified by 'userB123';Query OK, 0 rows affected (0.04 sec)mysql> alter user userC identified by 'userC123';Query OK, 0 rows affected (0.04 sec)mysql> create database sbtest_a;Query OK, 0 rows affected (0.54 sec)mysql> grant all on sbtest_a. to userA;Query OK, 0 rows affected (0.06 sec)mysql> create database sbtest_b;Query OK, 0 rows affected (0.54 sec)mysql> grant all on sbtest_b. to userB;Query OK, 0 rows affected (0.03 sec)mysql> create database sbtest_c;Query OK, 0 rows affected (0.54 sec)mysql> grant all on sbtest_c.* to userC;Query OK, 0 rows affected (0.04 sec)從 Dashboard->資源管控頁面中,可以看到剛剛創建的資源分組及對應的 RU 設置。
- 創建同步鏈路。創建 3 條 TiCDC 同步鏈路 (changefeed),分別為 sbtest_a (集羣 A) -> sbtest_a (集羣 B) 、sbtest_b (集羣 A) -> sbtest_b (集羣 B) 、sbtest_c (集羣 A) -> sbtest_c (集羣 B) 。
-- changefeed 配置文件[tidb@host-xx-xx-x-151 packages]$ cat changfeed_sbtest_a.toml[filter]rules = ['sbtest_a.*'][tidb@host-xx-xx-x-151 packages]$ cat changfeed_sbtest_b.toml[filter]rules = 'sbtest_b.*'$ cat changfeed_sbtest_c.toml[filter]rules = ['sbtest_c.*']-- 創建 changefeed 同步鏈路tiup cdc cli changefeed create --server=http://xx.xx.x.151:8300 --sink-uri="mysql://userA:userA123@xx.xx.x.151:24000/" --changefeed-id="sbtest-a-atob" --config=changfeed_sbtest_a.tomltiup cdc cli changefeed create --server=http://xx.xx.x.151:8300 --sink-uri="mysql://userB:userB123@xx.xx.x.151:24000/" --changefeed-id="sbtest-b-atob" --config=changfeed_sbtest_b.tomltiup cdc cli changefeed create --server=http://xx.xx.x.151:8300 --sink-uri="mysql://userC:userC123@xx.xx.x.151:24000/" --changefeed-id="sbtest-c-atob" --config=changfeed_sbtest_c.toml-- 查看創建的 changefeed 同步鏈路[tidb@host-xx-xx-x-151 packages]$ tiup cdc cli changefeed list --server=http://xx.xx.x.151:8300tiup is checking updates for component cdc ...Starting componentcdc: /home/tidb/.tiup/components/cdc/v7.5.1/cdc cli changefeed list --server=http://xx.xx.x.151:8300[ { "id": "sbtest-a-atob", "namespace": "default", "summary": { "state": "normal", "tso": 451948847132835850, "checkpoint": "2024-08-19 14:13:51.360", "error": null } }, { "id": "sbtest-b-atob", "namespace": "default", "summary": { "state": "normal", "tso": 451948847132835850, "checkpoint": "2024-08-19 14:13:51.360", "error": null } }, { "id": "sbtest-c-atob", "namespace": "default", "summary": { "state": "normal", "tso": 451948847132835850, "checkpoint": "2024-08-19 14:13:51.360", "error": null } }]4. 模擬業務運行。運行 3 套 sysbench 測試(oltp_read_write),用於模擬不同的業務場景。第 1 套 sysbench 測試使用 userA 用户連接到集羣 A 的 sbtest_a,第 2 套 sysbench 測試使用 userB 用户連接到集羣 A 的 sbtest_b,第 3 套 sysbench 測試使用 userC 用户連接到集羣 A 的 sbtest_c。sh run_sysbench_a.sh autosh run_sysbench_b.sh autosh run_sysbench_c.sh auto查看各資源組 RU 使用情況,可以看到都按照之前設置的 1000 RU、2000 RU、3000 RU 使用到最大上限,且未出現超用的情況。
- 驗證數據一致性。停止 sysbench 模擬測試,使用 sync-diff-inspector 檢驗兩邊集羣數據是否一致。注意,針對 TiDB 主備集羣對比,sync-diff-inspector 支持在不停止同步的情況下對上下游進行一致性驗證,具體可參考官網文檔 主從集羣一致性讀和數據校驗(https://docs.pingcap.com/zh/tidb/stable/ticdc-upstream-downst...)。數據對比配置:[tidb@host-xx-xx-x-151 packages]$ cat sync-diff.toml# Diff Configuration.######################### Global config ########################## 檢查數據的線程數量,上下游數據庫的連接數會略大於該值check-thread-count = 4# 如果開啓,若表存在不一致,則輸出用於修復的 SQL 語句。export-fix-sql = true# 只對比表結構而不對比數據check-struct-only = false# 如果開啓,會跳過校驗上游或下游不存在的表。skip-non-existing-table = false######################### Datasource config #########################[data-sources][data-sources.tidba] # mysql1 是該數據庫實例唯一標識的自定義 id,用於下面 task.source-instances/task.target-instance 中 host = "xx.xx.x.151" port = 4000 user = "userA" password = "userA123" # 設置連接上游數據庫的密碼,可為明文或 Base64 編碼。 #(可選)使用映射規則來匹配上游多個分表,其中 rule1 和 rule2 在下面 Routes 配置欄中定義 route-rules = ["rule1"][data-sources.tidbb] host = "xx.xx.x.151" port = 24000 user = "userA" password = "userA123" # 設置連接下游數據庫的密碼,可為明文或 Base64 編碼。 #(可選)使用 TLS 連接 TiDB # security.ca-path = ".../ca.crt" # security.cert-path = ".../cert.crt" # security.key-path = ".../key.crt" #(可選)使用 TiDB 的 snapshot 功能,如果開啓的話會使用歷史數據進行對比 # snapshot = "386902609362944000" # 當 snapshot 設置為 "auto" 時,使用 TiCDC 在上下游的同步時間點,具體參考 <https://github.com/pingcap/tidb-tools/issues/663> # snapshot = "auto"########################### Routes ############################ 如果需要對比大量的不同庫名或者表名的表的數據,或者用於校驗上游多個分表與下游總表的數據,可以通過 table-rule 來設置映射關係# 可以只配置 schema 或者 table 的映射關係,也可以都配置[routes][routes.rule1] # rule1 是該配置的唯一標識的自定義 id,用於上面 data-sources.route-rules 中schema-pattern = "sbtest_a" # 匹配數據源的庫名,支持通配符 "*" 和 "?"target-schema = "sbtest_a" # 目標庫名######################### Task config ########################## 配置需要對比的*目標數據庫*中的表[task] # output-dir 會保存如下信息 # 1 sql:檢查出錯誤後生成的修復 SQL 文件,並且一個 chunk 對應一個文件 # 2 log:sync-diff.log 保存日誌信息 # 3 summary:summary.txt 保存總結 # 4 checkpoint:a dir 保存斷點續傳信息 output-dir = "./output2" # 上游數據庫,內容是 data-sources 聲明的唯一標識 id source-instances = ["tidba"] # 下游數據庫,內容是 data-sources 聲明的唯一標識 id target-instance = "tidbb" # 需要比對的下游數據庫的表,每個表需要包含數據庫名和表名,兩者由
.隔開 # 使用 ? 來匹配任意一個字符;使用 * 來匹配任意;詳細匹配規則參考 golang regexp pkg: https://github.com/google/re2/wiki/Syntax target-check-tables = ["sbtest_a.*"]對比結果顯示,3 個 schema 的主從集羣結果完全一致:[tidb@host-xx-xx-x-151 packages]$ ./tidb-community-toolkit-v7.5.1-linux-arm64/sync_diff_inspector --config=sync-diff-a.tomlA total of 5 tables need to be comparedComparing the table structure ofsbtest_a`.`sbtest1... equivalentComparing the table structure ofsbtest_a`.`sbtest2... equivalentComparing the table structure ofsbtest_a`.`sbtest4... equivalentComparing the table structure ofsbtest_a`.`sbtest3... equivalentComparing the table structure ofsbtest_a`.`sbtest5... equivalentComparing the table data ofsbtest_a`.`sbtest1... equivalentComparing the table data ofsbtest_a`.`sbtest3... equivalentComparing the table data ofsbtest_a`.`sbtest2... equivalentComparing the table data ofsbtest_a`.`sbtest4... equivalentComparing the table data ofsbtest_a`.`sbtest5... equivalent_____________________________________________________________________________Progress [============================================================>] 100% 0/0A total of 5 table have been compared and all are equal.You can view the comparision details through './output3/sync_diff.log'[tidb@host-xx-xx-x-151 packages]$ ./tidb-community-toolkit-v7.5.1-linux-arm64/sync_diff_inspector --config=sync-diff-b.tomlA total of 5 tables need to be comparedComparing the table structure ofsbtest_b`.`sbtest3... equivalentComparing the table structure ofsbtest_b`.`sbtest5... equivalentComparing the table structure ofsbtest_b`.`sbtest2... equivalentComparing the table structure ofsbtest_b`.`sbtest4... equivalentComparing the table structure ofsbtest_b`.`sbtest1... equivalentComparing the table data ofsbtest_b`.`sbtest3... equivalentComparing the table data ofsbtest_b`.`sbtest4... equivalentComparing the table data ofsbtest_b`.`sbtest5... equivalentComparing the table data ofsbtest_b`.`sbtest2... equivalentComparing the table data ofsbtest_b`.`sbtest1... equivalent_____________________________________________________________________________Progress [============================================================>] 100% 0/0A total of 5 table have been compared and all are equal.You can view the comparision details through './output4/sync_diff.log'[tidb@host-xx-xx-x-151 packages]$ ./tidb-community-toolkit-v7.5.1-linux-arm64/sync_diff_inspector --config=sync-diff-c.tomlA total of 5 tables need to be comparedComparing the table structure ofsbtest_c`.`sbtest1... equivalentComparing the table structure ofsbtest_c`.`sbtest4... equivalentComparing the table structure ofsbtest_c`.`sbtest5... equivalentComparing the table structure ofsbtest_c`.`sbtest3... equivalentComparing the table structure ofsbtest_c`.`sbtest2... equivalentComparing the table data ofsbtest_c`.`sbtest4... equivalentComparing the table data ofsbtest_c`.`sbtest1... equivalentComparing the table data ofsbtest_c`.`sbtest5... equivalentComparing the table data ofsbtest_c`.`sbtest3... equivalentComparing the table data ofsbtest_c`.`sbtest2... equivalent_____________________________________________________________________________Progress [============================================================>] 100% 0/0A total of 5 table have been compared and all are equal.You can view the comparision details through './output5/sync_diff.log'6. 切換單個同步鏈路。模擬切換單個同步鏈路,選擇 sbtest_c (集羣 A) -> sbtest_c (集羣 B)。首先需要停止 sbtest_c 上的業務並移除(或暫停)當前同步鏈路,其次重新構建反向同步鏈路 sbtest_c (集羣 B) -> sbtest_c (集羣 A),最後將模擬業務連接切換到集羣 B 上。刪除正向同步鏈路:tiup cdc cli changefeed remove --server=http://xx.xx.x.151:8300 --changefeed-id="sbtest-c-atob"tiup cdc cli changefeed list --server=http://xx.xx.x.151:8300
此時觀察到業務 C 對應的資源組的 RU 消耗為 0,而另外兩個資源組仍然在穩定運行當中。
搭建反向同步鏈路:tiup cdc cli changefeed create --server=http://xx.xx.x.151:8400 --sink-uri="mysql://userC:userC123@xx.xx.x.151:4000/" --changefeed-id="sbtest-c-atob" --config=changfeed_sbtest_c.tomltiup cdc cli changefeed list --server=http://xx.xx.x.151:8400
此時再查看各資源組 RU 使用情況,此時業務 C 的主要壓力來自於 TiCDC 同步過來的壓力。由於 TiCDC 只同步寫操作,因此 RU 消耗數量比上游實際負載要低,從圖中顯示平均使用 RU 數約為 500。
- 驗證數據一致性。重新啓動 sbtest_c 上的業務並寫入集羣 B,運行一段時間後停止並驗證切換後的 sbtest_c 兩邊數據是否一致,同時也驗證原來的同步鏈路 sbtest_a 和 sbtest_b 數據是否仍然保持一致性同步。經驗證後,數據完全一致,證明此方案實施可行。//運行模擬業務c,並寫入集羣 Bsh run_sysbench_c_revers.sh auto[tidb@host-xx-xx-x-151 packages]$ ./tidb-community-toolkit-v7.5.1-linux-arm64/sync_diff_inspector --config=sync-diff-c.tomlA total of 5 tables need to be comparedComparing the table structure of
sbtest_c`.`sbtest3... equivalentComparing the table structure ofsbtest_c`.`sbtest1... equivalentComparing the table structure ofsbtest_c`.`sbtest5... equivalentComparing the table structure ofsbtest_c`.`sbtest4... equivalentComparing the table structure ofsbtest_c`.`sbtest2... equivalentComparing the table data ofsbtest_c`.`sbtest5... equivalentComparing the table data ofsbtest_c`.`sbtest4... equivalentComparing the table data ofsbtest_c`.`sbtest1... equivalentComparing the table data ofsbtest_c`.`sbtest3... equivalentComparing the table data ofsbtest_c`.`sbtest2... equivalent_____________________________________________________________________________Progress [============================================================>] 100% 0/0A total of 5 table have been compared and all are equal.You can view the comparision details through './output5/sync_diff.log'
本文通過模擬環境測試驗證,基於 TiDB 的資源管控能力可以實現多業務融合方案,通過給不同的業務系統分配不同的資源組,實現多套業務共享一套集羣資源並且相互之間資源隔離的效果。基於 TiCDC 同步工具可以實現 TiDB 主備集羣容災,通過給不同的業務創建不同的同步鏈路,多個業務之間的主備同步流程互不干擾。結合資源管控及 TiCDC,我們可以實現一套多業務融合的容災解決方案,能夠滿足企業客户尤其是金融機構同時具有多業務融合、容災能力以及支持單體應用容災切換演練等方面的需求。