我是如何低效的看TiKV代碼的(一)

先從TiDB說起

TiDB 是什么

首先引用一下官方的定義:

TiDB 是 PingCAP 公司受 Google Spanner / F1 論文啟發(fā)而設計的開源分布式 HTAP (Hybrid Transactional and Analytical Processing) 數(shù)據(jù)庫纠屋,結合了傳統(tǒng)的 RDBMS 和 NoSQL 的最佳特性。TiDB 兼容 MySQL,支持無限的水平擴展窘游,具備強一致性和高可用性甸私。TiDB 的目標是為 OLTP (Online Transactional Processing) 和 OLAP (Online Analytical Processing) 場景提供一站式的解決方案。

TiDB 具備如下核心特性:

  • 高度兼容 MySQL

大多數(shù)情況下神帅,無需修改代碼即可從 MySQL 輕松遷移至 TiDB罕容,分庫分表后的 MySQL 集群亦可通過 TiDB 工具進行實時遷移。

  • 水平彈性擴展

通過簡單地增加新節(jié)點即可實現(xiàn) TiDB 的水平擴展高帖,按需擴展吞吐或存儲缰儿,輕松應對高并發(fā)、海量數(shù)據(jù)場景散址。

  • 分布式事務

TiDB 100% 支持標準的 ACID 事務乖阵。

  • 真正金融級高可用

相比于傳統(tǒng)主從 (M-S) 復制方案,基于 Raft 的多數(shù)派選舉協(xié)議可以提供金融級的 100% 數(shù)據(jù)強一致性保證预麸,且在不丟失大多數(shù)副本的前提下瞪浸,可以實現(xiàn)故障的自動恢復 (auto-failover),無需人工介入吏祸。

  • 一站式 HTAP 解決方案

TiDB 作為典型的 OLTP 行存數(shù)據(jù)庫对蒲,同時兼具強大的 OLAP 性能,配合 TiSpark贡翘,可提供一站式 HTAP 解決方案齐蔽,一份存儲同時處理 OLTP & OLAP,無需傳統(tǒng)繁瑣的 ETL 過程床估。

TiDB 的設計目標是 100% 的 OLTP 場景和 80% 的 OLAP 場景含滴。它解決了我們工作中面臨的因為數(shù)據(jù)量大到一定程度后橫向擴展受限,人工進行分庫分表丐巫,人工進行數(shù)據(jù)庫事務的問題谈况。降低了開發(fā)人員的心智負擔,讓開發(fā)人員可以更專注于具體業(yè)務递胧,提高了生產(chǎn)效率碑韵。

TiDB 整體架構

tidb總體結構

TiDB 有 TiDB Server 、PD Server缎脾、 TiKV Server 三個核心組件祝闻。

  • PD 是整個集群的管理模塊,它擁有上帝視角遗菠。 其主要工作有三個:一是存儲集群的元信息(某個 Key 存儲在哪個 TiKV 節(jié)點)联喘;二是對 TiKV 集群進行調度和負載均衡(如數(shù)據(jù)的遷移、Raft group leader 的遷移等)辙纬;三是分配全局唯一且遞增的事務 ID豁遭。

  • TiKV Server 是一個分布式的提供事務的 Key-Value 存儲引擎。 TiDB Server 負責接收 SQL 請求贺拣,處理 SQL 相關的邏輯蓖谢,并通過 PD 找到存儲計算所需數(shù)據(jù)的 TiKV 地址捂蕴,與 TiKV 交互獲取數(shù)據(jù),最終返回結果闪幽。

  • TiDB Server 是無狀態(tài)的啥辨,其本身并不存儲數(shù)據(jù),只負責計算盯腌,可以無限水平擴展委可,

在執(zhí)行一條Insert語句會做什么事情?

畫不多說腊嗡, 先上圖:


tidb內部結構

不要被這么復雜的圖嚇怕,因為其中的絕大部分內容都不會涉及(我也不會拾酝,不會還要拿來show --!!)燕少。
主體流程還是很容易明白的,首先蒿囤,TiDB會解析執(zhí)行的SQL語句客们,使用parser 將其變成AST,然后通過執(zhí)行計劃將其拆解成一個個的executor材诽。在獲取到所有的executor的執(zhí)行結果后底挫,對數(shù)據(jù)進行拼裝,最終返回給客戶端脸侥。

那么建邓,在數(shù)據(jù)庫中數(shù)據(jù)是怎么進行存儲,Server又是如何進行訪問的呢睁枕?
其實官边,數(shù)據(jù)庫將表中的row映射成kv結構,然后將kv進行物理存儲外遇。MySQL如此注簿,TiDB也是如此。這種想法其實也很自然跳仿,數(shù)據(jù)庫表中的每行使用id 作為key诡渴,行的內容作為value存儲下來,查詢某條記錄菲语,就變成了根據(jù)某個key妄辩,找對應的value。

Key的生成策略

首先山上,我們需要面對的問題就是對于一個數(shù)據(jù)庫表恩袱,使用什么樣的key生成策略來保存行的內容。同時因為數(shù)據(jù)庫的索引結構也可以用表存儲胶哲,因此畔塔,數(shù)據(jù)庫的索引也會被持久化到kv 中。

TiDB 對每個表分配一個 TableID,每一個索引都會分配一個 IndexID澈吨,每一行分配一個 RowID(如果表有整數(shù)型的 Primary Key把敢,那么會用 Primary Key 的值當做 RowID),其中 TableID 在整個集群內唯一谅辣,IndexID/RowID 在表內唯一修赞,這些 ID 都是 int64 類型。

  1. 數(shù)據(jù)庫行的key生成策略
${tablePrefix}_${rowPrefix}_${tableID}_${rowID}

其中tablePrefix是固定的t_桑阶, rowPrefix是固定的r_柏副。比如 table table_demo 的ID 為10,其中第一條數(shù)據(jù)的row ID 是1蚣录,那么它的key是t_r_10_1

  1. 數(shù)據(jù)庫索引key的生成策略
  • 主鍵或者唯一鍵的索引
${tablePrefix}_${idxPrefix}_${tableID}_${indexID}_${indexColumnsValue}

其中idxPrefix 是固定的i_割择, 比如id字段的索引ID 為2, 那么它對應的key 是 t_i_10_2_1 --> t_r_10_1

  • 非主鍵索引
${tablePrefix}_${idxPrefix}_${tableID}_${indexID}_${ColumnsValue}_${rowID}

具體的細節(jié)可以查看參考資料萎河,里面有非常詳細的表述荔泳。這里不做過多的解釋

TiDB 和TiKV的交互接口

在整個學習的過程中,頭腦中需要有一個問題虐杯,select玛歌,insert 操作是怎么在TiKV中實現(xiàn)的。
既然TiDB 已經(jīng)將具體的數(shù)據(jù)庫的row擎椰, 轉化成了kv支子,那么問題本身也就轉化成了在TiKV中如何實現(xiàn)getset 命令达舒。

這里先列舉相關的TiKV暴露給TiDB調用的接口译荞,學習的過程可以從這里入手。

service Tikv {

    // KV commands with mvcc/txn supported.

    rpc KvGet(kvrpcpb.GetRequest) returns (kvrpcpb.GetResponse) {}

    rpc KvScan(kvrpcpb.ScanRequest) returns (kvrpcpb.ScanResponse) {}

    rpc KvPrewrite(kvrpcpb.PrewriteRequest) returns (kvrpcpb.PrewriteResponse) {}

    rpc KvCommit(kvrpcpb.CommitRequest) returns (kvrpcpb.CommitResponse) {}

    rpc KvImport(kvrpcpb.ImportRequest) returns (kvrpcpb.ImportResponse) {}

    rpc KvCleanup(kvrpcpb.CleanupRequest) returns (kvrpcpb.CleanupResponse) {}

    rpc KvBatchGet(kvrpcpb.BatchGetRequest) returns (kvrpcpb.BatchGetResponse) {}

    rpc KvBatchRollback(kvrpcpb.BatchRollbackRequest) returns (kvrpcpb.BatchRollbackResponse) {}

    rpc KvScanLock(kvrpcpb.ScanLockRequest) returns (kvrpcpb.ScanLockResponse) {}

    rpc KvResolveLock(kvrpcpb.ResolveLockRequest) returns (kvrpcpb.ResolveLockResponse) {}

    rpc KvGC(kvrpcpb.GCRequest) returns (kvrpcpb.GCResponse) {}

    rpc KvDeleteRange(kvrpcpb.DeleteRangeRequest) returns (kvrpcpb.DeleteRangeResponse) {}

    // RawKV commands.

    rpc RawGet(kvrpcpb.RawGetRequest) returns (kvrpcpb.RawGetResponse) {}

    rpc RawBatchGet(kvrpcpb.RawBatchGetRequest) returns (kvrpcpb.RawBatchGetResponse) {}

    rpc RawPut(kvrpcpb.RawPutRequest) returns (kvrpcpb.RawPutResponse) {}

    rpc RawBatchPut(kvrpcpb.RawBatchPutRequest) returns (kvrpcpb.RawBatchPutResponse) {}

    rpc RawDelete(kvrpcpb.RawDeleteRequest) returns (kvrpcpb.RawDeleteResponse) {}

    rpc RawBatchDelete(kvrpcpb.RawBatchDeleteRequest) returns (kvrpcpb.RawBatchDeleteResponse) {}

    rpc RawScan(kvrpcpb.RawScanRequest) returns (kvrpcpb.RawScanResponse) {}

    rpc RawDeleteRange(kvrpcpb.RawDeleteRangeRequest) returns (kvrpcpb.RawDeleteRangeResponse) {}

    rpc RawBatchScan(kvrpcpb.RawBatchScanRequest) returns (kvrpcpb.RawBatchScanResponse) {}

    // SQL push down commands.

    rpc Coprocessor(coprocessor.Request) returns (coprocessor.Response) {}

    rpc CoprocessorStream(coprocessor.Request)  returns (stream coprocessor.Response) {}

    // Raft commands (tikv <-> tikv).

    rpc Raft(stream raft_serverpb.RaftMessage) returns (raft_serverpb.Done) {}

    rpc Snapshot(stream raft_serverpb.SnapshotChunk) returns (raft_serverpb.Done) {}

    // Region commands.

    rpc SplitRegion (kvrpcpb.SplitRegionRequest) returns (kvrpcpb.SplitRegionResponse) {}

    // transaction debugger commands.

    rpc MvccGetByKey(kvrpcpb.MvccGetByKeyRequest) returns (kvrpcpb.MvccGetByKeyResponse) {}

    rpc MvccGetByStartTs(kvrpcpb.MvccGetByStartTsRequest) returns (kvrpcpb.MvccGetByStartTsResponse) {}

}

參考資料

  1. https://pingcap.com/blog-cn/tidb-internal-2/

  2. https://pingcap.com/blog-cn/tidb-source-code-reading-4/

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末休弃,一起剝皮案震驚了整個濱河市吞歼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌塔猾,老刑警劉巖篙骡,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異丈甸,居然都是意外死亡糯俗,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門睦擂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來得湘,“玉大人,你說我怎么就攤上這事顿仇√哉” “怎么了摆马?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鸿吆。 經(jīng)常有香客問我囤采,道長,這世上最難降的妖魔是什么惩淳? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任蕉毯,我火速辦了婚禮,結果婚禮上思犁,老公的妹妹穿的比我還像新娘代虾。我一直安慰自己,他們只是感情好激蹲,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布棉磨。 她就那樣靜靜地躺著,像睡著了一般托呕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上频敛,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天项郊,我揣著相機與錄音,去河邊找鬼斟赚。 笑死着降,一個胖子當著我的面吹牛,可吹牛的內容都是我干的拗军。 我是一名探鬼主播任洞,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼发侵!你這毒婦竟也來了交掏?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤刃鳄,失蹤者是張志新(化名)和其女友劉穎盅弛,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叔锐,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡挪鹏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了愉烙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片讨盒。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖步责,靈堂內的尸體忽然破棺而出返顺,到底是詐尸還是另有隱情禀苦,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布创南,位于F島的核電站伦忠,受9級特大地震影響,放射性物質發(fā)生泄漏稿辙。R本人自食惡果不足惜昆码,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望邻储。 院中可真熱鬧赋咽,春花似錦、人聲如沸吨娜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宦赠。三九已至陪毡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間勾扭,已是汗流浹背毡琉。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留妙色,地道東北人桅滋。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像身辨,于是被迫代替她去往敵國和親丐谋。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內容

  • 一煌珊、分布式數(shù)據(jù)庫誕生背景 隨著互聯(lián)網(wǎng)的飛速發(fā)展号俐,業(yè)務量可能在短短的時間內爆發(fā)式地增長,對應的數(shù)據(jù)量可能快速地從幾百...
    nightwish夜愿閱讀 3,514評論 0 12
  • 71.1kg 早飯:一杯醇品定庵,三片切片萧落,20g原味沙拉醬,白開水兩杯洗贰。 午飯:一份米飯淋辣椒油(美滋滋)找岖,一份蔥豆...
    yummy0632閱讀 190評論 0 0
  • 產(chǎn)后第一件事:滿月排毒發(fā)汗 產(chǎn)后排毒發(fā)汗越早做越好许布,只要在產(chǎn)后身體沒有閉合狀態(tài)下,早排毒早好绎晃,排出身體毒素蜜唾、濕氣杂曲,...
    蘊姿媽媽產(chǎn)后調理閱讀 1,264評論 0 1
  • 初識餅部落是一個很簡單的開始:愛鮮啤的掌柜在朋友圈做了一個推薦,出于對掌柜的信任袁余,添加了酋長和餅哥的微信擎勘,...
    堯酋長閱讀 748評論 2 3
  • 自我分析(以第三人稱敘述): 首先是屋頂。屋頂瓦片層層疊疊颖榜,看似很用細心添磚加瓦棚饵,細看的話,第一排和最后一排的精細...
    渡迷閱讀 283評論 2 1