一、TiKV存儲(chǔ)
簡(jiǎn)述
- 通過(guò)單機(jī)的 RocksDB供鸠,TiKV 可以將數(shù)據(jù)快速地存儲(chǔ)在磁盤(pán)上杖玲;通過(guò) Raft,將數(shù)據(jù)復(fù)制到多臺(tái)機(jī)器上侥袜,以防單機(jī)失效骇窍。數(shù)據(jù)的寫(xiě)入是通過(guò) Raft 這一層的接口寫(xiě)入雌团,而不是直接寫(xiě) RocksDB旗唁。通過(guò)實(shí)現(xiàn) Raft,TiKV 變成了一個(gè)分布式的 Key-Value 存儲(chǔ)身腻,少數(shù)幾臺(tái)機(jī)器宕機(jī)也能通過(guò)原生的 Raft 協(xié)議自動(dòng)把副本補(bǔ)全雄坪,繼續(xù)讓業(yè)務(wù)無(wú)感知的對(duì)外服務(wù)厘熟。
Region
將整個(gè) Key-Value 空間分成很多段,每一段是一系列連續(xù)的 Key维哈,將每一段叫做一個(gè) Region绳姨,并且會(huì)盡量保持每個(gè) Region 中保存的數(shù)據(jù)不超過(guò)一定的大小,目前在 TiKV 中默認(rèn)是 96MB阔挠。每一個(gè) Region 都可以用 [StartKey飘庄,EndKey) 這樣一個(gè)左閉右開(kāi)區(qū)間來(lái)描述。
- 以 Region 為單位购撼,將數(shù)據(jù)分散在集群中所有的節(jié)點(diǎn)上跪削,并且盡量保證每個(gè)節(jié)點(diǎn)上服務(wù)的 Region 數(shù)量差不多
- 以 Region 為單位做 Raft(數(shù)據(jù)) 的復(fù)制和成員管理:一個(gè) Region 的多個(gè) Replica 會(huì)保存在不同的節(jié)點(diǎn)上,構(gòu)成一個(gè) Raft Group迂求。其中一個(gè) Replica 會(huì)作為這個(gè) Group 的 Leader碾盐,其他的 Replica 作為 Follower。所有的讀和寫(xiě)都是通過(guò) Leader 進(jìn)行揩局,(寫(xiě))再由 Leader 復(fù)制給 Follower毫玖。
MVCC(多版本并發(fā)控制)
TiKV 的 MVCC 實(shí)現(xiàn)是通過(guò)在 Key 后面添加版本號(hào)來(lái)實(shí)現(xiàn)×瓒ⅲ可以直接通過(guò) RocksDB 的 API: SeekPrefix(Key-Version)付枫,定位到第一個(gè)大于等于這個(gè) Key_Version 的位置。
分布式 ACID 事務(wù)
TiKV 的事務(wù)采用的是 Google 在 BigTable 中使用的事務(wù)模型:Percolator
能保證要么全部成功十气,要么全部失敗,不會(huì)出現(xiàn)的中間狀態(tài)和臟數(shù)據(jù)春霍。
二砸西、TiDB如何使用TiKV
問(wèn)題:如何存儲(chǔ)數(shù)據(jù)?哪些作為key址儒,哪些作為value芹枷?
對(duì)于一個(gè) Table 來(lái)說(shuō),需要存儲(chǔ)的數(shù)據(jù)包括三部分:
- 表中每一行的數(shù)據(jù)莲趣,以下簡(jiǎn)稱(chēng)表數(shù)據(jù)
- 表中所有索引的數(shù)據(jù)鸳慈,以下簡(jiǎn)稱(chēng)索引數(shù)據(jù)
- 表的元信息
對(duì)于表中每一行的數(shù)據(jù),既可以選擇行存也可以選擇列存喧伞,兩者各有優(yōu)缺點(diǎn)走芋,適用不同場(chǎng)景绩郎。
TiDB 的首要目標(biāo)是 OLTP 業(yè)務(wù),要滿(mǎn)足這類(lèi)業(yè)務(wù)的需求翁逞,數(shù)據(jù)庫(kù)需要支持快速的針對(duì)單行或者某些行的增肋杖、刪、改挖函、查等操作状植,所以 TiKV 的行存是比較合適該場(chǎng)景的。
從 TiDB 3.1 開(kāi)始(包括 TiDB 4.0)怨喘,為了能夠滿(mǎn)足用戶(hù)復(fù)雜的實(shí)時(shí)分析場(chǎng)景(OLAP津畸?),TiDB 提供了一個(gè)叫做** TiFlash 的列存引擎**必怜,它提供了列式的存儲(chǔ)模式和快速的分析能力肉拓。列存的映射關(guān)系比較簡(jiǎn)單,這里暫且不表棚赔。
2.1 索引
索引數(shù)據(jù)帝簇,TiDB 同時(shí)支持主鍵和二級(jí)索引(包括唯一索引和非唯一索引)。在 OLTP 場(chǎng)景下靠益,好的索引能夠極大的提升 SQL 查詢(xún)的性能丧肴,降低集群的整體負(fù)載。
- 對(duì)于 Insert 語(yǔ)句胧后,既需要將表數(shù)據(jù)寫(xiě)入 KV 存儲(chǔ)芋浮,也需要構(gòu)造和存儲(chǔ)對(duì)應(yīng)的索引數(shù)據(jù)。
- 對(duì)于 Update 語(yǔ)句壳快,需要在更新表數(shù)據(jù)的同時(shí)纸巷,也更新對(duì)應(yīng)的索引數(shù)據(jù)(如果有必要的話(huà))。
- 對(duì)于 Delete 語(yǔ)句眶痰,需要在刪除表數(shù)據(jù)的同時(shí)瘤旨,也刪除對(duì)應(yīng)的索引數(shù)據(jù)(如果有必要的話(huà))。
- 對(duì)于 Select 語(yǔ)句竖伯,情況會(huì)復(fù)雜一些存哲。用戶(hù)希望數(shù)據(jù)庫(kù)提供快速讀取一行數(shù)據(jù)的能力,所以每行表數(shù)據(jù)最好有一個(gè)唯一 ID (顯示或隱式的 ID)方便快速讀取七婴。其次用戶(hù)也可能會(huì)連續(xù)地讀取多行數(shù)據(jù)祟偷,比如 select * from user。最后還有通過(guò)索引讀取數(shù)據(jù)的需求打厘,對(duì)索引的使用可能是基于唯一索引或者主鍵的等值查詢(xún)(業(yè)界常說(shuō)的“點(diǎn)查”)或者是范圍查詢(xún)修肠。
當(dāng)然,在有了 TiFlash 以后户盯,全表掃更適合在 TiFlash 上進(jìn)行嵌施,因?yàn)榱惺酱鎯?chǔ)的優(yōu)勢(shì)饲化,這種場(chǎng)景中它能提供更快的讀取性能。
2.1.1 行數(shù)據(jù)的key設(shè)計(jì)
TiDB會(huì)為全集群生成唯一表ID艰管,為表內(nèi)數(shù)據(jù)生成唯一的行ID(有整型主鍵則是主鍵作為行ID)滓侍,則數(shù)據(jù)如下:
Key: tablePrefix{TableID}_recordPrefixSep{RowID}
Value: [col1, col2, col3, col4]
2.1.2 索引數(shù)據(jù)的 Key-Value 映射關(guān)系
TiDB 為表中每個(gè)索引分配了一個(gè)索引 ID,其中:
對(duì)于需要滿(mǎn)足唯一性約束的主鍵或者唯一索引牲芋,按照如下規(guī)則編碼成 (Key, Value) 鍵值對(duì):
Key: tablePrefix{tableID}_indexPrefixSep{indexID}_indexedColumnsValue
Value: RowID
對(duì)于不需要滿(mǎn)足唯一性約束的普通二級(jí)索引撩笆,按照如下規(guī)則編碼成 (Key, Value) 鍵值對(duì):
Key: tablePrefix{TableID}_indexPrefixSep{IndexID}_indexedColumnsValue_{RowID}
Value: null
2.2 元數(shù)據(jù)
另外存儲(chǔ)于某個(gè)key中,將元信息編碼后存儲(chǔ)
2.3 SQL 層簡(jiǎn)介
TiDB 的 SQL層缸浦,即tidb-server夕冲,負(fù)責(zé)將 SQL 翻譯成 KV 操作,轉(zhuǎn)發(fā)給共享的分布式 KV 存儲(chǔ)層 TiKV裂逐,并組裝返回結(jié)果歹鱼,最終返回查詢(xún)結(jié)果。
舉例:select count(*) from user where name='test'
卜高,像這樣一句語(yǔ)句弥姻,如果將數(shù)據(jù)返回到tiDB進(jìn)行過(guò)濾、計(jì)數(shù)會(huì)浪費(fèi)網(wǎng)絡(luò)IO和無(wú)意義計(jì)算掺涛⊥ザ兀可以將這類(lèi)操作下放到tiKV,粗略描述如下圖:
實(shí)際流程較復(fù)雜:
用戶(hù)的 SQL 請(qǐng)求會(huì)直接或者通過(guò)Load Balancer發(fā)送到 tidb-server薪缆,tidb-server 會(huì)解析MySQL Protocol Packet秧廉,獲取請(qǐng)求內(nèi)容,然后做語(yǔ)法解析拣帽、查詢(xún)計(jì)劃制定和優(yōu)化疼电、執(zhí)行查詢(xún)計(jì)劃獲取和處理數(shù)據(jù)。數(shù)據(jù)全部存儲(chǔ)在 TiKV 集群中减拭,所以在這個(gè)過(guò)程中 tidb-server 需要和 TiKV 交互蔽豺,獲取數(shù)據(jù)。最后 tidb-server 需要將查詢(xún)結(jié)果返回給用戶(hù)拧粪。
三修陡、關(guān)于調(diào)度
在這兩個(gè)組件的后面,還有一個(gè)叫做 PD(Placement Driver)的組件既们,雖然不直接和業(yè)務(wù)接觸濒析,但是這個(gè)組件是整個(gè)集群的核心正什,負(fù)責(zé)全局元信息的存儲(chǔ)以及 TiKV 集群負(fù)載均衡調(diào)度啥纸。
3.1 為什么要進(jìn)行調(diào)度
整個(gè)系統(tǒng)是在動(dòng)態(tài)變化,Region 分裂婴氮、節(jié)點(diǎn)加入斯棒、節(jié)點(diǎn)失效盾致、訪(fǎng)問(wèn)熱點(diǎn)變化等情況會(huì)不斷發(fā)生,整個(gè)調(diào)度系統(tǒng)也需要在動(dòng)態(tài)中不斷向最優(yōu)狀態(tài)前進(jìn)荣暮,因此我們需要一個(gè)中心節(jié)點(diǎn)庭惜,來(lái)對(duì)系統(tǒng)的整體狀況進(jìn)行把控和調(diào)整,所以有了 PD 這個(gè)模塊穗酥。
3.2 調(diào)度的需求整理
作為一個(gè)分布式高可用存儲(chǔ)系統(tǒng)护赊,必須滿(mǎn)足:副本數(shù)量不能多也不能少、副本需要分布在不同的機(jī)器上砾跃、新加節(jié)點(diǎn)后可以將其他節(jié)點(diǎn)上的副本遷移過(guò)來(lái)骏啰、節(jié)點(diǎn)下線(xiàn)后需要將數(shù)據(jù)遷移走。
作為一個(gè)良好的分布式系統(tǒng)抽高,需要優(yōu)化:維持整個(gè)集群的 Leader 分布均勻判耕、維持每個(gè)節(jié)點(diǎn)的儲(chǔ)存容量均勻、維持訪(fǎng)問(wèn)熱點(diǎn)分布均勻控制 Balance 的速度翘骂,避免影響在線(xiàn)服務(wù)壁熄;管理節(jié)點(diǎn)狀態(tài),包括手動(dòng)上線(xiàn)/下線(xiàn)節(jié)點(diǎn)碳竟,以及自動(dòng)下線(xiàn)失效節(jié)點(diǎn)草丧。
上述調(diào)度需求看似復(fù)雜,但是整理下來(lái)最終落地的無(wú)非是下面三件事:
- 增加一個(gè) Replica
- 刪除一個(gè) Replica
- 將 Leader 角色在一個(gè) Raft Group 的不同 Replica 之間 transfer瞭亮。
剛好 Raft 協(xié)議能夠滿(mǎn)足這三種需求方仿,通過(guò) AddReplica、RemoveReplica统翩、TransferLeader 這三個(gè)命令仙蚜,可以支撐上述三種基本操作。
3.3 信息收集
- 每個(gè) TiKV 節(jié)點(diǎn)(Store)會(huì)定期向 PD 匯報(bào)節(jié)點(diǎn)的整體信息厂汗。
- 每個(gè) Raft Group 的 Leader 會(huì)定期向 PD 匯報(bào)信息委粉。
3.4 調(diào)度的策略
- 保障一個(gè) Region 的 Replica 數(shù)量正確:在掉節(jié)點(diǎn)或恢復(fù)節(jié)點(diǎn)時(shí),增刪replica
- 保障一個(gè) Raft Group 中的多個(gè) Replica 不在同一個(gè)位置: 位置包括物理機(jī)器娶桦、單個(gè)機(jī)架贾节、單個(gè)機(jī)房≈云瑁可以給節(jié)點(diǎn)配置 lables栗涂,需要在 Replica 分配的時(shí)候盡量保證不會(huì)有一個(gè) Region 的多個(gè) Replica 所在結(jié)點(diǎn)有相同的位置標(biāo)識(shí)。
- 副本在 Store 之間的分布均勻分配:維持每個(gè)節(jié)點(diǎn)上面祈争,副本數(shù)量的均衡斤程,會(huì)使得總體的負(fù)載更均衡。
- Leader 數(shù)量在 Store 之間均勻分配: Raft 協(xié)議要讀取核寫(xiě)入都通過(guò) Leader 進(jìn)行菩混,所以計(jì)算的負(fù)載主要在 Leader 上面忿墅,PD 會(huì)盡可能將 Leader 在節(jié)點(diǎn)間分散開(kāi)扁藕。
- 訪(fǎng)問(wèn)熱點(diǎn)數(shù)量在 Store 之間均勻分配:每個(gè) Store 以及 Region Leader 在上報(bào)信息時(shí)攜帶了當(dāng)前訪(fǎng)問(wèn)負(fù)載的信息,比如 Key 的讀取/寫(xiě)入速度疚脐。PD 會(huì)檢測(cè)出訪(fǎng)問(wèn)熱點(diǎn)亿柑,且將其在節(jié)點(diǎn)之間分散開(kāi)。
- 各個(gè) Store 的存儲(chǔ)空間占用大致相等
- 控制調(diào)度速度棍弄,避免影響在線(xiàn)服務(wù)
3.5 自動(dòng)伸縮
TiDB 借助 TiDB Operator 和 PD 來(lái)實(shí)現(xiàn) Auto-Scale望薄。目前由 TiDB Operator 組件定期獲取 TiDB / TiKV 的 metrics 信息后,通過(guò) API 的方式暴露出期望的 TiDB/TiKV numbers呼畸,然后由 TiDB Operator 定期拉取 PD API 信息后式矫,通過(guò)內(nèi)部的 Auto-scaling 算法對(duì) TidbCluster.Spec.Replicas 進(jìn)行調(diào)整,從而實(shí)現(xiàn)Auto-scaling役耕。
3.6 動(dòng)態(tài)調(diào)度
3.7 根據(jù)負(fù)載動(dòng)態(tài)分裂 ( Load Base Splitting)
3.8 熱點(diǎn)隔離 (Isolate Frequently Access Region)
四采转、TiDB 和 MySQL 的區(qū)別
TiDB 作為開(kāi)源 NewSQL 數(shù)據(jù)庫(kù)的典型代表之一,同樣支持 SQL瞬痘,支持事務(wù) ACID 特性故慈。
在通訊協(xié)議上,TiDB 選擇與 MySQL 完全兼容框全,并盡可能兼容 MySQL 的語(yǔ)法察绷。
因此,基于 MySQL 數(shù)據(jù)庫(kù)開(kāi)發(fā)的系統(tǒng)津辩,大多數(shù)可以平滑遷移至 TiDB,而幾乎不用修改代碼喘沿。對(duì)用戶(hù)來(lái)說(shuō),遷移成本極低蚜印,過(guò)渡自然。
但仍有少量不兼容窄赋。
作者:陀氏
鏈接:http://www.reibang.com/p/1141be233bb2
來(lái)源:簡(jiǎn)書(shū)
著作權(quán)歸作者所有哟冬。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處忆绰。