一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

簡(jiǎn)單了解 TiDB 架構(gòu)

 路小路的日常 2022-04-25

一、前言

之前跟朋友聊天也會(huì)聊到,基于現(xiàn)有的微服務(wù)架構(gòu),絕大多數(shù)的性能瓶頸都不在服務(wù),因?yàn)槲覀兊姆?wù)是可以橫向擴(kuò)展的。

在很多的 case 下,這個(gè)瓶頸就是「數(shù)據(jù)庫(kù)」。例如,我們?yōu)榱藴p輕 MySQL 的負(fù)擔(dān),會(huì)引入消息隊(duì)列來(lái)對(duì)流量進(jìn)行削峰;再例如會(huì)引入 Redis 來(lái)緩存一些不太常變的數(shù)據(jù),來(lái)減少對(duì) MySQL 的請(qǐng)求。

另一方面,如果業(yè)務(wù)往 MySQL 中灌入了海量的數(shù)據(jù),不做優(yōu)化的話,會(huì)影響 MySQL 的性能。而對(duì)于這種情況,就需要進(jìn)行分庫(kù)分表,落地起來(lái)還是較為麻煩的。

聊著聊著,就聊到了分布式數(shù)據(jù)庫(kù)。其對(duì)數(shù)據(jù)的存儲(chǔ)方式就類似于 Redis Cluster 這種,不管你給我灌多少的數(shù)據(jù),理論上我都能夠吞下去。這樣一來(lái)也不用擔(dān)心后期數(shù)據(jù)量大了需要進(jìn)行分庫(kù)分表。

剛好,之前閑逛的時(shí)候看到了 PingCAP 的 TiDB,正好就來(lái)聊一聊。

二、正文

由于是簡(jiǎn)單了解,所以更多的側(cè)重點(diǎn)在存儲(chǔ)

1.TiDB Server

還是從一個(gè)黑盒子講起,在沒(méi)有了解之前,我們對(duì) TiDB 的認(rèn)識(shí)就是,我們往里面丟數(shù)據(jù),TiDB 負(fù)責(zé)存儲(chǔ)數(shù)據(jù)。并且由于是分布式的,所以理論上只要存儲(chǔ)資源夠,多大的數(shù)據(jù)都能夠存下。

我們知道,TiDB 支持 MySQL,或者說(shuō)兼容大多數(shù) MySQL 的語(yǔ)法。那我們就還是拿一個(gè) Insert 語(yǔ)句來(lái)當(dāng)作切入點(diǎn),探索數(shù)據(jù)在 TiDB 中到底是如何存儲(chǔ)的。

首先要執(zhí)行語(yǔ)句,必然要先建立連接。

在 MySQL 中,負(fù)責(zé)處理客戶端連接的是 MySQL Server,在 TiDB 中也有同樣的角色 —— TiDB Server,雖角色類似,但兩者有著很多的不同

TiDB Server 對(duì)外暴露 MySQL 協(xié)議,負(fù)責(zé) SQL 的解析、優(yōu)化,并最終生成分布式執(zhí)行計(jì)劃,MySQL 的 Server 層也會(huì)涉及到 SQL 的解析、優(yōu)化,但與 MySQL 最大的不同在于,TiDB Server 是無(wú)狀態(tài)的。

而 MySQL Server 由于和底層存儲(chǔ)引擎的耦合部署在同一個(gè)節(jié)點(diǎn),并且在內(nèi)存中緩存了頁(yè)的數(shù)據(jù),是有狀態(tài)的。

這里其實(shí)可以簡(jiǎn)單的把兩者理解為,TiDB 是無(wú)狀態(tài)的可橫向擴(kuò)展的服務(wù)。而 MySQL 則是在內(nèi)存中緩存了業(yè)務(wù)數(shù)據(jù)、無(wú)法橫向擴(kuò)展的單體服務(wù)。

而由于 TiDB Server 的無(wú)狀態(tài)特性,在生產(chǎn)中可以啟動(dòng)多個(gè)實(shí)例,并通過(guò)負(fù)載均衡的策略來(lái)對(duì)外提供統(tǒng)一服務(wù)。

實(shí)際情況下,TiDB 的存儲(chǔ)節(jié)點(diǎn)是單獨(dú)、分布式部署的,這里只是為了方便理解 TiDB Server 的橫向擴(kuò)展特性,不用糾結(jié),后面會(huì)聊到存儲(chǔ)

總結(jié)下來(lái),TiDB Server 只干一件事:負(fù)責(zé)解析 SQL,將實(shí)際的數(shù)據(jù)操作轉(zhuǎn)發(fā)給存儲(chǔ)節(jié)點(diǎn)。

2.TiKV

我們知道,對(duì)于 MySQL,其存儲(chǔ)引擎(絕大多數(shù)情況)是 InnoDB,其存儲(chǔ)采用的數(shù)據(jù)結(jié)構(gòu)是 B+ 樹(shù),最終以 .ibd 文件的形式存儲(chǔ)在磁盤上。那 TiDB 呢?

TiDB 的存儲(chǔ)是由 TiKV 來(lái)負(fù)責(zé)的,這是一個(gè)分布式、支持事務(wù)的 KV 存儲(chǔ)引擎。說(shuō)到底,它就是個(gè) KV 存儲(chǔ)引擎。

用大白話說(shuō),這就是個(gè)巨大的、有序的 Map。但說(shuō)到 KV 存儲(chǔ),很多人可能會(huì)聯(lián)想到 Redis,數(shù)據(jù)大多數(shù)時(shí)候是放在內(nèi)存,就算是 Redis,也會(huì)有像 RDB 和 AOF 這樣的持久化方式。那 TiKV 作為一個(gè)分布式的數(shù)據(jù)庫(kù),也不例外。它采用 RocksDB 引擎來(lái)實(shí)現(xiàn)持久化,具體的數(shù)據(jù)落地由其全權(quán)負(fù)責(zé)。

RocksDB 是由 Facebook 開(kāi)源的、用 C++ 實(shí)現(xiàn)的單機(jī) KV 存儲(chǔ)引擎。

3.索引數(shù)據(jù)

直接拿官網(wǎng)的例子給大家看看,話說(shuō) TiDB 中有這樣的一張表:

然后表里有三行數(shù)據(jù):

這三行數(shù)據(jù),每一行都會(huì)被映射成為一個(gè)鍵值對(duì):

其中,Key 中的 t10 代表 ID 為 10 的表,r1 代表 RowID 為 1 的行,由于我們建表時(shí)制定了主鍵,所以 RowID 就為主鍵的值。Value 就是該行除了主鍵之外的其他字段的值,上圖表示的就是主鍵索引。

那如果是非聚簇索引(二級(jí)索引)呢?就比如索引 idxAge,建表語(yǔ)句里對(duì) Age 這一列建立了二級(jí)索引:

i1 代表 ID 為 1 的索引,即當(dāng)前這個(gè)二級(jí)索引,10、20、30 則是索引列 Age 的值,最后的 1、2、3 則是對(duì)應(yīng)的行的主鍵 ID。從建索引的語(yǔ)句部分可以看出來(lái),idxAge 是個(gè)普通的二級(jí)索引,不是唯一索引。所以索引中允許存在多個(gè) Age 為 30 的列。

但如果我們是唯一索引呢?

只拿表 ID、索引 ID 和索引值來(lái)組成 Key,這樣一來(lái)如果再次插入 Age 為 30 的數(shù)據(jù),TiKV 就會(huì)發(fā)現(xiàn)該 Key 已經(jīng)存在了,就能做到唯一鍵檢測(cè)。

4.存儲(chǔ)細(xì)節(jié)

知道了列數(shù)據(jù)是如何映射成 Map 的,我們就可以繼續(xù)了解存儲(chǔ)相關(guān)的細(xì)節(jié)了。

從圖中,我們可以看出個(gè)問(wèn)題:如果某個(gè) TiKV 節(jié)點(diǎn)掛了,那么該節(jié)點(diǎn)上的所有數(shù)據(jù)是不是都沒(méi)了?

當(dāng)然不是的,TiDB 可以是一款金融級(jí)高可用的分布式關(guān)系型數(shù)據(jù)庫(kù),怎么可能會(huì)讓這種事發(fā)生。

TiKV 在存儲(chǔ)數(shù)據(jù)時(shí),會(huì)將同一份數(shù)據(jù)想辦法存儲(chǔ)到多個(gè) TiKV 節(jié)點(diǎn)上,并且使用 Raft 協(xié)議來(lái)保證同一份數(shù)據(jù)在多個(gè) TiKV 節(jié)點(diǎn)上的數(shù)據(jù)一致性。

上圖為了方便理解,進(jìn)行了簡(jiǎn)化。實(shí)際上一個(gè) TiKV 中有存在 2 個(gè) RocksDB。一個(gè)用于存儲(chǔ) Raft Log,通常叫 RaftDB,而另一個(gè)用于存儲(chǔ)用戶數(shù)據(jù),通常叫 KVDB。

簡(jiǎn)單來(lái)說(shuō),就是會(huì)選擇其中一份數(shù)據(jù)作為 Leader 對(duì)外提供讀、寫服務(wù),其余的作為 Follower 僅僅只同步 Leader 的數(shù)據(jù)。當(dāng) Leader 掛掉之后,可以自動(dòng)的進(jìn)行故障轉(zhuǎn)移,從 Follower 中重新選舉新的 Leader 出來(lái)。

看到這,是不是覺(jué)得跟 Kafka 有那么點(diǎn)神似了。Kafka 中一個(gè) Topic 是邏輯概念,實(shí)際上會(huì)分成多個(gè) Partition,分散到多個(gè) Broker 上,并且會(huì)選舉一個(gè) Leader Partition 對(duì)外提供服務(wù),當(dāng) Leader Partition 出現(xiàn)故障時(shí),會(huì)從 Follower Partiiton 中重新再選舉一個(gè) Leader 出來(lái)。

那么,Kafka 中選舉、提供服務(wù)的單位是 Partition,TiDB 中的是什么呢?

5.Region

答案是 Region。剛剛講過(guò),TiKV 可以理解為一個(gè)巨大的 Map,而 Map 中某一段連續(xù)的 Key 就是一個(gè) Region。不同的 Region 會(huì)保存在不同的 TiKV 上。

一個(gè) Region 有多個(gè)副本,每個(gè)副本也叫 Replica,多個(gè) Replica 組成了一個(gè) Raft Group。按照上面介紹的邏輯,某個(gè) Replica 會(huì)被選作 Leader,其余 Replica 作為 Follower。

并且,在數(shù)據(jù)寫入時(shí),TiDB 會(huì)盡量保證 Region 不會(huì)超過(guò)一定的大小,目前這個(gè)值是 96M。當(dāng)然,還是可能會(huì)超過(guò)這個(gè)大小限制。

每個(gè) Region 都可以用 [startKey, endKey) 這樣一個(gè)左閉右開(kāi)的區(qū)間來(lái)表示。

但不可能讓它無(wú)限增長(zhǎng)是吧?所以 TiDB 做了一個(gè)最大值的限制,當(dāng) Region 的大小超過(guò)144M(默認(rèn)) 后,TiKV 會(huì)將其分裂成兩個(gè)或更多個(gè) Region,以保證數(shù)據(jù)在各個(gè) Region 中的均勻分布;同理,當(dāng)某個(gè) Region 由于短時(shí)間刪除了大量的數(shù)據(jù)之后,會(huì)變的比其他 Region 小很多,TiKV 會(huì)將比較小的兩個(gè)相鄰的 Region 合并

大致的存儲(chǔ)機(jī)制、高可用機(jī)制上面已經(jīng)簡(jiǎn)單介紹了。

但其實(shí)上面還遺留一了比較大的問(wèn)題。大家可以結(jié)合上面的圖思考,一條查詢語(yǔ)句過(guò)來(lái),TiDB Server 解析了之后,它是怎么知道自己要找的數(shù)據(jù)在哪個(gè) Region 里?這個(gè) Region 又在哪個(gè) TiKV 上?

難道要遍歷所有的 TiKV 節(jié)點(diǎn)?用腳想想都不可能這么完。剛剛講到多副本,除了要知道提供讀、寫服務(wù)的 Leader Replica 所在的 TiKV,還需要知道其余的 Follower Replica 都分別在哪個(gè)實(shí)例等等。

6.PD

這就需要引入 PD 了,有了 PD 「存儲(chǔ)相關(guān)的細(xì)節(jié)」那幅圖就會(huì)變成這樣:

PD 是個(gè)啥?其全名叫 Placement Driver,用于管理整個(gè)集群的元數(shù)據(jù),你可以把它當(dāng)成是整個(gè)集群的控制節(jié)點(diǎn)也行。PD 集群本身也支持高可用,至少由 3 個(gè)節(jié)點(diǎn)組成。舉個(gè)對(duì)等的例子應(yīng)該就好理解了,你可以把 PD 大概理解成 Zookeeper,或者 RocketMQ 里的 NameServer。Zookeeper 不必多說(shuō),NameServer 是負(fù)責(zé)管理整個(gè) RocketMQ 集群的元數(shù)據(jù)的組件。

擔(dān)心大家杠,所以特意把大概兩個(gè)字加粗了。因?yàn)?PD 不僅僅負(fù)責(zé)元數(shù)據(jù)管理,還擔(dān)任根據(jù)數(shù)據(jù)分布狀態(tài)進(jìn)行合理調(diào)度的工作。

這個(gè)根據(jù)數(shù)據(jù)狀態(tài)進(jìn)行調(diào)度,具體是指啥呢?

7.調(diào)度

舉個(gè)例子,假設(shè)每個(gè) Raft Group 需要始終保持 3 個(gè)副本,那么當(dāng)某個(gè) Raft Group 的 Replica 由于網(wǎng)絡(luò)、機(jī)器實(shí)例等原因不可用了,Replica 數(shù)量下降到了 1 個(gè),此時(shí) PD 檢測(cè)到了就會(huì)進(jìn)行調(diào)度,選擇適當(dāng)?shù)臋C(jī)器補(bǔ)充 Replica;Replica 補(bǔ)充完后,掉線的又恢復(fù)了就會(huì)導(dǎo)致 Raft Group 數(shù)量多于預(yù)期,此時(shí) PD 會(huì)合理的刪除掉多余的副本。

一句話概括上面描述的特性:PD 會(huì)讓任何時(shí)候集群內(nèi)的 Raft Group 副本數(shù)量保持預(yù)期值

這個(gè)可以參考 Kubernetes 里的 Replica Set 概念,我理解是很類似的。

或者,當(dāng) TiDB 集群進(jìn)行存儲(chǔ)擴(kuò)容,向存儲(chǔ)集群新增 TiKV 節(jié)點(diǎn)時(shí),PD 會(huì)將其他 TiKV 節(jié)點(diǎn)上的 Region 遷移到新增的節(jié)點(diǎn)上來(lái)。

或者,Leader Replica 掛了,PD 會(huì)從 Raft Group 的 Replica 中選舉出一個(gè)新的 Leader。

再比如,熱點(diǎn) Region 的情況,并不是所有的 Region 都會(huì)被頻繁的訪問(wèn)到,PD 就需要對(duì)這些熱點(diǎn) Region 進(jìn)行負(fù)載均衡的調(diào)度。

總結(jié)一下 PD 的調(diào)度行為會(huì)發(fā)現(xiàn),就 3 個(gè)操作:

  1. 增加一個(gè) Replica

  2. 刪除一個(gè) Replica

  3. 將 Leader 角色在一個(gè) Raft Group 的不同副本之間遷移

了解完了調(diào)度的操作,我們?cè)僬w的理解一下調(diào)度的需求,這點(diǎn) TiDB 的官網(wǎng)有很好的總結(jié),我把它們整理成腦圖供大家參考:

大多數(shù)點(diǎn)都還好,只是可能會(huì)對(duì)「控制負(fù)載均衡的速度」有點(diǎn)問(wèn)題。因?yàn)?TiDB 集群在進(jìn)行負(fù)載均衡時(shí),會(huì)進(jìn)行 Region 的遷移,可以理解為跟 Redis 的 Rehash 比較耗時(shí)是類似的問(wèn)題,可能會(huì)影響線上的服務(wù)。

8.心跳

PD 而要做到調(diào)度這些決策,必然需要掌控整個(gè)集群的相關(guān)數(shù)據(jù),比如現(xiàn)在有多少個(gè) TiKV?多少個(gè) Raft Group?每個(gè) Raft Group 的 Leader 在哪里等等,這些其實(shí)都是通過(guò)心跳機(jī)制來(lái)收集的。

在 NameServer 中,所有的 RocketMQ Broker 都會(huì)將自己注冊(cè)到 NameServer 中,并且定時(shí)發(fā)送心跳,Broker 中保存的相關(guān)數(shù)據(jù)也會(huì)隨心跳一起發(fā)送到 NameServer 中,以此來(lái)更新集群的元數(shù)據(jù)。

PD 和 TiKV 也是類似的操作,TiKV 中有兩個(gè)組件會(huì)和 PD 交互,分別是:

  1. Raft Group 的 Leader Replica

  2. TiKV 節(jié)點(diǎn)本身

PD 通過(guò)心跳來(lái)收集數(shù)據(jù),更新維護(hù)整個(gè)集群的元數(shù)據(jù),并且在心跳返回時(shí),將對(duì)應(yīng)的「調(diào)度指令」返回。

值得注意的是,上圖中每個(gè) TiKV 中 Raft 只連了一條線,實(shí)際上一個(gè) TiKV 節(jié)點(diǎn)上可能會(huì)有多個(gè) Raft Group 的 Leader

Store(即 TiKV 節(jié)點(diǎn)本身)心跳會(huì)帶上當(dāng)前節(jié)點(diǎn)存儲(chǔ)的相關(guān)數(shù)據(jù),例如磁盤的使用狀況、Region 的數(shù)量等等。通過(guò)上報(bào)的數(shù)據(jù),PD 會(huì)維護(hù)、更新 TiKV 的狀態(tài),PD 用 5 種狀態(tài)來(lái)標(biāo)識(shí) TiKV 的存儲(chǔ),分別是:

  1. Up:這個(gè)懂的都懂,不懂的解釋了也不懂(手動(dòng) doge)

  2. Disconnect:超過(guò) 20 秒沒(méi)有心跳,就會(huì)變成該狀態(tài)

  3. Down:Disconnect 了 max-store-down-time 的值之后,就會(huì)變成 Down,默認(rèn) 30 分鐘。此時(shí) PD 會(huì)在其他 Up 的 TiKV 上補(bǔ)足 Down 掉的節(jié)點(diǎn)上的 Region

  4. Offline:通過(guò) PD Control 進(jìn)行手動(dòng)下線操作,該 Store 會(huì)變?yōu)?Offline 狀態(tài)。PD 會(huì)將該節(jié)點(diǎn)上所有的 Region 搬遷到其他 Store 上去。當(dāng)所有的 Region 遷移完成后,就會(huì)變成 Tomstone 狀態(tài)

  5. Tombstone:表示已經(jīng)涼透了,可以安全的清理掉了。

其官網(wǎng)的圖已經(jīng)畫的很好了,就不再重新畫了,以下?tīng)顟B(tài)機(jī)來(lái)源于 TiDB 官網(wǎng):

image-20220420210115414

Raft Leader 則更多的是上報(bào)當(dāng)前某個(gè) Region 的狀態(tài),比如當(dāng)前 Leader 的位置、Followers Region 的數(shù)量、掉線 Follower 的個(gè)數(shù)、讀寫速度等,這樣 TiDB Server 層在解析的時(shí)候才知道對(duì)應(yīng)的 Leader Region 的位置。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    日韩一级一片内射视频4k| 国产成人一区二区三区久久| 激情三级在线观看视频| 国产黑人一区二区三区| 国产亚洲成av人在线观看| 欧美日韩国产的另类视频| 久久亚洲午夜精品毛片| 成人精品欧美一级乱黄| 久久中文字幕中文字幕中文| 国产高清在线不卡一区| 欧美尤物在线观看西比尔| 日韩欧美精品一区二区三区| 色哟哟哟在线观看视频| 久久经典一区二区三区| 亚洲一区二区三区三区| 国产又爽又猛又粗又色对黄| 日韩精品免费一区二区三区| 久久热这里只有精品视频 | 我要看日本黄色小视频| 欧美国产精品区一区二区三区| 免费大片黄在线观看国语| 不卡一区二区在线视频| 不卡中文字幕在线免费看| 国产一区一一一区麻豆| 国产又粗又猛又爽色噜噜| 午夜久久精品福利视频| 殴美女美女大码性淫生活在线播放 | 国产又粗又深又猛又爽又黄| 夫妻性生活黄色录像视频| 日韩成人高清免费在线| 人妻久久这里只有精品| 嫩草国产福利视频一区二区| 成年午夜在线免费视频| 免费在线成人激情视频| 免费播放一区二区三区四区| 九九热这里只有精品哦| 青青操成人免费在线视频| 观看日韩精品在线视频| 99久久精品一区二区国产| 国产av天堂一区二区三区粉嫩| 大伊香蕉一区二区三区|