作者:翟玉龍,施聞軒
本文适用于 TiDB 4.0 版本,介紹了如何定位和解決寫入熱點問題。關于讀熱點的處理方法,可臨時參考下面的文章,也請期待我們的後續補充
- 「少數 region 讀、寫流量很大的熱點表該如何處理?」
TiDB 作為分布式資料庫,自身擁有一些負載均衡機制,盡可能将業務負載均勻地分布到不同計算或存儲節點上,更好地利用上整體系統資源。然而,機制不是萬能的,在一些場景下仍會有部分業務負載不能被很好地分散,影響性能,形成單點的過高負載,也稱為熱點。
TiDB 提供了完整的方案用于排查、解決或規避這類熱點。通過均衡負載熱點,可以提升整體性能,包括提高 QPS 和降低延遲等。
需要說明的是,性能問題不一定是熱點造成的,也有可能有多個因素共同影響,在排查前需要先确認是否與熱點相關(見下文)。另外,即使業務負載嚴重不均衡、熱點明顯,也不會引發正确性問題。
确認存在寫熱點
判斷依據:打開監控面闆 TiKV-Trouble-Shooting 中 Hot Write 面闆(如下圖所示),觀察 Raftstore CPU 監控是否存在個别 TiKV 節點的名額明顯高于其他節點的現象。
示例:存在寫熱點
18:30 前有單個 TiKV 執行個體的 Raft store CPU 比其他節點高出将近一倍,存在寫入熱點。在 18:30 後,寫入熱點得到了緩解。

示例:負載均衡、不存在明顯熱點
示例:負載不夠均衡,但不是熱點
需要注意排除以下案例,監控中負載有一定的不均衡,但因為并非個别 TiKV CPU 名額過高,是以不構成熱點:
使用 TiDB Dashboard 定位熱點表
TiDB Dashboard 中的「熱點可視化」功能可幫助使用者縮小熱點排查範圍到表級别。以下是一個「熱點可視化」功能展示的熱力圖樣例,該圖橫坐标是時間,縱坐标排列了各個表和索引,顔色越亮代表其流量越大。可在工具欄中切換顯示讀或寫流量。
當圖中寫入流量圖出現以下明亮斜線(斜向上或斜向下)時,說明該大流量表構成了寫入熱點:
将滑鼠移到亮色塊上,即可看到是什麼表或索引具有大流量,如下所示:
大多數情況下,顯著的熱點都會來自于表資料。索引熱點有存在的可能性,但一般不大顯著,是以本文不覆寫。
這類寫入熱點主要有以下幾種成因:
成因 | 規避或解決方案 |
自增主鍵 | 不要使用自增主鍵,可改用 UUID 等,或使用 AUTO_RANDOM |
無主鍵/聯合主鍵/非 INT 類型主鍵 | 使用 SHARD_ROW_ID_BITS |
INT 類型主鍵,且連續寫入數值接近的主鍵 | 将該主鍵改為普通索引,再使用 SHARD_ROW_ID_BITS |
寫入流量圖中以下這類亮色橫線對應的則是另一種熱點模式:熱點小表,但 TiDB 内置機制還不能很好地緩解這個情況,建議通過業務側增加緩存等方法繞過:
可閱讀「TiDB in Action - 2.1 識别叢集熱點和業務模式」進一步了解「熱點可視化」工具的使用。
使用 SHARD_ROW_ID_BITS 處理熱點表
本方法不适用于自增主鍵,自增主鍵可用下文的 AUTO_RANDOM 方法。另外如果熱點表的主鍵是 INT 類型,使用本方法前需先去除主鍵改為普通索引。
通過設定表的 SHARD_ROW_ID_BITS 屬性可以将相鄰的行寫入轉化為離散的行寫入,緩解熱點。樣例如下:
CREATE TABLE t (a INT) SHARD_ROW_ID_BITS = 4;
ALTER TABLE t SHARD_ROW_ID_BITS = 4;
SHARD_ROW_ID_BITS 的值決定了打散程度,使用者可根據 TiKV 個數以及打散效果決定和調整該值的大小:
- SHARD_ROW_ID_BITS = 4 表示 16 個分片
- SHARD_ROW_ID_BITS = 6 表示 64 個分片
- SHARD_ROW_ID_BITS = 0 表示預設值 1 個分片
SHARD_ROW_ID_BITS 的值可以動态修改,每次修改之後,隻對新寫入的資料生效。
注意:SHARD_ROW_ID_BITS 不宜設定得過大,否則會造成 TiDB 與 TiKV 之間内部請求數放大(與分片數相關),增加 CPU 和網絡開銷,無法取得最佳性能。
以下是兩張無主鍵情況下使用 SHARD_ROW_ID_BITS 打散熱點後的流量圖,第一張展示了打散前的情況,第二張展示了打散後的情況。
由流量圖可見,設定 SHARD_ROW_ID_BITS 後,流量熱點可以由之前的很集中變得很分散。
更詳細的使用方法可以閱讀 SHARD_ROW_ID_BITS 文檔。
使用 AUTO_RANDOM 處理自增主鍵熱點表
适用于代替自增主鍵,解決自增主鍵帶來的寫入熱點。
該功能目前還是實驗性功能,不推薦生産環境使用。可使用以下配置啟用:
[experimental]
allow-auto-random = true
使用該功能後,将由 TiDB 生成随機分布且空間耗盡前不重複的主鍵,達到離散寫入、打散寫入熱點的目的。注意,TiDB 生成的主鍵不再是自增的主鍵,可使用 LAST_INSERT_ID() 擷取上次配置設定的主鍵值。
接下來,将建表語句中的 AUTO_INCREMENT 改為 AUTO_RANDOM 即可使用該功能,示例如下:
以下是将 AUTO_INCREMENT 表改為 AUTO_RANDOM 打散熱點後的流量圖,第一張是 AUTO_INCREMENT,第二張是 AUTO_RANDOM。
由流量圖可見,使用 AUTO_RANDOM 代替 AUTO_INCREMENT 可以很好地打散熱點情況。
更詳細的使用方法可以閱讀 AUTO_RANDOM 文檔。