首頁 > 後端開發 > Golang > 主體

tidb是go語言麼

青灯夜游
發布: 2022-12-02 18:24:17
原創
6052 人瀏覽過

是,TiDB採用go語言編寫。 TiDB是一個分散式NewSQL資料庫;它支援水平彈性擴充、ACID事務、標準SQL、MySQL語法和MySQL協議,具有資料強一致的高可用特性。 TiDB架構中的PD儲存了叢集的元訊息,如key在哪個TiKV節點;PD也負責叢集的負載平衡以及資料分片等。 PD透過內嵌etcd來支援資料分佈和容錯;PD採用go語言編寫。

tidb是go語言麼

本教學操作環境:windows7系統、GO 1.18版本、Dell G3電腦。

Go 語言不少重量級項目,而國內最屌的 Go 開源專案應該就是 TiDB 了吧。 TiDB 是一個分散式資料庫,很多人可能對此一無所知。今天就跟大家聊聊這個話題。

TiDB設計簡單,官網和程式碼都非常易讀,是學習分散式資料庫的首選開源專案。

資料庫、作業系統和編譯器並稱為三大系統,可以說是整個電腦軟體的基石。

很多人用過資料庫,但是很少人實作過一個資料庫,特別是實作一個分散式資料庫。了解資料庫的實作原理和細節,一方面可以提升個人技術,對建立其他系統有幫助,另一方面也有利於用好資料庫。

一、TiDB簡介

#TiDB是一個分散式 NewSQL 資料庫。它支援水平彈性擴展、ACID 事務、標準SQL、MySQL 語法和MySQL 協議,具有資料強一致的高可用特性,是一個不僅適合OLTP 場景還適合OLAP 場景的混合資料庫

OLTP:On-Line Transaction Processing,線上交易處理
OLAP:On-Line Analytical Processing,線上分析處理

  • 高度相容MySQL 5.7

TiDB 高度相容MySQL 5.7 協定、MySQL 5.7 常用的功能及文法.雖然 TiDB 支援 MySQL 語法和協議,但 TiDB 是由 PingCAP 團隊完全自主開發的產品,並非基於MySQL開發。

MySQL 5.7 生態中的系統工具 (PHPMyAdmin、Navicat、MySQL Workbench、mysqldump、Mydumper、Myloader)、客戶端等都適用於 TiDB。

TiDB 目前還不支援觸發器、預存程序、自訂函數、外鍵。

  • 易用性

#TiDB 使用起來很簡單,可以將TiDB 叢集當作MySQL 來用,可以將TiDB 用在任何以MySQL 作為後台儲存服務的應用程式中,基本上不需要修改應用程式碼,同時可以用大部分流行的MySQL 管理工具來管理TiDB。

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

  • 支援分散式事務

#無論是一個地方的幾個節點,或是跨多個資料中心的多個節點,TiDB 皆支援ACID 分散式事務

TiDB 事務模型靈感源自 Google Percolator 模型,主體是一個兩階段提交協定,並進行了一些實用的最佳化。此模型依賴一個時間戳分配器,為每個事務分配單調遞增的時間戳,這樣就偵測到事務衝突。在 TiDB 叢集中,PD 承擔時間戳分配器的角色

TiDB不需要像MySQL一樣透過支援XA來滿足跨資料庫事務,TiDO的本身的分散式事務模型無論是在效能上還是在穩定性上都要比XA 要高出很多,所以不會也不需要支援XA。

與傳統的單機資料庫相比,TiDB 具有以下優勢

  • 純分散式架構,具有良好的擴展性,支援彈性的擴縮容
  • 支援SQL,對外暴露MySQL 的網路協議,並相容於大多數MySQL 的語法,在大多數場景下可以直接取代MySQL
  • 預設支援高可用,在少數副本失效的情況下,資料庫本身能夠自動進行資料修復和故障轉移,對業務透明
  • 支援ACID 事務,對於一些有強一致需求的場景友好,例如:銀行轉帳
  • 具有豐富的工具鏈生態,涵蓋資料遷移、同步、備份等多種場景

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

  • 資料量大,單機保存不下
  • 不希望做Sharding 或懶得做Sharding
  • 存取模式上沒有明顯的熱點
  • 需要交易、需要強一致、需要災備
  • 希望Real-Time HTAP,減少儲存連結

五大核心特性

  • 一鍵水平擴充或縮容

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

  • 金融級高可用

    #資料採用多副本存儲,資料副本透過Multi-Raft 協定同步交易日誌,多數派寫入成功事務才能提交,確保資料強一致性且少數副本發生故障時不影響資料的可用性。可按需配置副本地理位置、副本數量等策略滿足不同容災等級的要求。

  • 即時HTAP

    #提供行儲存引擎TiKV、列儲存引擎TiFlash 兩款儲存引擎,TiFlash 透過Multi -Raft Learner 協議即時從TiKV 複製數據,確保行存儲引擎TiKV 和列存儲引擎TiFlash 之間的數據強一致。 TiKV、TiFlash 可依需求部署在不同的機器,解決 HTAP 資源隔離的問題。

  • 雲端原生的分散式資料庫

    #專為雲端而設計的分散式資料庫,透過TiDB Operator 可在公有雲、私有雲、混合雲實現部署工具化、自動化。

  • 相容MySQL 5.7 協定與MySQL 生態

    相容於MySQL 5.7 協定、MySQL 常用的功能、MySQL 生態,應用程式無需或修改少量程式碼即可從MySQL 遷移到TiDB。提供豐富的資料遷移工具幫助應用程式便捷完成資料遷移。

四大核心應用程式場景

  • 對資料一致性及高可靠、系統高可用、可擴展性、容災要求較高的金融業屬性的場景

    眾所周知,金融業對數據一致性及高可靠、系統高可用、可擴展性、容災需求較高。傳統的解決方案是同城兩個機房提供服務、異地一個機房提供資料容災能力但不提供服務,此解決方案有以下缺點:資源利用率低、維護成本高、RTO (Recovery Time Objective) RPO (Recovery Point Objective) 無法真實達到企業所期望的價值。 TiDB 採用多副本 Multi-Raft 協定的方式將資料調度到不同的機房、機架、機器,當部分機器故障時系統可自動切換,確保系統的 RTO

  • 對儲存容量、可擴充性、並發要求較高的大量資料及高並發的OLTP 場景

    隨著業務的高速發展,資料呈現爆炸性的成長,傳統的單機資料庫無法滿足因資料爆炸性的成長對資料庫的容量要求,可行方案是採用分庫分錶的中間件產品或NewSQL 資料庫替代、採用高端的儲存設備等,其中性價比最大的是NewSQL 資料庫,例如:TiDB。 TiDB 採用運算、儲存分離的架構,可對運算、儲存分別進行擴容和縮容,運算最大支援 512 節點,每個節點最大支援 1000 並發,叢集容量最大支援 PB 等級。

  • Real-time HTAP 場景

    隨著5G、物聯網、人工智慧的高速發展,企業所生產的資料會越來越多,其規模可能達到數百TB 甚至PB 級別,傳統的解決方案是透過OLTP 型資料庫處理線上線上交易業務,透過ETL 工具將資料同步到OLAP 型資料庫進行資料分析,這種處理方案存在著儲存成本高、即時性差等多方面的問題。 TiDB 在4.0 版本中引入列存儲引擎TiFlash 結合行存儲引擎TiKV 構建真正的HTAP 數據庫,在增加少量存儲成本的情況下,可以在同一個系統中做聯機交易處理、實時數據分析,大大節省企業的成本。

  • 資料匯聚、二次加工處理的場景

    目前絕大部分企業的業務資料都分散在不同的系統中,沒有一個統一的匯總,隨著業務的發展,企業的決策層需要了解整個公司的業務狀況以便及時做出決策,故需要將分散在各個系統的資料匯聚在同一個系統並進行二次加工處理產生T 0 或T 1 的報表。傳統常見的解決方案是採用 ETL Hadoop 來完成,但 Hadoop 系統太複雜,維運、儲存成本太高無法滿足使用者的需求。與 Hadoop 相比,TiDB 就簡單得多,業務透過 ETL 工具或 TiDB 的同步工具將資料同步到 TiDB,在 TiDB 中可透過 SQL 直接產生報表。

二、快速上手

TiDB 是分散式系統。最基礎的 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、宣告全域環境變數。 source ${your_shell_profile}

    source /home/user/.bashrc
    登入後複製
  • #step3、在目前 session 執行下列指令啟動叢集。

    tiup playground
    登入後複製
  • step4、驗證。 【現在可以像使用MySQL一樣使用TiDB啦

    #新开启一个 session 以访问 TiDB 数据库。
    #使用 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架構原理

tidb是go語言麼

tidb是go語言麼

在核心設計上,TiDB 分散式資料庫將整體架構拆分成了多個模組,各模組之間互相通信,組成完整的TiDB 系統。對應的架構圖如下:

TiDB Server 負責處理SQL相關的邏輯,將SQL語句轉成key,透過PD找出資料具體在哪個TiKV。 TiDB本身是無狀態的,不儲存數據,只負責運算。 TiDB採用go語言編寫。 【相關推薦:Go影片教學

PDPD儲存了叢集的元信息,如key在哪個TiKV 節點;PD還負責叢集的負載平衡以及資料分片等。 PD透過內嵌etcd來支援資料分佈和容錯。 PD採用go語言編寫。

TiKV ServerTiKV 是一個分散式的提供交易的Key-Value 儲存引擎,基於Google Spanner, HBase 設計,但脫離了底層較為複雜的HDFS 。透過RocksDB將key-value值存在本地地盤,使用 Raft 協定做複製,保持資料的一致性和容災。 TiKV採用Rust語言編寫。





1、TiDB資料庫的儲存-TiKV Server

##TiDB儲存模型,一個分散式帶事務的KV 引擎一個全域有序的分散式Key-Value 引擎

】 ###的分層結構以及如何實現多副本容錯。 ######儲存節點###TiKV Server###:負責儲存數據,從外部看 TiKV 是分散式的提供交易的 Key-Value 儲存引擎。儲存資料的基本單位是 Region,每個 Region 負責儲存一個 Key Range(從 StartKey 到 EndKey 的左閉右開區間)的數據,每個 TiKV 節點會負責多個 Region。 TiKV 的 API 在 KV 鍵值對層面提供對分散式事務的原生支持,預設提供了 SI (Snapshot Isolation) 的隔離級別,這也是 TiDB 在 SQL 層面支援分散式事務的核心。 TiDB 的 SQL 層做完 SQL 解析後,會將 SQL 的執行計劃轉換為對 TiKV API 的實際呼叫。所以,資料都儲存在 TiKV 中。另外,TiKV 中的資料都會自動維護多副本(預設為三副本),天然支援高可用和自動故障轉移。 ######TiFlash:TiFlash 是一類特殊的儲存節點。和普通 TiKV 節點不一樣的是,在 TiFlash 內部,資料是以列式的形式進行存儲,主要的功能是為分析型的場景加速。 ###############TiKV#########儲存資料需要保證:資料不遺失、資料不錯→Raft協定。除此之外,還需要考慮以下問題:######1、能否支援跨資料中心的容災? ### 2、寫入速度是否夠快? ### 3、資料保存下來後,是否方便讀取? ### 4、保存的資料如何修改?如何支持並發的修改? ### 5、如何原子地修改多筆記錄? ######TiKV專案很好的解決了以上問題。那麼###如何實現 TiKV 這樣一個高效能高可靠性的巨大的(分散式的) Map? ######
  • TiKV是一個巨大的 Map,也就是儲存的是 Key-Value pair。
  • 這個Map 中的Key-Value pair 依照Key 的二進位順序有序,也就是我們可以Seek 到某一個Key 的位置,然後不斷的呼叫Next 方法以遞增的順序取得比這個Key 大的Key-Value。

Raft和RocksDB

TiKV 利用Raft 來做資料複製,每個資料變更都會落地為一Raft 日誌,並透過Raft 的日誌複製功能,將資料安全可靠地同步到Group 的多數節點。

TiKV 沒有選擇直接向磁碟上寫數據,而是把數據保存在 RocksDB 中,具體的數據落地由 RocksDB 負責。 【RocksDB 是一個非常優秀的開源的單機儲存引擎。 】

tidb是go語言麼

透過使用 Raft 一致性演算法,資料在各 TiKV 節點間複製為多重副本,以確保某個節點掛掉時資料的安全性。

實際上在底層,TiKV 使用複製日誌 狀態機 (State Machine) 的模型來複製資料。對於寫入請求,資料被寫入 Leader,然後 Leader 以日誌的形式將命令複製到它的 Follower 中。當叢集中的大多數節點收到此日誌時,日誌會被提交,狀態機會會相應作出變更。

Region概念

對於一個KV 系統,將資料分散在多台機器上有兩種比較典型的方案:一個是依照Key 做Hash,根據Hash 值選擇對應的儲存節點;另一種是分Range,某一段連續的Key 都保存在一個儲存節點上。 為了支援範圍查詢,TiKV 選擇了第二種方式,將整個Key-Value 空間分成許多段,每一段是一系列連續的Key,我們將每一段叫做一個 Region,而且我們會盡量保持每個Region 中儲存的資料不超過一定的大小(這個大小可以配置,目前預設是96Mb)。每一個 Region 都可以用 StartKey 到 EndKey 這樣一個左閉右開區間來描述。

tidb是go語言麼

將資料分割成Region 後,會做兩件重要的事情

  • # #以Region 為單位,將資料分散在叢集中所有的節點上,並且盡量保證每個節點上服務的Region 數量差不多。

    資料依照 Key 切割成許多 Region,每個 Region 的資料只會保存在一個節點上面。我們的系統會有一個元件【PD】來負責將Region 盡可能均勻的散佈在叢集中所有的節點上,這樣

    一方面實現了儲存容量的水平擴展(增加新的節點後,會自動將其他節點上的Region 調度過來),另一方面也實現了負載平衡(不會出現某個節點有很多數據,其他節點上沒什麼數據的情況)。同時為了確保上層客戶端能夠存取所需的數據,系統中也會由元件【PD】記錄Region 在節點上面的分佈情況,也就是透過任一Key 就能查詢到這個Key 在哪個Region 中,以及這個Region 目前在哪個節點上。

  • 以 Region 為單位做 Raft 的複製和成員管理。

    TiKV 是以 Region 為單位做資料的複製,也就是一個 Region 的資料會保存多個副本,將每一個副本稱為一個 Replica。 Replica 之間是透過 Raft 來保持資料的一致性(終於提到了 Raft),一個 Region 的多個 Replica 會保存在不同的節點上,構成一個 Raft Group。其中一個 Replica 會作為這個 Group 的 Leader,其它的 Replica 作為 Follower。所有的讀取和寫入都是透過 Leader 進行,再由 Leader 複製給 Follower。

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

tidb是go語言麼

#以Region 為單位做資料的分散和複製,就有了一個分散式的具備一定容災能力的KeyValue 系統,不用再擔心資料存不下,或是磁碟故障遺失資料的問題。

MVCC

如果兩個Client 同時去修改一個Key 的Value,如果沒有MVCC,就需要對資料上鎖,在分散式場景下,可能會帶來效能以及死鎖問題。 TiKV 的 MVCC 實作是透過在 Key 後面加入 Version 來實現。

对于同一个 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 的事务的实现采用了 MVCC(多版本并发控制)机制,当新写入的数据覆盖旧的数据时,旧的数据不会被替换掉,而是与新写入的数据同时保留,并以时间戳来区分版本。Garbage Collection (GC) 的任务便是清理不再需要的旧数据。

  • GC整体流程

一个 TiDB 集群中会有一个 TiDB 实例被选举为 GC leader,GC 的运行由 GC leader 来控制。

GC 会被定期触发。每次 GC 时,首先,TiDB 会计算一个称为 safe point 的时间戳,接下来 TiDB 会在保证 safe point 之后的快照全部拥有正确数据的前提下,删除更早的过期数据。每一轮 GC 分为以下三个步骤

step1:“Resolve Locks” 【清理锁】阶段会对所有 Region 扫描 safe point 之前的锁,并清理这些锁。

step2:“Delete Ranges” 【删除区间】阶段快速地删除由于 DROP TABLE/DROP INDEX 等操作产生的整区间的废弃数据。

step3:“Do GC”【进行GC清理】阶段每个 TiKV 节点将会各自扫描该节点上的数据,并对每一个 key 删除其不再需要的旧版本。

默认配置下,GC 每 10 分钟触发一次,每次 GC 会保留最近 10 分钟内的数据(即默认 GC life time 为 10 分钟,safe point 的计算方式为当前时间减去 GC life time)。如果一轮 GC 运行时间太久,那么在一轮 GC 完成之前,即使到了下一次触发 GC 的时间也不会开始下一轮 GC。另外,为了使持续时间较长的事务能在超过 GC life time 之后仍然可以正常运行,safe point 不会超过正在执行中的事务的开始时间 (start_ts)。

2、TiDB数据库的计算——TiDB Server

从 SQL 的角度了解了数据是如何存储,以及如何用于计算。

TiDB 在 TiKV 提供的分布式存储能力基础上,构建了兼具优异的交易处理能力与良好的数据分析能力的计算引擎。

TiDB Server:SQL 解析层,对外暴露 MySQL 协议的连接 endpoint,负责接受客户端的连接,执行 SQL 解析和优化,最终生成分布式执行计划。TiDB 层本身是无状态的,实践中可以启动多个 TiDB 实例,通过负载均衡组件(如 LVS、HAProxy 或 F5)对外提供统一的接入地址,客户端的连接可以均匀地分摊在多个 TiDB 实例上以达到负载均衡的效果。TiDB Server 本身并不存储数据,只是解析 SQL,将实际的数据读取请求转发给底层的存储节点 TiKV(或 TiFlash)。

SQL映射KV

可以将关系模型简单理解为 Table 和 SQL 语句,那么问题变为如何在 KV 结构上保存 Table 以及如何在 KV 结构上运行 SQL 语句。 SQL 和 KV 结构之间存在巨大的区别,那么如何能够方便高效地进行映射,就成为一个很重要的问题。一个好的映射方案必须有利于对数据操作的需求。

tidb是go語言麼

分布式SQL运算

首先我们需要将计算尽量靠近存储节点,以避免大量的 RPC 调用。其次,我们需要将 Filter 也下推到存储节点进行计算,这样只需要返回有效的行,避免无意义的网络传输。最后,我们可以将聚合函数、GroupBy 也下推【计算下推】到存储节点,进行预聚合,每个节点只需要返回一个 Count 值即可,再由 tidb-server 将 Count 值 Sum 起来【并行算子】。 这里有一个数据逐层返回的示意图:

tidb是go語言麼

实际上 TiDB 的 SQL 层要复杂的多,模块以及层次非常多,下面这个图【SQL引擎架构】列出了重要的模块以及调用关系:

tidb是go語言麼

SQL查詢傳回的簡短流程:使用者的SQL 要求會直接或透過Load Balancer 傳送到tidb-server,tidb-server 會解析MySQL Protocol Packet,取得請求內容,然後做語法解析、查詢計劃制定和最佳化、執行查詢計劃以取得和處理資料。資料全部儲存在 TiKV 叢集中,所以在這個過程中 tidb-server 需要和 tikv-server 交互,取得資料。最後 tidb-server 需要將查詢結果傳回給使用者。

SQL執行流程

在TiDB 中,從輸入的查詢文字到最終的執行計劃執行結果的過程可以見下圖:

tidb是go語言麼

首先經過parser 對原始查詢文字的解析以及一些簡單的合法性驗證後,TiDB 首先會對查詢做一些邏輯上的等價變化-查詢邏輯優化
透過這些等價變化,使得這個查詢在邏輯執行計劃上可以變得更容易處理。在等價變化結束之後,TiDB 會得到​​一個與原始查詢等價的查詢計劃結構,之後根據資料分佈、以及一個算子具體的執行開銷,來獲得一個最終的執行計劃——查詢物理優化
同時,TiDB 在執行 PREPARE 語句時,可以選擇開啟快取來降低 TiDB 產生執行計畫的開銷-執行計畫快取

3、TiDB資料庫的排程-PD Server

PD (Placement Driver) 是TiDB 叢集的管理模組,同時也負責集群數據的即時調度。

調度場景

PD (Placement Driver) Server:整個TiDB 叢集的元資訊管理模組,負責存儲每個TiKV 節點即時的資料分佈情況和叢集的整體拓撲結構,提供TiDB Dashboard 管控介面,並為分散式事務分配事務ID。 PD 不僅儲存元訊息,同時還會根據 TiKV 節點即時上報的資料分佈狀態,下發資料調度指令給特定的 TiKV 節點,可以說是整個叢集的「大腦」。此外,PD 本身也是由至少 3 個節點構成,從而提供高可用。建議部署奇數個 PD 節點。

調度需求

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

  • 副本數量不能多也不能少。
  • 副本需要根據拓樸結構分佈在不同屬性的機器上。
  • 節點宕機或異常能夠自動合理快速地進行容災。

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

  • 維持整個群集的Leader 分佈均勻。
  • 維持每個節點的儲存容量均勻。
  • 維持訪問熱點分佈均勻。
  • 控制負載平衡的速度,避免影響線上服務。
  • 管理節點狀態,包含手動上線/下線節點。

為了滿足這些需求,需要收集足夠的信息,例如每個節點的狀態、每個Raft Group 的資訊、業務存取操作的統計等;其次需要設定一些策略,PD 根據這些資訊以及調度的策略,制定盡量滿足前面所述需求的調度計畫。

調度操作

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

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

剛好Raft 協定透過AddReplicaRemoveReplicaTransferLeader 這三個指令,可以支撐上述三種基本操作。

TiKV Store 的狀態具體分為 Up,Disconnect,Offline,Down,Tombstone。各狀態的關係如下:

tidb是go語言麼

調度策略

  • 一個 Region 的副本數量正確。
  • 一個 Raft Group 中的多個副本不在同一個位置。
  • 副本在 Store 之間的分佈均勻分配。
  • Leader 數量在 Store 之間均勻分配。
  • 存取熱點數量在 Store 之間均勻分配。
  • 各個 Store 的儲存空間佔用大致相等。
  • 控制調度速度,避免影響線上服務。

調度實作

PD 不斷的透過Store 【即TiKV節點】或Leader 的心跳包收集訊息,獲得整個集群的詳細數據,並且根據這些資訊以及調度策略生成調度操作序列,每次收到Region Leader 發來的心跳包時,PD 都會檢查是否有對這個Region 待進行的操作,通過心跳包的回复消息,將需要進行的操作返回給Region Leader,並在後面的心跳包中監測執行結果。注意這裡的操作只是給 Region Leader 的建議,並不保證一定能得到執行,具體是否會執行以及什麼時候執行,由 Region Leader 自己根據當前自身狀態來定。

五、TiDB最佳實務

TiDB 的最佳實務與其實作原則密切相關,建議先了解一些基本的實作機制,包括Raft、分散式事務、資料分片、負載平衡、SQL 到KV 的映射方案、二級索引的實作方法、分散式執行引擎。

Raft

Raft 是一致性協議,能提供強一致的資料複製保證,TiDB 最底層用Raft 來同步數據。每次寫入都要寫入多數副本,才能對外返回成功,這樣即使丟掉少數副本,也能保證系統中還有最新的資料。例如最大 3 副本的話,每次寫入 2 副本才算成功,任何時候,只遺失一個副本的情況下,存活的兩個副本中至少有一個具有最新的資料。

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

分散式事務

TiDB 提供完整的分散式事務,事務模型是在 Google Percolator 的基礎上做了一些最佳化。

  • 樂觀鎖定

    TiDB 的樂觀事務模型,只有在真正提交的時候,才會做衝突偵測。如果有衝突,則需要重試。這種模型在衝突嚴重的場景下,會比較低效,因為重試之前的操作都是無效的,需要重複做。舉一個比較極端的例子,就是把資料庫當做計數器用,如果存取的並發度比較高,那麼一定會有嚴重的衝突,導致大量的重試甚至是超時。但如果訪問衝突並不十分嚴重,那麼樂觀鎖模型就具備較高的效率。在衝突嚴重的場景下,建議使用悲觀鎖,或在系統架構層面解決問題,例如將計數器放在 Redis 中。

  • 悲觀鎖定

    TiDB 的悲觀事務模式,悲觀事務的行為和MySQL 基本上一致,在執行階段就會上鎖,先到先得,避免衝突情況下的重試,可以保證有較多衝突的事務的成功率。悲觀鎖定同時解決了希望透過 select for update 對資料提前鎖定的場景。但如果業務場景本身衝突較少,樂觀鎖的效能會更有優勢。

  • 交易大小限制

    由於分散式交易要做兩階段提交,且底層也需要做Raft 複製,如果一個交易非常大,會讓提交過程非常慢,並且會卡住下面的Raft 複製流程。為了避免系統出現被卡住的情況,我們對交易的大小做了限制【單一交易包含的 SQL 語句不超過 5000 條(預設)】。

資料分片

TiKV 會自動將底層資料依照 Key 的 Range 進行分片。每個 Region 是一個 Key 的範圍,從 StartKeyEndKey 的左閉右開區間。 Region 中的 Key-Value 總量超過一定值,就會自動分裂。這部分對用戶透明。

負載平衡

PD 會根據整個 TiKV 叢集的狀態,對叢集的負載進行調度。調度是以 Region 為單位,以 PD 配置的策略為調度邏輯,自動完成。

SQL on KV

TiDB 會自動將 SQL 結構對應為 KV 結構。簡單來說,TiDB 執行了以下操作:

  • 一行資料對應為一個KV,Key 以TableID 建構前綴,以行ID 為後綴
  • 一條索引對應為一個KV,Key 以TableID IndexID 建構前綴,以索引值建構後綴

可以看到,對於一個表格中的資料或索引,會具有相同的前綴,這樣在TiKV 的Key 空間內,這些Key- Value 會在相鄰的位置。那麼當寫入量很大,並且集中在一個表上面時,就會造成寫入的熱點,特別是連續寫入的資料中某些索引值也是連續的(例如update time 這種按時間遞增的字段),會在很少的幾個Region 上形成寫入熱點,成為整個系統的瓶頸。同樣,如果所有的資料讀取操作也都集中在很小的一個範圍內(例如在連續的幾萬或十幾萬行資料上),那麼可能造成資料的存取熱點。

二級索引

TiDB 支援完整的二級索引,並且是全域索引,許多查詢可以透過索引來最佳化。如果利用好二級索引,對業務非常重要,許多MySQL 上的經驗在TiDB 這裡依然適用,不過TiDB 還有一些自己的特點,需要注意,這一節主要討論在TiDB 上使用二級索引的一些注意事項。

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

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

  • 透過索引查詢和直接掃描 Table 的差異。

  • 查詢並發度。

    資料分散在許多 Region 上,所以 TiDB 在做查詢的時候會並發進行,預設的並發度比較保守,因為過高的並發度會消耗大量的系統資源。

    對於 OLTP 類型的查詢,往往不會涉及大量的數據,較低的並發度已經可以滿足需求。
    對於 OLAP 類型的 Query,往往需要較高的並發度。

    所以 TiDB 支援透過 System Variable 來調整查詢並發度。 【tidb_distsql_scan_concurrency、tidb_index_lookup_size、tidb_index_lookup_concurrency、tidb_index_serial_scan_concurrency等等】

  • 透過索引保證結果順序。 【索引除了可以用來過濾資料之外,還能用來對資料排序,先依照索引的順序取得行ID,然後再依照行ID 的回傳順序傳回行的內容,這樣可以保證回傳結果依照索引列有序。 】

  • 也支援逆序索引。 【目前速度比順序 Scan 慢一些,通常情況下慢 20%,在資料頻繁修改造成版本較多的情況下,會慢的更多。如果可能,建議避免對索引的逆序 Scan】

更多程式相關知識,請造訪:程式設計影片! !

以上是tidb是go語言麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!