成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

TiDB 源碼閱讀系列文章(十八)tikv-client(上)

zhjx922 / 2896人閱讀

摘要:獲取所在的是通過向發(fā)送請求完成的。外部調(diào)用的接口,并不需要關(guān)心的細(xì)節(jié),請求都是為了實現(xiàn)接口而發(fā)起的。實現(xiàn)不同的接口需要發(fā)送不同的請求。這種錯誤主要是因為的分裂,當(dāng)內(nèi)的數(shù)據(jù)量增多以后,會分裂成多個新的。

作者:周昱行

在整個 SQL 執(zhí)行過程中,需要經(jīng)過 Parser,Optimizer,Executor,DistSQL 這幾個主要的步驟,最終數(shù)據(jù)的讀寫是通過 tikv-client 與 TiKV 集群通訊來完成的。

為了完成數(shù)據(jù)讀寫的任務(wù),tikv-client 需要解決以下幾個具體問題:

如何定位到某一個 key 或 key range 所在的 TiKV 地址?

如何建立和維護(hù)和 tikv-server 之間的連接?

如何發(fā)送 RPC 請求?

如何處理各種錯誤?

如何實現(xiàn)分布式讀取多個 TiKV 節(jié)點(diǎn)的數(shù)據(jù)?

如何實現(xiàn) 2PC 事務(wù)?

我們接下來就對以上幾個問題逐一解答,其中 5、6 會在下篇中介紹。

如何定位 key 所在的 tikv-server

我們需要回顧一下之前 《三篇文章了解 TiDB 技術(shù)內(nèi)幕——說存儲》 這篇文章中介紹過的一個重要的概念:Region。

TiDB 的數(shù)據(jù)分布是以 Region 為單位的,一個 Region 包含了一個范圍內(nèi)的數(shù)據(jù),通常是 96MB 的大小,Region 的 meta 信息包含了 StartKey 和 EndKey 這兩個屬性。當(dāng)某個 key >= StartKey && key < EndKey 的時候,我們就知道了這個 key 所在的 Region,然后我們就可以通過查找該 Region 所在的 TiKV 地址,去這個地址讀取這個 key 的數(shù)據(jù)。

獲取 key 所在的 Region, 是通過向 PD 發(fā)送請求完成的。PD client 實現(xiàn)了這樣一個接口:

[GetRegion(ctx context.Context, key []byte) (metapb.Region, metapb.Peer, error)](https://github.com/pingcap/ti...

通過調(diào)用這個接口,我們就可以定位這個 key 所在的 Region 了。

如果需要獲取一個范圍內(nèi)的多個 Region,我們會從這個范圍的 StartKey 開始,多次調(diào)用 GetRegion 這個接口,每次返回的 Region 的 EndKey 做為下次請求的 StartKey,直到返回的 Region 的 EndKey 大于請求范圍的 EndKey。

以上執(zhí)行過程有一個很明顯的問題,就是我們每次讀取數(shù)據(jù)的時候,都需要先去訪問 PD,這樣會給 PD 帶來巨大壓力,同時影響請求的性能。

為了解決這個問題,tikv-client 實現(xiàn)了一個 RegionCache 的組件,緩存 Region 信息, 當(dāng)需要定位 key 所在的 Region 的時候,如果 RegionCache 命中,就不需要訪問 PD 了。RegionCache 的內(nèi)部,有兩種數(shù)據(jù)結(jié)構(gòu)保存 Region 信息,一個是 map,另一個是 b-tree,用 map 可以快速根據(jù) region ID 查找到 Region,用 b-tree 可以根據(jù)一個 key 找到包含該 key 的 Region。

嚴(yán)格來說,PD 上保存的 Region 信息,也是一層 cache,真正最新的 Region 信息是存儲在 tikv-server 上的,每個 tikv-server 會自己決定什么時候進(jìn)行 Region 分裂,在 Region 變化的時候,把信息上報給 PD,PD 用上報上來的 Region 信息,滿足 tidb-server 的查詢需求。

當(dāng)我們從 cache 獲取了 Region 信息,并發(fā)送請求以后, tikv-server 會對 Region 信息進(jìn)行校驗,確保請求的 Region 信息是正確的。

如果因為 Region 分裂,Region 遷移導(dǎo)致了 Region 信息變化,請求的 Region 信息就會過期,這時 tikv-server 就會返回 Region 錯誤。遇到了 Region 錯誤,我們就需要清理 RegionCache,重新獲取最新的 Region 信息,并重新發(fā)送請求。

如何建立和維護(hù)和 tikv-server 之間的連接

當(dāng) TiDB 定位到 key 所在的 tikv-server 以后,就需要建立和 TiKV 之間的連接,我們都知道, TCP 連接的建立和關(guān)閉有不小的開銷,同時會增大延遲,使用連接池可以節(jié)省這部分開銷,TiDB 和 tikv-server 之間也維護(hù)了一個連接池 connArray。

TiDB 和 TiKV 之間通過 gRPC 通信,而 gPRC 支持在單 TCP 連接上多路復(fù)用,所以多個并發(fā)的請求可以在單個連接上執(zhí)行而不會相互阻塞。

理論上一個 tidb-server 和一個 tikv-server 之間只需要維護(hù)一個連接,但是在性能測試的時候發(fā)現(xiàn),單個連接在并發(fā)-高的時候,會成為性能瓶頸,所以實際實現(xiàn)的時候,tidb-server 對每一個 tikv-server 地址維護(hù)了多個連接,并以 round-robin 算法選擇連接發(fā)送請求。連接的個數(shù)可以在 config 文件里配置,默認(rèn)是 16。

如何發(fā)送 RPC 請求

tikv-client 通過 tikvStore 這個類型,實現(xiàn) kv.Storage 這個接口,我們可以把 tikvStore 理解成 tikv-client 的一個包裝。外部調(diào)用 kv.Storage 的接口,并不需要關(guān)心 RPC 的細(xì)節(jié),RPC 請求都是 tikvStore 為了實現(xiàn) kv.Storage 接口而發(fā)起的。

實現(xiàn)不同的 kv.Storage 接口需要發(fā)送不同的 RPC 請求。比如實現(xiàn) Snapshot.BatchGet 需要tikvpb.TikvClient.KvBatchGet 方法;實現(xiàn) Transaction.Commit,需要 tikvpb.TikvClient.KvPrewrite, tikvpb.TikvClient.KvCommit 等多個方法。

在 tikvStore 的實現(xiàn)里,并沒有直接調(diào)用 RPC 方法,而是通過一個 Client 接口調(diào)用,做這一層的抽象的主要目的是為了讓下層可以有不同的實現(xiàn)。比如用來測試的 mocktikv 就自己實現(xiàn)了 Client 接口,通過本地調(diào)用實現(xiàn),并不需要調(diào)用真正的 RPC。

rpcClient 是真正實現(xiàn) RPC 請求的 Client 實現(xiàn),通過調(diào)用 tikvrpc.CallRPC,發(fā)送 RPC 請求。tikvrpc.CallRPC 再往下層走,就是調(diào)用具體每個 RPC ?生成的代碼了,到了生成的代碼這一層,就已經(jīng)是 gRPC 框架這一層的內(nèi)容了,我們就不繼續(xù)深入解析了,感興趣的同學(xué)可以研究一下 gRPC 的實現(xiàn)。

如何處理各種錯誤

我們前面提到 RPC 請求都是通過 Client 接口發(fā)送的,但實際上這個接口并沒有直接被各個 tikvStore 的各個方法調(diào)用,而是通過一個 RegionRequestSender 的對象調(diào)用的。

RegionRequestSender 主要的工作除了發(fā)送 RPC 請求,還要負(fù)責(zé)處理各種可以重試的錯誤,比如網(wǎng)絡(luò)錯誤和部分 Region 錯誤。

RPC 請求遇到的錯誤主要分為兩大類:Region 錯誤和網(wǎng)絡(luò)錯誤。

Region ?錯誤 是由 tikv-server 收到請求后,在 response 里返回的,常見的有以下幾種:

NotLeader

這種錯誤的原因通常是 Region 的調(diào)度,PD 為了負(fù)載均衡,可能會把一個熱點(diǎn) Region 的 leader 調(diào)度到空閑的 tikv-server 上,而請求只能由 leader 來處理。遇到這種錯誤就需要 tikv-client 重試,把請求發(fā)給新的 leader。

StaleEpoch

這種錯誤主要是因為 Region 的分裂,當(dāng) Region 內(nèi)的數(shù)據(jù)量增多以后,會分裂成多個新的 Region。新的 Region 包含的 range 是不同的,如果直接執(zhí)行,返回的結(jié)果有可能是錯誤的,所以 TiKV 就會拒絕這個請求。tikv-client 需要從 PD 獲取最新的 Region 信息并重試。

ServerIsBusy

這個錯誤通常是因為 tikv-server 積壓了過多的請求處理不完,tikv-server 如果不拒絕這個請求,隊列會越來越長,可能等到客戶端超時了,請求還沒有來的及處理。所以做為一種保護(hù)機(jī)制,tikv-server 提前返回錯誤,讓客戶端等待一段時間后再重試。

另一類錯誤是網(wǎng)絡(luò)錯誤,錯誤是由 SendRequest 的返回值 返回的 error 的,遇到這種錯誤通常意味著這個 tikv-server 沒有正常返回請求,可能是網(wǎng)絡(luò)隔離或 tikv-server down 了。tikv-client 遇到這種錯誤,會調(diào)用 OnSendFail 方法,處理這個錯誤,會在 RegionCache 里把這個請求失敗的 tikv-server 上的所有 region 都 drop 掉,避免其他請求遇到同樣的錯誤。

當(dāng)遇到可以重試的錯誤的時候,我們需要等待一段時間后重試,我們需要保證每次重試等待時間不能太短也不能太長,太短會造成多次無謂的請求,增加系統(tǒng)壓力和開銷,太長會增加請求的延遲。我們用指數(shù)退避的算法來計算每一次重試前的等待時間,這部分的邏輯是在 Backoffer 里實現(xiàn)的。

在上層執(zhí)行一個 SQL 語句的時候,在 tikv-client 這一層會觸發(fā)多個順序的或并發(fā)的請求,發(fā)向多個 tikv-server,為了保證上層 SQL 語句的超時時間,我們需要考慮的不僅僅是單個 RPC 請求,還需要考慮一個 query 整體的超時時間。

為了解決這個問題,Backoffer 實現(xiàn)了 fork 功能, 在發(fā)送每一個子請求的時候,需要 fork 出一個 child Backofferchild Backoffer 負(fù)責(zé)單個 RPC 請求的重試,它記錄了 parent Backoffer 已經(jīng)等待的時間,保證總的等待時間,不會超過 query 超時時間。

對于不同錯誤,需要等待的時間是不一樣的,每個 Backoffer 在創(chuàng)建時,會根據(jù)不同類型,創(chuàng)建不同的 backoff 函數(shù)。

以上就是 tikv-client 上篇的內(nèi)容,我們在下篇會詳細(xì)介紹實現(xiàn)分布式計算相關(guān)的 copIterator 和實現(xiàn)分布式事務(wù)的 twoPCCommiter。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/17788.html

相關(guān)文章

  • TiDB 源碼閱讀系列文章(十九)tikv-client(下)

    摘要:是什么在介紹的概念之前,我們需要簡單回顧一下前面源碼閱讀系列文章六中講過的和的概念以及它們和語句的關(guān)系。的任務(wù)就是實現(xiàn)請求,執(zhí)行所有涉及到的請求,并依次返回結(jié)果。構(gòu)造出了所有之后,下一步就是執(zhí)行這些了。 上篇文章 中,我們介紹了數(shù)據(jù)讀寫過程中 tikv-client 需要解決的幾個具體問題,本文將繼續(xù)介紹 tikv-client 里的兩個主要的模塊——負(fù)責(zé)處理分布式計算的 copIte...

    whataa 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<