TIDB儲存TiKV的鍵值對資料

小火子冲冲冲發表於2024-05-26

1. TiDB概述

TiDB 是一款開源 分散式關係型資料庫,同時支援 線上事務處理(OLTP) 與 線上分析處理(OLAP) 的混合型(Hybrid Transactional and Analytical Processing, HTAP) 分散式資料庫,具備水平擴容或縮容、金融級高可用、實時 HTAP、Kubernetes 雲原生的分散式資料庫、相容 MySQL 5.7 協議和 MySQL 生態等重要特性,支援在本地和雲上部署。

與傳統的單機 MySQL 資料庫相比,TiDB 具有以下優勢:

  • 分散式架構: 純分散式架構,擁有良好的擴充套件性,支援彈性的擴縮容

  • 相容MySQL: 支援 SQL,對外暴露 MySQL 的網路協議,併相容大多數 MySQL 的語法,在大多數場景下可以直接替換 MySQL

  • 高可用部署: 預設支援高可用,在少數副本失效的情況下,資料庫本身能夠自動進行資料修復和故障轉移,對業務透明

  • 支援強一致性: 符合CAP理論的CP,支援 ACID 事務,對於一些有強一致需求的場景友好,例如:銀行轉賬

  • 豐富的開源生態鏈: 具有豐富的工具鏈生態,覆蓋資料遷移、同步、備份等多種場景

2. TiDB元件

在核心設計上,TiDB 分散式資料庫將整體架構拆分成了多個模組,各模組之間互相通訊,組成完整的 TiDB 系統。對應的架構圖如下:

計算引擎層:TiDB/TiSpark

儲存引擎層:TiKV/TiFlash

3. TiKV鍵值對資料是如何組織的

1. 表資料對映到KV

由於 TiDB 底層基於鍵值對儲存資料,TiDB 表中的 行資料 需要按照一定格式對映轉換為 鍵值對:

  • 為了保證同一張表的資料放在一起,方便查詢,TiDB 會為每個表分配一個 表 ID,用 TableID 表示。表 ID 是一個整數,在整個 叢集內唯一。

  • TiDB 會為表中每行資料分配一個 行 ID,用 RowID 表示。行 ID 也是一個整數,在表內唯一。對於行 ID,TiDB 做了一個小最佳化,如果某個表有整數型的主鍵,TiDB 會使用主鍵的值當做這一行資料的行 ID。

每行資料按照如下規則編碼成 (Key, Value) 鍵值對:

Key: tablePrefix{TableID}_recordPrefixSep{RowID}
Value: [col1, col2, col3, col4]

2. 表索引對映到KV

TiDB 同時支援 主鍵索引 和 二級索引。與表資料對映方案類似,TiDB 為表中每個索引分配了一個 索引 ID,用 IndexID 表示。

  • 對於 主鍵索引 和 唯一索引,需要根據鍵值快速定位到對應的 RowID,因此,按照如下規則編碼成 (Key, Value) 鍵值對:

Key: tablePrefix{TableID}_indexPrefixSep{IndexID}_indexedColumnsValue
Value: RowID

  • 對於非唯一性約束的 普通二級索引,一個鍵值可能 對應多行,需要根據 鍵值範圍 查詢對應的 RowID。因此,按照如下規則編碼成 (Key, Value) 鍵值對:

Key: tablePrefix{TableID}_indexPrefixSep{IndexID}indexedColumnsValue{RowID}
Value: null

3. KV對映示例

資料與 KV 的對映關係,定義如下:

複製
tablePrefix     = []byte{'t'}recordPrefixSep = []byte{'r'}indexPrefixSep  = []byte{'i'}1.2.3.

假設表結構如下:

複製
CREATE_TABLE User (    ID int,    Name varchar(20),    Role varchar(20),    Age int,    UID int,    PRIMARY KEY (ID),    KEY idxAge (Age),    UNIQUE KEY idxUID (UID));1.2.3.4.5.6.7.8.9.10.

假設表資料如下:

複製
1, "TiDB", "SQL Layer", 10, 100012, "TiKV", "KV Engine", 20, 100023, "PD", "Manager", 30, 100031.2.3.
  • 表資料對映到KV如下:

複製
t10_r1 --> ["TiDB", "SQL Layer", 10, 10001]t10_r2 --> ["TiKV", "KV Engine", 20, 10002]t10_r3 --> ["PD",   "Manager",   30, 10003]1.2.3.
  • 唯一索引對映到KV如下:

複製
t10_i1_10001 --> 1t10_i2_10002 --> 2t10_i3_10003 --> 31.2.3.
  • 非唯一索引對映到KV如下:

複製
# 假設 IndexID 為 1t10_i1_10_1 --> nullt10_i1_20_2 --> nullt10_i1_30_3 --> null1.2.3.4

相關文章