自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

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

一、前言

大家如果看過我之前發(fā)過的文章就知道,我寫過很多篇關(guān)于 MySQL 的文章,從我的 Github 匯總倉庫 中可以看出來:

可能還不是很全,算是對(duì) MySQL 有一個(gè)淺顯但較為全面的理解。之前跟朋友聊天也會(huì)聊到,基于現(xiàn)有的微服務(wù)架構(gòu),絕大多數(shù)的性能瓶頸都不在服務(wù),因?yàn)槲覀兊姆?wù)是可以橫向擴(kuò)展的。

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

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

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

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

二、正文

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

1.TiDB Server

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

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

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

在 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 是無狀態(tài)的。

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

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

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

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

總結(jié)下來,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+ 樹,最終以 .ibd 文件的形式存儲(chǔ)在磁盤上。那 TiDB 呢?

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

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

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

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

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

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

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

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

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

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

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

只拿表 ID、索引 ID 和索引值來組成 Key,這樣一來如果再次插入 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è)問題:如果某個(gè) TiKV 節(jié)點(diǎn)掛了,那么該節(jié)點(diǎn)上的所有數(shù)據(jù)是不是都沒了?

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

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

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

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

看到這,是不是覺得跟 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 出來。

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

5.Region

答案是 Region。剛剛講過,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ì)超過一定的大小,目前這個(gè)值是 96M。當(dāng)然,還是可能會(huì)超過這個(gè)大小限制。

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

但不可能讓它無限增長是吧?所以 TiDB 做了一個(gè)最大值的限制,當(dāng) Region 的大小超過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)簡單介紹了。

但其實(shí)上面還遺留一了比較大的問題。大家可以結(jié)合上面的圖思考,一條查詢語句過來,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 不必多說,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)上來。

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

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

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

  • 增加一個(gè) Replica
  • 刪除一個(gè) Replica
  • 將 Leader 角色在一個(gè) Raft Group 的不同副本之間遷移

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

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

8.心跳

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

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

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

  • Raft Group 的 Leader Replica
  • TiKV 節(jié)點(diǎn)本身

PD 通過心跳來收集數(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ù)量等等。通過上報(bào)的數(shù)據(jù),PD 會(huì)維護(hù)、更新 TiKV 的狀態(tài),PD 用 5 種狀態(tài)來標(biāo)識(shí) TiKV 的存儲(chǔ),分別是:

  • Up:這個(gè)懂的都懂,不懂的解釋了也不懂(手動(dòng) doge)
  • Disconnect:超過 20 秒沒有心跳,就會(huì)變成該狀態(tài)
  • Down:Disconnect 了 max-store-down-time 的值之后,就會(huì)變成 Down,默認(rèn) 30 分鐘。此時(shí) PD 會(huì)在其他 Up 的 TiKV 上補(bǔ)足 Down 掉的節(jié)點(diǎn)上的 Region
  • Offline:通過 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)
  • Tombstone:表示已經(jīng)涼透了,可以安全的清理掉了。

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

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 的位置。

責(zé)任編輯:武曉燕 來源: SH的全棧筆記
相關(guān)推薦

2022-11-11 19:09:13

架構(gòu)

2019-09-18 11:03:01

數(shù)據(jù)存儲(chǔ)數(shù)據(jù)庫

2009-12-17 18:16:44

JRuby語言技術(shù)

2017-06-09 08:00:38

TiDB調(diào)度數(shù)據(jù)庫

2017-06-04 23:58:08

TiDB數(shù)據(jù)庫存儲(chǔ)

2017-06-04 23:57:10

TiDBSQL存儲(chǔ)數(shù)據(jù)

2015-08-26 16:17:49

OpenStack OpenStack 架開源云平臺(tái)

2009-06-24 14:25:13

JSF整體架構(gòu)

2021-05-25 05:25:24

MySQL數(shù)據(jù)庫

2010-05-24 15:18:38

Linux SNMP

2023-06-25 12:10:34

Linux文件權(quán)限

2021-12-08 17:54:55

架構(gòu)控制平面

2019-07-18 17:08:56

物聯(lián)網(wǎng)技術(shù)軟件

2015-02-28 11:36:01

FDD

2021-04-09 06:25:41

區(qū)塊鏈區(qū)塊鏈技術(shù)

2009-09-18 16:00:07

LINQ架構(gòu)

2009-11-04 15:44:39

ADO.NET Sql

2017-11-14 12:56:31

云計(jì)算 Cloud TiDB奧秘

2017-11-15 13:11:03

云計(jì)算Cloud TiDB技術(shù)

2023-08-17 10:12:04

前端整潔架構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)