溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

tidb是不是go語言

發(fā)布時間:2022-12-03 09:32:45 來源:億速云 閱讀:108 作者:iii 欄目:編程語言

本篇內(nèi)容介紹了“tidb是不是go語言”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

是,TiDB采用go語言編寫。TiDB是一個分布式NewSQL數(shù)據(jù)庫;它支持水平彈性擴展、ACID事務、標準SQL、MySQL語法和MySQL協(xié)議,具有數(shù)據(jù)強一致的高可用特性。TiDB架構中的PD儲存了集群的元信息,如key在哪個TiKV節(jié)點;PD還負責集群的負載均衡以及數(shù)據(jù)分片等。PD通過內(nèi)嵌etcd來支持數(shù)據(jù)分布和容錯;PD采用go語言編寫。

Go 語言不少重量級項目,而國內(nèi)最牛逼的 Go 開源項目應該就是 TiDB 了吧。TiDB 是一個分布式數(shù)據(jù)庫,很多人可能對此一無所知。今天就跟大家聊聊這個話題。

TiDB設計簡單,官網(wǎng)和代碼都非常易讀,是學習分布式數(shù)據(jù)庫的首選開源項目。

數(shù)據(jù)庫、操作系統(tǒng)和編譯器并稱為三大系統(tǒng),可以說是整個計算機軟件的基石。

很多人用過數(shù)據(jù)庫,但是很少有人實現(xiàn)過一個數(shù)據(jù)庫,特別是實現(xiàn)一個分布式數(shù)據(jù)庫。了解數(shù)據(jù)庫的實現(xiàn)原理和細節(jié),一方面可以提高個人技術,對構建其他系統(tǒng)有幫助,另一方面也有利于用好數(shù)據(jù)庫。

一、TiDB簡介

TiDB是一個分布式 NewSQL 數(shù)據(jù)庫。它支持水平彈性擴展、ACID 事務、標準 SQL、MySQL 語法和 MySQL 協(xié)議,具有數(shù)據(jù)強一致的高可用特性,是一個不僅適合 OLTP 場景還適合 OLAP 場景的混合數(shù)據(jù)庫。

OLTP:On-Line Transaction Processing,聯(lián)機事務處理。
OLAP:On-Line Analytical Processing,聯(lián)機分析處理。

  • 高度兼容 MySQL 5.7

TiDB 高度兼容 MySQL 5.7 協(xié)議、MySQL 5.7 常用的功能及語法。雖然 TiDB 支持 MySQL 語法和協(xié)議,但是 TiDB 是由 PingCAP 團隊完全自主開發(fā)的產(chǎn)品,并非基于MySQL開發(fā)。

MySQL 5.7 生態(tài)中的系統(tǒng)工具 (PHPMyAdmin、Navicat、MySQL Workbench、mysqldump、Mydumper、Myloader)、客戶端等均適用于 TiDB。

TiDB 目前還不支持觸發(fā)器、存儲過程、自定義函數(shù)、外鍵。

  • 易用性

TiDB 使用起來很簡單,可以將 TiDB 集群當成 MySQL 來用,可以將 TiDB 用在任何以 MySQL 作為后臺存儲服務的應用中,并且基本上不需要修改應用代碼,同時可以用大部分流行的 MySQL 管理工具來管理 TiDB。

只要支持 MySQL Client/Driver 的編程語言,都可以直接使用 TiDB。

  • 支持分布式事務

無論是一個地方的幾個節(jié)點,還是跨多個數(shù)據(jù)中心的多個節(jié)點,TiDB 均支持 ACID 分布式事務。

TiDB 事務模型靈感源自 Google Percolator 模型,主體是一個兩階段提交協(xié)議,并進行了一些實用的優(yōu)化。該模型依賴于一個時間戳分配器,為每個事務分配單調(diào)遞增的時間戳,這樣就檢測到事務沖突。在 TiDB 集群中,PD 承擔時間戳分配器的角色。

TiDB不需要像MySQL一樣通過支持XA來滿足跨數(shù)據(jù)庫事務,TiDO的本身的分布式事務模型無論是在性能上還是在穩(wěn)定性上都要比 XA 要高出很多,所以不會也不需要支持 XA。

與傳統(tǒng)的單機數(shù)據(jù)庫相比,TiDB 具有以下優(yōu)勢

  • 純分布式架構,擁有良好的擴展性,支持彈性的擴縮容

  • 支持 SQL,對外暴露 MySQL 的網(wǎng)絡協(xié)議,并兼容大多數(shù) MySQL 的語法,在大多數(shù)場景下可以直接替換 MySQL

  • 默認支持高可用,在少數(shù)副本失效的情況下,數(shù)據(jù)庫本身能夠自動進行數(shù)據(jù)修復和故障轉(zhuǎn)移,對業(yè)務透明

  • 支持 ACID 事務,對于一些有強一致需求的場景友好,例如:銀行轉(zhuǎn)賬

  • 具有豐富的工具鏈生態(tài),覆蓋數(shù)據(jù)遷移、同步、備份等多種場景

簡單來說,TiDB 適合具備下面這些特點的場景

  • 數(shù)據(jù)量大,單機保存不下

  • 不希望做 Sharding 或者懶得做 Sharding

  • 訪問模式上沒有明顯的熱點

  • 需要事務、需要強一致、需要災備

  • 希望 Real-Time HTAP,減少存儲鏈路

五大核心特性

  • 一鍵水平擴容或者縮容

    得益于 TiDB 存儲計算分離的架構的設計,可按需對計算、存儲分別進行在線擴容或者縮容,擴容或者縮容過程中對應用運維人員透明。

  • 金融級高可用

    數(shù)據(jù)采用多副本存儲,數(shù)據(jù)副本通過 Multi-Raft 協(xié)議同步事務日志,多數(shù)派寫入成功事務才能提交,確保數(shù)據(jù)強一致性且少數(shù)副本發(fā)生故障時不影響數(shù)據(jù)的可用性??砂葱枧渲酶北镜乩砦恢?、副本數(shù)量等策略滿足不同容災級別的要求。

  • 實時 HTAP

    提供行存儲引擎 TiKV、列存儲引擎 TiFlash 兩款存儲引擎,TiFlash 通過 Multi-Raft Learner 協(xié)議實時從 TiKV 復制數(shù)據(jù),確保行存儲引擎 TiKV 和列存儲引擎 TiFlash 之間的數(shù)據(jù)強一致。TiKV、TiFlash 可按需部署在不同的機器,解決 HTAP 資源隔離的問題。

  • 云原生的分布式數(shù)據(jù)庫

    專為云而設計的分布式數(shù)據(jù)庫,通過 TiDB Operator 可在公有云、私有云、混合云中實現(xiàn)部署工具化、自動化。

  • 兼容 MySQL 5.7 協(xié)議和 MySQL 生態(tài)

    兼容 MySQL 5.7 協(xié)議、MySQL 常用的功能、MySQL 生態(tài),應用無需或者修改少量代碼即可從 MySQL 遷移到 TiDB。提供豐富的數(shù)據(jù)遷移工具幫助應用便捷完成數(shù)據(jù)遷移。

四大核心應用場景

  • 對數(shù)據(jù)一致性及高可靠、系統(tǒng)高可用、可擴展性、容災要求較高的金融行業(yè)屬性的場景

    眾所周知,金融行業(yè)對數(shù)據(jù)一致性及高可靠、系統(tǒng)高可用、可擴展性、容災要求較高。傳統(tǒng)的解決方案是同城兩個機房提供服務、異地一個機房提供數(shù)據(jù)容災能力但不提供服務,此解決方案存在以下缺點:資源利用率低、維護成本高、RTO (Recovery Time Objective)RPO (Recovery Point Objective) 無法真實達到企業(yè)所期望的值。TiDB 采用多副本 + Multi-Raft 協(xié)議的方式將數(shù)據(jù)調(diào)度到不同的機房、機架、機器,當部分機器出現(xiàn)故障時系統(tǒng)可自動進行切換,確保系統(tǒng)的 RTO <= 30s 及 RPO = 0。

  • 對存儲容量、可擴展性、并發(fā)要求較高的海量數(shù)據(jù)及高并發(fā)的 OLTP 場景

    隨著業(yè)務的高速發(fā)展,數(shù)據(jù)呈現(xiàn)爆炸性的增長,傳統(tǒng)的單機數(shù)據(jù)庫無法滿足因數(shù)據(jù)爆炸性的增長對數(shù)據(jù)庫的容量要求,可行方案是采用分庫分表的中間件產(chǎn)品或者 NewSQL 數(shù)據(jù)庫替代、采用高端的存儲設備等,其中性價比最大的是 NewSQL 數(shù)據(jù)庫,例如:TiDB。TiDB 采用計算、存儲分離的架構,可對計算、存儲分別進行擴容和縮容,計算最大支持 512 節(jié)點,每個節(jié)點最大支持 1000 并發(fā),集群容量最大支持 PB 級別。

  • Real-time HTAP 場景

    隨著 5G、物聯(lián)網(wǎng)、人工智能的高速發(fā)展,企業(yè)所生產(chǎn)的數(shù)據(jù)會越來越多,其規(guī)模可能達到數(shù)百 TB 甚至 PB 級別,傳統(tǒng)的解決方案是通過 OLTP 型數(shù)據(jù)庫處理在線聯(lián)機交易業(yè)務,通過 ETL 工具將數(shù)據(jù)同步到 OLAP 型數(shù)據(jù)庫進行數(shù)據(jù)分析,這種處理方案存在存儲成本高、實時性差等多方面的問題。TiDB 在 4.0 版本中引入列存儲引擎 TiFlash 結(jié)合行存儲引擎 TiKV 構建真正的 HTAP 數(shù)據(jù)庫,在增加少量存儲成本的情況下,可以在同一個系統(tǒng)中做聯(lián)機交易處理、實時數(shù)據(jù)分析,極大地節(jié)省企業(yè)的成本。

  • 數(shù)據(jù)匯聚、二次加工處理的場景

    當前絕大部分企業(yè)的業(yè)務數(shù)據(jù)都分散在不同的系統(tǒng)中,沒有一個統(tǒng)一的匯總,隨著業(yè)務的發(fā)展,企業(yè)的決策層需要了解整個公司的業(yè)務狀況以便及時做出決策,故需要將分散在各個系統(tǒng)的數(shù)據(jù)匯聚在同一個系統(tǒng)并進行二次加工處理生成 T+0 或 T+1 的報表。傳統(tǒng)常見的解決方案是采用 ETL + Hadoop 來完成,但 Hadoop 體系太復雜,運維、存儲成本太高無法滿足用戶的需求。與 Hadoop 相比,TiDB 就簡單得多,業(yè)務通過 ETL 工具或者 TiDB 的同步工具將數(shù)據(jù)同步到 TiDB,在 TiDB 中可通過 SQL 直接生成報表。

二、快速上手

TiDB 是一個分布式系統(tǒng)。最基礎的 TiDB 測試集群通常由 2 個 TiDB 實例、3 個 TiKV 實例、3 個 PD 實例和可選的 TiFlash 實例構成。通過 TiUP Playground,可以快速搭建出上述的一套基礎測試集群,步驟如下:

  • step1、下載并安裝 TiUP。


    curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh


安裝完成后顯示:

Successfully set mirror to https://tiup-mirrors.pingcap.com
Detected shell: bash
Shell profile:  /home/user/.bashrc
/home/user/.bashrc has been modified to add tiup to PATH
open a new terminal or source /home/user/.bashrc to use it
Installed path: /home/user/.tiup/bin/tiup
===============================================
Have a try:     tiup playground
===============================================

  • step2、聲明全局環(huán)境變量。 source ${your_shell_profile}


    source /home/user/.bashrc


  • step3、在當前 session 執(zhí)行以下命令啟動集群。


    tiup playground


  • step4、驗證。【現(xiàn)在可以像使用MySQL一樣使用TiDB啦


    #新開啟一個 session 以訪問 TiDB 數(shù)據(jù)庫。
    #使用 TiUP client 連接 TiDB:
    tiup client
    #也可使用 MySQL 客戶端連接 TiDB
    mysql --host 127.0.0.1 --port 4000 -u root
    #通過 http://127.0.0.1:9090 訪問 TiDB 的 Prometheus 管理界面。
    #通過 http://127.0.0.1:2379/dashboard 訪問 TiDB Dashboard 頁面,默認用戶名為 root,密碼為空。
    #通過 http://127.0.0.1:3000 訪問 TiDB 的 Grafana 界面,默認用戶名和密碼都為 admin。


三、TiDB架構原理

在內(nèi)核設計上,TiDB 分布式數(shù)據(jù)庫將整體架構拆分成了多個模塊,各模塊之間互相通信,組成完整的 TiDB 系統(tǒng)。對應的架構圖如下:

tidb是不是go語言

  • TiDB Server 負責處理SQL相關的邏輯,將SQL語句轉(zhuǎn)成key,通過PD來查找數(shù)據(jù)具體在哪個TiKV。TiDB本身是無狀態(tài)的,不存儲數(shù)據(jù),只負責計算。TiDB采用go語言編寫?!鞠嚓P推薦:Go視頻教程】

  • PD

    PD儲存了集群的元信息,如key在哪個 TiKV 節(jié)點;PD還負責集群的負載均衡以及數(shù)據(jù)分片等。PD通過內(nèi)嵌etcd來支持數(shù)據(jù)分布和容錯。PD采用go語言編寫。

  • TiKV Server

    TiKV 是一個分布式的提供事務的 Key-Value 存儲引擎,基于Google Spanner, HBase 設計,但脫離了底層較為復雜的HDFS。通過RocksDB將key-value值存在本地地盤,使用 Raft 協(xié)議做復制,保持數(shù)據(jù)的一致性和容災。TiKV采用Rust語言編寫。

tidb是不是go語言

1、TiDB數(shù)據(jù)庫的存儲——TiKV Server

TiDB存儲模型,一個分布式帶事務的 KV 引擎【一個全局有序的分布式 Key-Value 引擎 】 的分層結(jié)構以及如何實現(xiàn)多副本容錯。

存儲節(jié)點TiKV Server:負責存儲數(shù)據(jù),從外部看 TiKV 是一個分布式的提供事務的 Key-Value 存儲引擎。存儲數(shù)據(jù)的基本單位是 Region,每個 Region 負責存儲一個 Key Range(從 StartKey 到 EndKey 的左閉右開區(qū)間)的數(shù)據(jù),每個 TiKV 節(jié)點會負責多個 Region。TiKV 的 API 在 KV 鍵值對層面提供對分布式事務的原生支持,默認提供了 SI (Snapshot Isolation) 的隔離級別,這也是 TiDB 在 SQL 層面支持分布式事務的核心。TiDB 的 SQL 層做完 SQL 解析后,會將 SQL 的執(zhí)行計劃轉(zhuǎn)換為對 TiKV API 的實際調(diào)用。所以,數(shù)據(jù)都存儲在 TiKV 中。另外,TiKV 中的數(shù)據(jù)都會自動維護多副本(默認為三副本),天然支持高可用和自動故障轉(zhuǎn)移。

TiFlash:TiFlash 是一類特殊的存儲節(jié)點。和普通 TiKV 節(jié)點不一樣的是,在 TiFlash 內(nèi)部,數(shù)據(jù)是以列式的形式進行存儲,主要的功能是為分析型的場景加速。

TiKV

保存數(shù)據(jù)需要保證:數(shù)據(jù)不丟、數(shù)據(jù)不錯→Raft協(xié)議。除此之外,還需要考慮以下問題:

1、能否支持跨數(shù)據(jù)中心的容災?
2、寫入速度是否夠快?
3、數(shù)據(jù)保存下來后,是否方便讀???
4、保存的數(shù)據(jù)如何修改?如何支持并發(fā)的修改?
5、如何原子地修改多條記錄?

TiKV項目很好的解決了以上問題。那么如何實現(xiàn) TiKV 這樣一個高性能高可靠性的巨大的(分布式的) Map?

  • TiKV是一個巨大的 Map,也就是存儲的是 Key-Value pair。

  • 這個 Map 中的 Key-Value pair 按照 Key 的二進制順序有序,也就是我們可以 Seek 到某一個 Key 的位置,然后不斷的調(diào)用 Next 方法以遞增的順序獲取比這個 Key 大的 Key-Value。

Raft和RocksDB

TiKV 利用 Raft 來做數(shù)據(jù)復制,每個數(shù)據(jù)變更都會落地為一條 Raft 日志,通過 Raft 的日志復制功能,將數(shù)據(jù)安全可靠地同步到 Group 的多數(shù)節(jié)點中。

TiKV 沒有選擇直接向磁盤上寫數(shù)據(jù),而是把數(shù)據(jù)保存在 RocksDB 中,具體的數(shù)據(jù)落地由 RocksDB 負責?!綬ocksDB 是一個非常優(yōu)秀的開源的單機存儲引擎?!?/p>

tidb是不是go語言

通過使用 Raft 一致性算法,數(shù)據(jù)在各 TiKV 節(jié)點間復制為多副本,以確保某個節(jié)點掛掉時數(shù)據(jù)的安全性。

實際上在底層,TiKV 使用復制日志 + 狀態(tài)機 (State Machine) 的模型來復制數(shù)據(jù)。對于寫入請求,數(shù)據(jù)被寫入 Leader,然后 Leader 以日志的形式將命令復制到它的 Follower 中。當集群中的大多數(shù)節(jié)點收到此日志時,日志會被提交,狀態(tài)機會相應作出變更。

Region概念

對于一個 KV 系統(tǒng),將數(shù)據(jù)分散在多臺機器上有兩種比較典型的方案:一種是按照 Key 做 Hash,根據(jù) Hash 值選擇對應的存儲節(jié)點;另一種是分 Range,某一段連續(xù)的 Key 都保存在一個存儲節(jié)點上。為了支持范圍查詢,TiKV 選擇了第二種方式,將整個 Key-Value 空間分成很多段,每一段是一系列連續(xù)的 Key,我們將每一段叫做一個 Region,并且我們會盡量保持每個 Region 中保存的數(shù)據(jù)不超過一定的大?。ㄟ@個大小可以配置,目前默認是 96Mb)。每一個 Region 都可以用 StartKey 到 EndKey 這樣一個左閉右開區(qū)間來描述。

tidb是不是go語言

將數(shù)據(jù)劃分成 Region 后,會做 兩件重要的事情

  • 以 Region 為單位,將數(shù)據(jù)分散在集群中所有的節(jié)點上,并且盡量保證每個節(jié)點上服務的 Region 數(shù)量差不多。

    數(shù)據(jù)按照 Key 切分成很多 Region,每個 Region 的數(shù)據(jù)只會保存在一個節(jié)點上面。我們的系統(tǒng)會有一個組件【PD】來負責將 Region 盡可能均勻的散布在集群中所有的節(jié)點上,這樣一方面實現(xiàn)了存儲容量的水平擴展(增加新的節(jié)點后,會自動將其他節(jié)點上的 Region 調(diào)度過來),另一方面也實現(xiàn)了負載均衡(不會出現(xiàn)某個節(jié)點有很多數(shù)據(jù),其他節(jié)點上沒什么數(shù)據(jù)的情況)。同時為了保證上層客戶端能夠訪問所需要的數(shù)據(jù),系統(tǒng)中也會由組件【PD】記錄 Region 在節(jié)點上面的分布情況,也就是通過任意一個 Key 就能查詢到這個 Key 在哪個 Region 中,以及這個 Region 目前在哪個節(jié)點上。

  • 以 Region 為單位做 Raft 的復制和成員管理。

    TiKV 是以 Region 為單位做數(shù)據(jù)的復制,也就是一個 Region 的數(shù)據(jù)會保存多個副本,將每一個副本叫做一個 Replica。Replica 之間是通過 Raft 來保持數(shù)據(jù)的一致(終于提到了 Raft),一個 Region 的多個 Replica 會保存在不同的節(jié)點上,構成一個 Raft Group。其中一個 Replica 會作為這個 Group 的 Leader,其它的 Replica 作為 Follower。所有的讀和寫都是通過 Leader 進行,再由 Leader 復制給 Follower。

    理解了 Region 之后,應該可以理解下面這張圖:

tidb是不是go語言

以 Region 為單位做數(shù)據(jù)的分散和復制,就有了一個分布式的具備一定容災能力的 KeyValue 系統(tǒng),不用再擔心數(shù)據(jù)存不下,或者是磁盤故障丟失數(shù)據(jù)的問題。

MVCC

如果兩個 Client 同時去修改一個 Key 的 Value,如果沒有 MVCC,就需要對數(shù)據(jù)上鎖,在分布式場景下,可能會帶來性能以及死鎖問題。 TiKV 的 MVCC 實現(xiàn)是通過在 Key 后面添加 Version 來實現(xiàn)。

對于同一個 Key 的多個版本,把版本號較大的放在前面,版本號小的放在后面。這樣當用戶通過一個 Key + Version 來獲取 Value 的時候,可以將 Key 和 Version 構造出 MVCC 的 Key,也就是 Key-Version。然后可以直接 Seek(Key-Version),定位到第一個大于等于這個 Key-Version 的位置。

#簡單來說,沒有 MVCC 之前,可以把 TiKV 看做這樣的
Key1 -> Value
Key2 -> Value
……
KeyN -> Value
#有了 MVCC 之后,TiKV 的 Key 排列是這樣的:
Key1-Version3 -> Value
Key1-Version2 -> Value
Key1-Version1 -> Value
……
Key2-Version4 -> Value
Key2-Version3 -> Value
Key2-Version2 -> Value
Key2-Version1 -> Value
……
KeyN-Version2 -> Value
KeyN-Version1 -> Value
……

GC

TiDB 的事務的實現(xiàn)采用了 MVCC(多版本并發(fā)控制)機制,當新寫入的數(shù)據(jù)覆蓋舊的數(shù)據(jù)時,舊的數(shù)據(jù)不會被替換掉,而是與新寫入的數(shù)據(jù)同時保留,并以時間戳來區(qū)分版本。Garbage Collection (GC) 的任務便是清理不再需要的舊數(shù)據(jù)。

  • GC整體流程

一個 TiDB 集群中會有一個 TiDB 實例被選舉為 GC leader,GC 的運行由 GC leader 來控制。

GC 會被定期觸發(fā)。每次 GC 時,首先,TiDB 會計算一個稱為 safe point 的時間戳,接下來 TiDB 會在保證 safe point 之后的快照全部擁有正確數(shù)據(jù)的前提下,刪除更早的過期數(shù)據(jù)。每一輪 GC 分為以下三個步驟

step1:“Resolve Locks” 【清理鎖】階段會對所有 Region 掃描 safe point 之前的鎖,并清理這些鎖。

step2:“Delete Ranges” 【刪除區(qū)間】階段快速地刪除由于 DROP TABLE/DROP INDEX 等操作產(chǎn)生的整區(qū)間的廢棄數(shù)據(jù)。

step3:“Do GC”【進行GC清理】階段每個 TiKV 節(jié)點將會各自掃描該節(jié)點上的數(shù)據(jù),并對每一個 key 刪除其不再需要的舊版本。

默認配置下,GC 每 10 分鐘觸發(fā)一次,每次 GC 會保留最近 10 分鐘內(nèi)的數(shù)據(jù)(即默認 GC life time 為 10 分鐘,safe point 的計算方式為當前時間減去 GC life time)。如果一輪 GC 運行時間太久,那么在一輪 GC 完成之前,即使到了下一次觸發(fā) GC 的時間也不會開始下一輪 GC。另外,為了使持續(xù)時間較長的事務能在超過 GC life time 之后仍然可以正常運行,safe point 不會超過正在執(zhí)行中的事務的開始時間 (start_ts)。

2、TiDB數(shù)據(jù)庫的計算——TiDB Server

從 SQL 的角度了解了數(shù)據(jù)是如何存儲,以及如何用于計算。

TiDB 在 TiKV 提供的分布式存儲能力基礎上,構建了兼具優(yōu)異的交易處理能力與良好的數(shù)據(jù)分析能力的計算引擎。

TiDB Server:SQL 解析層,對外暴露 MySQL 協(xié)議的連接 endpoint,負責接受客戶端的連接,執(zhí)行 SQL 解析和優(yōu)化,最終生成分布式執(zhí)行計劃。TiDB 層本身是無狀態(tài)的,實踐中可以啟動多個 TiDB 實例,通過負載均衡組件(如 LVS、HAProxy 或 F5)對外提供統(tǒng)一的接入地址,客戶端的連接可以均勻地分攤在多個 TiDB 實例上以達到負載均衡的效果。TiDB Server 本身并不存儲數(shù)據(jù),只是解析 SQL,將實際的數(shù)據(jù)讀取請求轉(zhuǎn)發(fā)給底層的存儲節(jié)點 TiKV(或 TiFlash)。

SQL映射KV

可以將關系模型簡單理解為 Table 和 SQL 語句,那么問題變?yōu)槿绾卧?KV 結(jié)構上保存 Table 以及如何在 KV 結(jié)構上運行 SQL 語句。 SQL 和 KV 結(jié)構之間存在巨大的區(qū)別,那么如何能夠方便高效地進行映射,就成為一個很重要的問題。一個好的映射方案必須有利于對數(shù)據(jù)操作的需求。

tidb是不是go語言

分布式SQL運算

首先我們需要將計算盡量靠近存儲節(jié)點,以避免大量的 RPC 調(diào)用。其次,我們需要將 Filter 也下推到存儲節(jié)點進行計算,這樣只需要返回有效的行,避免無意義的網(wǎng)絡傳輸。最后,我們可以將聚合函數(shù)、GroupBy 也下推【計算下推】到存儲節(jié)點,進行預聚合,每個節(jié)點只需要返回一個 Count 值即可,再由 tidb-server 將 Count 值 Sum 起來【并行算子】。 這里有一個數(shù)據(jù)逐層返回的示意圖:

tidb是不是go語言

實際上 TiDB 的 SQL 層要復雜的多,模塊以及層次非常多,下面這個圖【SQL引擎架構】列出了重要的模塊以及調(diào)用關系:

tidb是不是go語言

SQL查詢返回的簡要流程:用戶的 SQL 請求會直接或者通過 Load Balancer 發(fā)送到 tidb-server,tidb-server 會解析 MySQL Protocol Packet,獲取請求內(nèi)容,然后做語法解析、查詢計劃制定和優(yōu)化、執(zhí)行查詢計劃獲取和處理數(shù)據(jù)。數(shù)據(jù)全部存儲在 TiKV 集群中,所以在這個過程中 tidb-server 需要和 tikv-server 交互,獲取數(shù)據(jù)。最后 tidb-server 需要將查詢結(jié)果返回給用戶。

SQL執(zhí)行流程

在 TiDB 中,從輸入的查詢文本到最終的執(zhí)行計劃執(zhí)行結(jié)果的過程可以見下圖:

tidb是不是go語言

首先經(jīng)過 parser 對原始查詢文本的解析以及一些簡單的合法性驗證后,TiDB 首先會對查詢做一些邏輯上的等價變化——查詢邏輯優(yōu)化。
通過這些等價變化,使得這個查詢在邏輯執(zhí)行計劃上可以變得更易于處理。在等價變化結(jié)束之后,TiDB 會得到一個與原始查詢等價的查詢計劃結(jié)構,之后根據(jù)數(shù)據(jù)分布、以及一個算子具體的執(zhí)行開銷,來獲得一個最終的執(zhí)行計劃——查詢物理優(yōu)化。
同時,TiDB 在執(zhí)行 PREPARE 語句時,可以選擇開啟緩存來降低 TiDB 生成執(zhí)行計劃的開銷——執(zhí)行計劃緩存

3、TiDB數(shù)據(jù)庫的調(diào)度——PD Server

PD (Placement Driver) 是 TiDB 集群的管理模塊,同時也負責集群數(shù)據(jù)的實時調(diào)度。

調(diào)度場景

PD (Placement Driver) Server:整個 TiDB 集群的元信息管理模塊,負責存儲每個 TiKV 節(jié)點實時的數(shù)據(jù)分布情況和集群的整體拓撲結(jié)構,提供 TiDB Dashboard 管控界面,并為分布式事務分配事務 ID。PD 不僅存儲元信息,同時還會根據(jù) TiKV 節(jié)點實時上報的數(shù)據(jù)分布狀態(tài),下發(fā)數(shù)據(jù)調(diào)度命令給具體的 TiKV 節(jié)點,可以說是整個集群的“大腦”。此外,PD 本身也是由至少 3 個節(jié)點構成,從而提供高可用。建議部署奇數(shù)個 PD 節(jié)點。

調(diào)度需求

第一類:作為一個分布式高可用存儲系統(tǒng),必須滿足的需求,包括幾種:【 容災功能 】

  • 副本數(shù)量不能多也不能少。

  • 副本需要根據(jù)拓撲結(jié)構分布在不同屬性的機器上。

  • 節(jié)點宕機或異常能夠自動合理快速地進行容災。

第二類:作為一個良好的分布式系統(tǒng),需要考慮的地方包括:【資源利用率更高且合理,具備良好的擴展性】

  • 維持整個集群的 Leader 分布均勻。

  • 維持每個節(jié)點的儲存容量均勻。

  • 維持訪問熱點分布均勻。

  • 控制負載均衡的速度,避免影響在線服務。

  • 管理節(jié)點狀態(tài),包括手動上線/下線節(jié)點。

為了滿足這些需求,需要收集足夠的信息,比如每個節(jié)點的狀態(tài)、每個 Raft Group 的信息、業(yè)務訪問操作的統(tǒng)計等;其次需要設置一些策略,PD 根據(jù)這些信息以及調(diào)度的策略,制定出盡量滿足前面所述需求的調(diào)度計劃。

調(diào)度操作

調(diào)度的基本操作指的是為了滿足調(diào)度的策略。上述調(diào)度需求可整理為以下三個操作:

  • 增加一個副本

  • 刪除一個副本

  • 將 Leader 角色在一個 Raft Group 的不同副本之間 transfer(遷移)

剛好 Raft 協(xié)議通過 AddReplicaRemoveReplica、TransferLeader 這三個命令,可以支撐上述三種基本操作。

TiKV Store 的狀態(tài)具體分為 Up,Disconnect,Offline,Down,Tombstone。各狀態(tài)的關系如下:

tidb是不是go語言

調(diào)度策略
  • 一個 Region 的副本數(shù)量正確。

  • 一個 Raft Group 中的多個副本不在同一個位置。

  • 副本在 Store 之間的分布均勻分配。

  • Leader 數(shù)量在 Store 之間均勻分配。

  • 訪問熱點數(shù)量在 Store 之間均勻分配。

  • 各個 Store 的存儲空間占用大致相等。

  • 控制調(diào)度速度,避免影響在線服務。

調(diào)度實現(xiàn)

PD 不斷的通過 Store 【即TiKV節(jié)點】或者 Leader 的心跳包收集信息,獲得整個集群的詳細數(shù)據(jù),并且根據(jù)這些信息以及調(diào)度策略生成調(diào)度操作序列,每次收到 Region Leader 發(fā)來的心跳包時,PD 都會檢查是否有對這個 Region 待進行的操作,通過心跳包的回復消息,將需要進行的操作返回給 Region Leader,并在后面的心跳包中監(jiān)測執(zhí)行結(jié)果。注意這里的操作只是給 Region Leader 的建議,并不保證一定能得到執(zhí)行,具體是否會執(zhí)行以及什么時候執(zhí)行,由 Region Leader 自己根據(jù)當前自身狀態(tài)來定。

五、TiDB最佳實踐

TiDB 的最佳實踐與其實現(xiàn)原理密切相關,建議先了解一些基本的實現(xiàn)機制,包括 Raft、分布式事務、數(shù)據(jù)分片、負載均衡、SQL 到 KV 的映射方案、二級索引的實現(xiàn)方法、分布式執(zhí)行引擎。

Raft

Raft 是一種一致性協(xié)議,能提供強一致的數(shù)據(jù)復制保證,TiDB 最底層用 Raft 來同步數(shù)據(jù)。每次寫入都要寫入多數(shù)副本,才能對外返回成功,這樣即使丟掉少數(shù)副本,也能保證系統(tǒng)中還有最新的數(shù)據(jù)。比如最大 3 副本的話,每次寫入 2 副本才算成功,任何時候,只丟失一個副本的情況下,存活的兩個副本中至少有一個具有最新的數(shù)據(jù)。

相比 Master-Slave 方式的同步,同樣是保存三副本,Raft 的方式更為高效,因為寫入的延遲取決于最快的兩個副本,而不是最慢的那個副本。所以使用 Raft 同步的情況下,異地多活成為可能。在典型的兩地三中心場景下,每次寫入只需要本數(shù)據(jù)中心以及離得近的一個數(shù)據(jù)中心寫入成功就能保證數(shù)據(jù)的一致性,而并不需要三個數(shù)據(jù)中心都寫成功。

分布式事務

TiDB 提供完整的分布式事務,事務模型是在 Google Percolator 的基礎上做了一些優(yōu)化。

  • 樂觀鎖

    TiDB 的樂觀事務模型,只有在真正提交的時候,才會做沖突檢測。如果有沖突,則需要重試。這種模型在沖突嚴重的場景下,會比較低效,因為重試之前的操作都是無效的,需要重復做。舉一個比較極端的例子,就是把數(shù)據(jù)庫當做計數(shù)器用,如果訪問的并發(fā)度比較高,那么一定會有嚴重的沖突,導致大量的重試甚至是超時。但是如果訪問沖突并不十分嚴重,那么樂觀鎖模型具備較高的效率。在沖突嚴重的場景下,推薦使用悲觀鎖,或在系統(tǒng)架構層面解決問題,比如將計數(shù)器放在 Redis 中。

  • 悲觀鎖

    TiDB 的悲觀事務模式,悲觀事務的行為和 MySQL 基本一致,在執(zhí)行階段就會上鎖,先到先得,避免沖突情況下的重試,可以保證有較多沖突的事務的成功率。悲觀鎖同時解決了希望通過 select for update 對數(shù)據(jù)提前鎖定的場景。但如果業(yè)務場景本身沖突較少,樂觀鎖的性能會更有優(yōu)勢。

  • 事務大小限制

    由于分布式事務要做兩階段提交,并且底層還需要做 Raft 復制,如果一個事務非常大,會使得提交過程非常慢,并且會卡住下面的 Raft 復制流程。為了避免系統(tǒng)出現(xiàn)被卡住的情況,我們對事務的大小做了限制【單個事務包含的 SQL 語句不超過 5000 條(默認)】。

數(shù)據(jù)分片

TiKV 自動將底層數(shù)據(jù)按照 Key 的 Range 進行分片。每個 Region 是一個 Key 的范圍,從 StartKeyEndKey 的左閉右開區(qū)間。Region 中的 Key-Value 總量超過一定值,就會自動分裂。這部分對用戶透明。

負載均衡

PD 會根據(jù)整個 TiKV 集群的狀態(tài),對集群的負載進行調(diào)度。調(diào)度是以 Region 為單位,以 PD 配置的策略為調(diào)度邏輯,自動完成。

SQL on KV

TiDB 自動將 SQL 結(jié)構映射為 KV 結(jié)構。簡單來說,TiDB 執(zhí)行了以下操作:

  • 一行數(shù)據(jù)映射為一個 KV,Key 以 TableID 構造前綴,以行 ID 為后綴

  • 一條索引映射為一個 KV,Key 以 TableID+IndexID 構造前綴,以索引值構造后綴

可以看到,對于一個表中的數(shù)據(jù)或者索引,會具有相同的前綴,這樣在 TiKV 的 Key 空間內(nèi),這些 Key-Value 會在相鄰的位置。那么當寫入量很大,并且集中在一個表上面時,就會造成寫入的熱點,特別是連續(xù)寫入的數(shù)據(jù)中某些索引值也是連續(xù)的(比如 update time 這種按時間遞增的字段),會在很少的幾個 Region 上形成寫入熱點,成為整個系統(tǒng)的瓶頸。同樣,如果所有的數(shù)據(jù)讀取操作也都集中在很小的一個范圍內(nèi)(比如在連續(xù)的幾萬或者十幾萬行數(shù)據(jù)上),那么可能造成數(shù)據(jù)的訪問熱點。

二級索引

TiDB 支持完整的二級索引,并且是全局索引,很多查詢可以通過索引來優(yōu)化。如果利用好二級索引,對業(yè)務非常重要,很多 MySQL 上的經(jīng)驗在 TiDB 這里依然適用,不過 TiDB 還有一些自己的特點,需要注意,這一節(jié)主要討論在 TiDB 上使用二級索引的一些注意事項。

  • 二級索引不是越多越好。

  • 對區(qū)分度【基數(shù)】比較大的列建立索引比較合適。有多個查詢條件時,可以選擇組合索引,注意最左前綴原則。

  • 通過索引查詢和直接掃描 Table 的區(qū)別。

  • 查詢并發(fā)度。

    數(shù)據(jù)分散在很多 Region 上,所以 TiDB 在做查詢的時候會并發(fā)進行,默認的并發(fā)度比較保守,因為過高的并發(fā)度會消耗大量的系統(tǒng)資源。

    對于 OLTP 類型的查詢,往往不會涉及到大量的數(shù)據(jù),較低的并發(fā)度已經(jīng)可以滿足需求。
    對于 OLAP 類型的 Query,往往需要較高的并發(fā)度。

    所以 TiDB 支持通過 System Variable 來調(diào)整查詢并發(fā)度?!総idb_distsql_scan_concurrency、tidb_index_lookup_size、tidb_index_lookup_concurrency、tidb_index_serial_scan_concurrency等等】

  • 通過索引保證結(jié)果順序?!舅饕丝梢杂脕磉^濾數(shù)據(jù)之外,還能用來對數(shù)據(jù)排序,首先按照索引的順序獲取行 ID,然后再按照行 ID 的返回順序返回行的內(nèi)容,這樣可以保證返回結(jié)果按照索引列有序?!?/p>

  • 也支持逆序索引?!灸壳八俣缺软樞?Scan 慢一些,通常情況下慢 20%,在數(shù)據(jù)頻繁修改造成版本較多的情況下,會慢的更多。如果可能,建議避免對索引的逆序 Scan】

“tidb是不是go語言”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI