当前位置:网站首页>TiDB 6.0:讓 TSO 更高效丨TiDB Book Rush

TiDB 6.0:讓 TSO 更高效丨TiDB Book Rush

2022-06-30 03:18:00 TiDB

本文作者:h5n1,TiDB愛好者,目前就職於聯通軟件研究院,asktug 主頁

1. 前言

TiDB 作為一個分布式數據庫,計算節點 tidb server 和存儲節點 tikv/tiflash server 有著近乎線性的擴展能力,當資源不足時直接在線擴容即可。但作為整個集群大腦的 PD 節點因為只有 leader 提供服務,不能向其他組件一樣通過擴展節點而提高處理能力。

目前 TSO 分配的主要問題:

  1. TSO 分配由 PD Leader 節點提供,大量請求下會導致 Leader 節點 CPU 利用率增高,影響事務延遲。

  2. PD Follower 節點基本處於空閑狀態,系統資源利用率較低。

  3. TiDB 跨數據中心訪問 PD Leader 時,數據中心間的延遲導致事務延遲增加。

為提昇 TSO 的處理性能針對部分場景 TiDB 引入了 TSO Follower Proxy、RC Read TSO 優化、Local TSO 等特性,通過擴展 PD 處理能力和减少 TSO 請求的方式,提昇整體吞吐量,降低事務延遲。

2. TSO

TSO 是一個單調遞增的時間戳,由 PD leader 分配。TiDB 在事務開始時會獲取 TSO 作為 start_ts、提交時獲取 TSO 作為 commit_ts,依靠 TSO 實現事務的 MVCC。TSO 為 64 比特的整型數值,由物理部分和邏輯部分組成,高 48 比特為物理部分是 unixtime 的毫秒時間,低 18 比特為邏輯部分是一個數值計數器,理論上每秒可產生 262144000(即 2 ^ 18 * 1000)個 TSO。

為保證性能 PD 並不會每次為一個請求生成一個 TSO,而是會預先申請一個可分配的時間窗口,時間窗口是當前時間和當前時間+3 秒後的 TSO,並保存在 etcd 內,之後便可以從窗口中分配 TSO。每隔一定時間就會觸發更新時間窗口。當 PD 重啟或 leader 切換後會從 etcd 內獲取保存的最大 TSO 開始分配,以保證 TSO 的連續遞增。

3. Follower Proxy

默認情况下 TSO 請求由 PD leader 處理,TiDB 內部通過 PD Client 向 PD leader 發送請求獲取 TSO,PD client 並不會將收到的請求立刻發送給 PD leader ,而將同一時刻收到的所有請求打包發送給 PD leader,然後由 PD leader 返回一批 TSO。由於僅有 leader 提供服務,tidb server 數量較多時會有較多的 PD Client 和 PD Leader 建立連接,導致切換處理連接請求時 CPU 消耗較高。同時 follower 節點僅通過 raft 同步數據和提供選舉等功能,基本處於空閑狀態。

在 5.3.0 版本引入 TSO Follower Proxy 功能,當開啟後 tidb 的 PD Client 會隨機選擇一個 PD 節點(包括 leader 和 follower )發送 TSO 請求,PD Follower 會作為一個代理服務將收到的一批請求按照默認情况下 PD Client 處理 TSO 方式打包發送給 leader 處理,以進一步减少 PD Client 和 PD Leader 的交互次數以及 PD leader 的連接數,以此降低 leader 的 CPU 負載。

通過設置全局變量 tidb_enable_tso_follower_proxy 為 true 即可開啟 PD follower 的 TSO 代理功能,該功能適用於 tidb server 數量較多並發請求很高,PD leader 因高壓力的 TSO 請求而達到 CPU 瓶頸,導致 TSO RPC 請求的延遲較高的場景。

4. RC Read TSO 優化

Read-Commited 隔離級別需要在悲觀事務模式下,在悲觀事務中每個 SQL 執行時會從 PD 獲取 TSO (for_update_ts) 用於一致性讀、沖突檢測等,每個 SQL 相當於一個 Snapshot-Isolation 的’小事務’,相比樂觀事務模式悲觀事務產生的 TSO 請求會更多,在整個事務期間如果能在不破壞事務一致性和隔離性的情况下减少 tso 請求次數,就能够降低 PD 的負載和事務延遲,從而提昇整體性能。

6.0 版本中對 RC 事務中的 SELECT 語句 TSO 請求做了優化,使用一種樂觀方式獲取 TSO ,僅當遇到新版本後才會獲取最新的 TSO 讀取數據,通過减少讀操作從 PD 獲取 TSO 的請求次數,從而降低查詢延遲,提昇讀寫沖突較小場景的 QPS。該特性由 tidb_rc_read_check_ts 變量控制,默認為 off,開啟該功能設置為 on 即可。

優化後 select 語句處理基本過程如下:

  1. Select 語句執行時不從 PD 獲取 TSO 作為 for_update_ts,而是使用上一個有效的 TSO 作為 for_update_ts(即為 read_ts)。如果是事務中的第一個語句則是 start_ts,否則是上一個 SQL 的 for_update_ts。

  2. 構建執行計劃並執行,發送到 tikv 的數據讀取請求(pointget、coprocessor)會帶上 RcReadCheckTS 標志。

  3. 數據讀取請求使用前面獲得的 read_ts 做一致性讀取,並將數據返回 tidb server。

  4. TiKV 會檢查返回的數據是否有更新版本,如果有更新的版本則返回 WriteConflict 錯誤,否則返回數據後正常結束執行。

  5. 如果此時 tidb 還未向 client 發送數據則會從 PD 獲取最新的 TSO 作為 for_update_ts 重新執行整個查詢,否則會向 client 返回錯誤。

從上面的過程可以看出當遇到新版本後會導致 tidb server 使用正常的流程重新獲取 TSO 和執行 SQL,在讀寫沖突的情况下會降低性能使得事務執行時間延長。如果已經有部分數據返回 client 的話會導致報錯 SQL 執行失敗,雖然通過增加 tidb_init_chunk_size 變量大小延遲 tikv 返回數據時間,可以降低一些上述錯誤發生的情况,但仍然不是一個根本解决方式。

5. Local TSO

在多數據中心場景下 PD leader 比特於某個數據中心內,數據中心間的延遲會造成 TSO 請求延遲增加,如果能够在數據中心內完成 TSO 請求和分配則可以大大降低 TSO 請求延遲。基於此 tidb 引入了 Local TSO (實驗功能),PD 中設計 2 個 TSO allocator 角色:local tso allocator 和 global tso allocator,相應的事務也被分成了本地事務 local transaction 和全局事務 global transaction 兩種。

  • Local TSO

當通過 enable-local-tso 啟用後數據中心內的 PD 會選出一個節點作為 local tso allocator 用於分配 TSO,該節點作為 local tso 分配的 leader 角色( PD 角色仍為 follower )。當事務操作的數據僅涉及到本數據中心的數據時,則判斷為本地事務,向本地 tso allocator 申請 local tso。

每個數據中心分配自己的 local tso,相互之間是獨立的,為避免不同數據中心分配了相同的 TSO,PD 會設置 local tso 中的邏輯時間低幾比特做後綴,不同的數據中心使用不同的值,同時這些信息會持久化記錄到 PD 內。

  • Global TSO

當事務操作的數據涉及到其他數據中心時則為全局事務,此時需要向 PD leader 申請 global tso, PD leader 作為 global tso allocator。當未啟用 local-tso 功能時,仍按原來的邏輯所有數據中的 TSO 請求由 PD leader 負責處理。

為保證 local tso 和 global tso 的線性增長,global tso allocator 和 local tso allocator 會進行 max_tso 同步:

  1. Global tso allocator 收集所有 local tso allocator 的最大 local tso。

  2. 從所有 local tso 中選出一個最大的 local tso 作為 max_tso 下發到 local allocator。

  3. 如果 max_tso 比自己的大則更新 TSO 為 max_tso,否則直接返回成功。

Local tso 的使用需要考慮不同的數據中心處理不同的業務,同時要結合 PlacementRules in SQL 將錶根據業務規則按數據中心進行分布,同時可設置 txn_scope 變量為 local/global 用於人為控制獲取 global tso 還是 local tso.

基本配置步驟 (目前不支持 Local TSO 回退為 Global TSO 模式):

  1. PD、TiKV、TiDB server 均需要根據實際部署設置 label,為保證高可用每個 DC 的 PD 數量應>1。

  1. 開啟庫或錶級 Placement Rules in SQL,根據地域和業務關系進行調度。

CREATE PLACEMENT POLICY dc1_leader LEADER_CONSTRAINTS="DC1" FOLLOWER_CONSTRAINTS="DC1,DC2,DC3" FOLLOWERS=2; Alter table new_order PARTITION p0 PLACEMENT POLICY dc1_leaders;

  1. 設置 PD 參數 enable-local-tso=on 使用 tiup reload 重啟 PD 開啟 Local TSO 功能。啟用之後可通過 pd-ctl -u pd_ip:pd_port member 中 tso_allocator_leaders 項內容查看每個中心的 local tso allocator leader。

6. 測試

6.1 測試環境

6.2 TSO Follower Proxy

在 1024 線程下使用 sysbench 對 6 張 1 億記錄錶在開啟 TSO Follower Proxy 前後的 TPS 和平均延遲如下:

測試期間 TSO Follower Proxy 關閉和開啟時的 CPU 利用率:

6.3 RC Read TSO

使用 tiup-bench 測試不同線程下開啟 tidb_rc_read_check_ts 前後的 TPCC,可以看到開啟該功能後對 TPCC 有一定提昇,但隨著線程數增加沖突增多 TPCC 出現下降情况。

通過 TiDB –> PD Client –> PD Client CMD OPS 監控可以看到 256 線程下開啟 tidb_rc_read_check_ts 後 PD client 中等待 TSO 的次數明顯降低。

6.4 Local TSO

Local TSO 作為實驗功能尚需完善,TPCC 測試中當開啟該功能後出現大量報主鍵重複錯誤。

7. 總結

為提昇 TSO 的擴展性和效率,TiDB 進行了大量的優化工作,但這些優化有確定的場景,需要結合業務和實際情况考慮,否則盲目開啟有可能會造成 QPS 降低、延遲增高的情况:

對於 Follower TSO Proxy 適合於由於 PD Leader CPU 繁忙導致的 TSO 獲取延遲的場景,通過開啟 Follower Proxy 後降低 leader 的壓力。

RC Read TSO 優化適合於讀多寫少的場景,如果數據沖突嚴重反而會造成性能下降。

Local TSO 作為 TiDB 分布式授時方案從理論上能够解决因數據中心間的延遲造成的 TSO 延遲,不過目前實驗功能尚有一些問題。

原网站

版权声明
本文为[TiDB]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/181/202206300310378291.html