本篇內(nèi)容介紹了“tidb是不是go語言”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
成都創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比公主嶺網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式公主嶺網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋公主嶺地區(qū)。費(fèi)用合理售后完善,10年實(shí)體公司更值得信賴。
是,TiDB采用go語言編寫。TiDB是一個分布式NewSQL數(shù)據(jù)庫;它支持水平彈性擴(kuò)展、ACID事務(wù)、標(biāo)準(zhǔn)SQL、MySQL語法和MySQL協(xié)議,具有數(shù)據(jù)強(qiáng)一致的高可用特性。TiDB架構(gòu)中的PD儲存了集群的元信息,如key在哪個TiKV節(jié)點(diǎn);PD還負(fù)責(zé)集群的負(fù)載均衡以及數(shù)據(jù)分片等。PD通過內(nèi)嵌etcd來支持?jǐn)?shù)據(jù)分布和容錯;PD采用go語言編寫。
Go 語言不少重量級項(xiàng)目,而國內(nèi)最牛逼的 Go 開源項(xiàng)目應(yīng)該就是 TiDB 了吧。TiDB 是一個分布式數(shù)據(jù)庫,很多人可能對此一無所知。今天就跟大家聊聊這個話題。
TiDB設(shè)計(jì)簡單,官網(wǎng)和代碼都非常易讀,是學(xué)習(xí)分布式數(shù)據(jù)庫的首選開源項(xiàng)目。
數(shù)據(jù)庫、操作系統(tǒng)和編譯器并稱為三大系統(tǒng),可以說是整個計(jì)算機(jī)軟件的基石。
很多人用過數(shù)據(jù)庫,但是很少有人實(shí)現(xiàn)過一個數(shù)據(jù)庫,特別是實(shí)現(xiàn)一個分布式數(shù)據(jù)庫。了解數(shù)據(jù)庫的實(shí)現(xiàn)原理和細(xì)節(jié),一方面可以提高個人技術(shù),對構(gòu)建其他系統(tǒng)有幫助,另一方面也有利于用好數(shù)據(jù)庫。
TiDB是一個分布式 NewSQL 數(shù)據(jù)庫。它支持水平彈性擴(kuò)展、ACID 事務(wù)、標(biāo)準(zhǔn) SQL、MySQL 語法和 MySQL 協(xié)議,具有數(shù)據(jù)強(qiáng)一致的高可用特性,是一個不僅適合 OLTP場景還適合 OLAP場景的混合數(shù)據(jù)庫。
OLTP:On-Line Transaction Processing,聯(lián)機(jī)事務(wù)處理。
OLAP:On-Line Analytical Processing,聯(lián)機(jī)分析處理。
高度兼容 MySQL 5.7
TiDB 高度兼容 MySQL 5.7 協(xié)議、MySQL 5.7 常用的功能及語法。雖然 TiDB 支持 MySQL 語法和協(xié)議,但是 TiDB 是由 PingCAP 團(tuán)隊(duì)完全自主開發(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 集群當(dāng)成 MySQL 來用,可以將 TiDB 用在任何以 MySQL 作為后臺存儲服務(wù)的應(yīng)用中,并且基本上不需要修改應(yīng)用代碼,同時可以用大部分流行的 MySQL 管理工具來管理 TiDB。
只要支持 MySQL Client/Driver 的編程語言,都可以直接使用 TiDB。
支持分布式事務(wù)
無論是一個地方的幾個節(jié)點(diǎn),還是跨多個數(shù)據(jù)中心的多個節(jié)點(diǎn),TiDB 均支持 ACID 分布式事務(wù)。
TiDB 事務(wù)模型靈感源自 Google Percolator 模型,主體是一個兩階段提交協(xié)議,并進(jìn)行了一些實(shí)用的優(yōu)化。該模型依賴于一個時間戳分配器,為每個事務(wù)分配單調(diào)遞增的時間戳,這樣就檢測到事務(wù)沖突。在 TiDB 集群中,PD 承擔(dān)時間戳分配器的角色。
TiDB不需要像MySQL一樣通過支持XA來滿足跨數(shù)據(jù)庫事務(wù),TiDO的本身的分布式事務(wù)模型無論是在性能上還是在穩(wěn)定性上都要比 XA 要高出很多,所以不會也不需要支持 XA。
與傳統(tǒng)的單機(jī)數(shù)據(jù)庫相比,TiDB 具有以下優(yōu)勢:
純分布式架構(gòu),擁有良好的擴(kuò)展性,支持彈性的擴(kuò)縮容
支持 SQL,對外暴露 MySQL 的網(wǎng)絡(luò)協(xié)議,并兼容大多數(shù) MySQL 的語法,在大多數(shù)場景下可以直接替換 MySQL
默認(rèn)支持高可用,在少數(shù)副本失效的情況下,數(shù)據(jù)庫本身能夠自動進(jìn)行數(shù)據(jù)修復(fù)和故障轉(zhuǎn)移,對業(yè)務(wù)透明
支持 ACID 事務(wù),對于一些有強(qiáng)一致需求的場景友好,例如:銀行轉(zhuǎn)賬
具有豐富的工具鏈生態(tài),覆蓋數(shù)據(jù)遷移、同步、備份等多種場景
簡單來說,TiDB 適合具備下面這些特點(diǎn)的場景:
數(shù)據(jù)量大,單機(jī)保存不下
不希望做 Sharding 或者懶得做 Sharding
訪問模式上沒有明顯的熱點(diǎn)
需要事務(wù)、需要強(qiáng)一致、需要災(zāi)備
希望 Real-Time HTAP,減少存儲鏈路
一鍵水平擴(kuò)容或者縮容
得益于 TiDB 存儲計(jì)算分離的架構(gòu)的設(shè)計(jì),可按需對計(jì)算、存儲分別進(jìn)行在線擴(kuò)容或者縮容,擴(kuò)容或者縮容過程中對應(yīng)用運(yùn)維人員透明。
金融級高可用
數(shù)據(jù)采用多副本存儲,數(shù)據(jù)副本通過 Multi-Raft 協(xié)議同步事務(wù)日志,多數(shù)派寫入成功事務(wù)才能提交,確保數(shù)據(jù)強(qiáng)一致性且少數(shù)副本發(fā)生故障時不影響數(shù)據(jù)的可用性??砂葱枧渲酶北镜乩砦恢谩⒏北緮?shù)量等策略滿足不同容災(zāi)級別的要求。
實(shí)時 HTAP
提供行存儲引擎 TiKV、列存儲引擎 TiFlash 兩款存儲引擎,TiFlash 通過 Multi-Raft Learner 協(xié)議實(shí)時從 TiKV 復(fù)制數(shù)據(jù),確保行存儲引擎 TiKV 和列存儲引擎 TiFlash 之間的數(shù)據(jù)強(qiáng)一致。TiKV、TiFlash 可按需部署在不同的機(jī)器,解決 HTAP 資源隔離的問題。
云原生的分布式數(shù)據(jù)庫
專為云而設(shè)計(jì)的分布式數(shù)據(jù)庫,通過 TiDB Operator 可在公有云、私有云、混合云中實(shí)現(xiàn)部署工具化、自動化。
兼容 MySQL 5.7 協(xié)議和 MySQL 生態(tài)
兼容 MySQL 5.7 協(xié)議、MySQL 常用的功能、MySQL 生態(tài),應(yīng)用無需或者修改少量代碼即可從 MySQL 遷移到 TiDB。提供豐富的數(shù)據(jù)遷移工具幫助應(yīng)用便捷完成數(shù)據(jù)遷移。
對數(shù)據(jù)一致性及高可靠、系統(tǒng)高可用、可擴(kuò)展性、容災(zāi)要求較高的金融行業(yè)屬性的場景
眾所周知,金融行業(yè)對數(shù)據(jù)一致性及高可靠、系統(tǒng)高可用、可擴(kuò)展性、容災(zāi)要求較高。傳統(tǒng)的解決方案是同城兩個機(jī)房提供服務(wù)、異地一個機(jī)房提供數(shù)據(jù)容災(zāi)能力但不提供服務(wù),此解決方案存在以下缺點(diǎn):資源利用率低、維護(hù)成本高、RTO (Recovery Time Objective)及 RPO (Recovery Point Objective)無法真實(shí)達(dá)到企業(yè)所期望的值。TiDB 采用多副本 + Multi-Raft 協(xié)議的方式將數(shù)據(jù)調(diào)度到不同的機(jī)房、機(jī)架、機(jī)器,當(dāng)部分機(jī)器出現(xiàn)故障時系統(tǒng)可自動進(jìn)行切換,確保系統(tǒng)的 RTO <= 30s 及 RPO = 0。
對存儲容量、可擴(kuò)展性、并發(fā)要求較高的海量數(shù)據(jù)及高并發(fā)的 OLTP 場景
隨著業(yè)務(wù)的高速發(fā)展,數(shù)據(jù)呈現(xiàn)爆炸性的增長,傳統(tǒng)的單機(jī)數(shù)據(jù)庫無法滿足因數(shù)據(jù)爆炸性的增長對數(shù)據(jù)庫的容量要求,可行方案是采用分庫分表的中間件產(chǎn)品或者 NewSQL 數(shù)據(jù)庫替代、采用高端的存儲設(shè)備等,其中性價比最大的是 NewSQL 數(shù)據(jù)庫,例如:TiDB。TiDB 采用計(jì)算、存儲分離的架構(gòu),可對計(jì)算、存儲分別進(jìn)行擴(kuò)容和縮容,計(jì)算最大支持 512 節(jié)點(diǎn),每個節(jié)點(diǎn)最大支持 1000 并發(fā),集群容量最大支持 PB 級別。
Real-time HTAP 場景
隨著 5G、物聯(lián)網(wǎng)、人工智能的高速發(fā)展,企業(yè)所生產(chǎn)的數(shù)據(jù)會越來越多,其規(guī)??赡苓_(dá)到數(shù)百 TB 甚至 PB 級別,傳統(tǒng)的解決方案是通過 OLTP 型數(shù)據(jù)庫處理在線聯(lián)機(jī)交易業(yè)務(wù),通過 ETL 工具將數(shù)據(jù)同步到 OLAP 型數(shù)據(jù)庫進(jìn)行數(shù)據(jù)分析,這種處理方案存在存儲成本高、實(shí)時性差等多方面的問題。TiDB 在 4.0 版本中引入列存儲引擎 TiFlash 結(jié)合行存儲引擎 TiKV 構(gòu)建真正的 HTAP 數(shù)據(jù)庫,在增加少量存儲成本的情況下,可以在同一個系統(tǒng)中做聯(lián)機(jī)交易處理、實(shí)時數(shù)據(jù)分析,極大地節(jié)省企業(yè)的成本。
數(shù)據(jù)匯聚、二次加工處理的場景
當(dāng)前絕大部分企業(yè)的業(yè)務(wù)數(shù)據(jù)都分散在不同的系統(tǒng)中,沒有一個統(tǒng)一的匯總,隨著業(yè)務(wù)的發(fā)展,企業(yè)的決策層需要了解整個公司的業(yè)務(wù)狀況以便及時做出決策,故需要將分散在各個系統(tǒng)的數(shù)據(jù)匯聚在同一個系統(tǒng)并進(jìn)行二次加工處理生成 T+0 或 T+1 的報(bào)表。傳統(tǒng)常見的解決方案是采用 ETL + Hadoop 來完成,但 Hadoop 體系太復(fù)雜,運(yùn)維、存儲成本太高無法滿足用戶的需求。與 Hadoop 相比,TiDB 就簡單得多,業(yè)務(wù)通過 ETL 工具或者 TiDB 的同步工具將數(shù)據(jù)同步到 TiDB,在 TiDB 中可通過 SQL 直接生成報(bào)表。
TiDB 是一個分布式系統(tǒng)。最基礎(chǔ)的 TiDB 測試集群通常由 2 個 TiDB 實(shí)例、3 個 TiKV 實(shí)例、3 個 PD 實(shí)例和可選的 TiFlash 實(shí)例構(gòu)成。通過 TiUP Playground
,可以快速搭建出上述的一套基礎(chǔ)測試集群,步驟如下:
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、在當(dāng)前 session 執(zhí)行以下命令啟動集群。
tiup playground
step4、驗(yàn)證?!?strong>現(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 頁面,默認(rèn)用戶名為 root,密碼為空。
#通過 http://127.0.0.1:3000 訪問 TiDB 的 Grafana 界面,默認(rèn)用戶名和密碼都為 admin。
在內(nèi)核設(shè)計(jì)上,TiDB 分布式數(shù)據(jù)庫將整體架構(gòu)拆分成了多個模塊,各模塊之間互相通信,組成完整的 TiDB 系統(tǒng)。對應(yīng)的架構(gòu)圖如下:
TiDB Server 負(fù)責(zé)處理SQL相關(guān)的邏輯,將SQL語句轉(zhuǎn)成key,通過PD來查找數(shù)據(jù)具體在哪個TiKV。TiDB本身是無狀態(tài)的,不存儲數(shù)據(jù),只負(fù)責(zé)計(jì)算。TiDB采用go語言編寫?!鞠嚓P(guān)推薦:Go視頻教程】
PD
PD儲存了集群的元信息,如key在哪個 TiKV 節(jié)點(diǎn);PD還負(fù)責(zé)集群的負(fù)載均衡以及數(shù)據(jù)分片等。PD通過內(nèi)嵌etcd來支持?jǐn)?shù)據(jù)分布和容錯。PD采用go語言編寫。
TiKV Server
TiKV 是一個分布式的提供事務(wù)的 Key-Value 存儲引擎,基于Google Spanner, HBase 設(shè)計(jì),但脫離了底層較為復(fù)雜的HDFS。通過RocksDB將key-value值存在本地地盤,使用 Raft 協(xié)議做復(fù)制,保持?jǐn)?shù)據(jù)的一致性和容災(zāi)。TiKV采用Rust語言編寫。
TiDB存儲模型,一個分布式帶事務(wù)的 KV 引擎【一個全局有序的分布式 Key-Value 引擎】 的分層結(jié)構(gòu)以及如何實(shí)現(xiàn)多副本容錯。
存儲節(jié)點(diǎn)TiKV Server:負(fù)責(zé)存儲數(shù)據(jù),從外部看 TiKV 是一個分布式的提供事務(wù)的 Key-Value 存儲引擎。存儲數(shù)據(jù)的基本單位是 Region,每個 Region 負(fù)責(zé)存儲一個 Key Range(從 StartKey 到 EndKey 的左閉右開區(qū)間)的數(shù)據(jù),每個 TiKV 節(jié)點(diǎn)會負(fù)責(zé)多個 Region。TiKV 的 API 在 KV 鍵值對層面提供對分布式事務(wù)的原生支持,默認(rèn)提供了 SI (Snapshot Isolation) 的隔離級別,這也是 TiDB 在 SQL 層面支持分布式事務(wù)的核心。TiDB 的 SQL 層做完 SQL 解析后,會將 SQL 的執(zhí)行計(jì)劃轉(zhuǎn)換為對 TiKV API 的實(shí)際調(diào)用。所以,數(shù)據(jù)都存儲在 TiKV 中。另外,TiKV 中的數(shù)據(jù)都會自動維護(hù)多副本(默認(rèn)為三副本),天然支持高可用和自動故障轉(zhuǎn)移。
TiFlash:TiFlash 是一類特殊的存儲節(jié)點(diǎn)。和普通 TiKV 節(jié)點(diǎn)不一樣的是,在 TiFlash 內(nèi)部,數(shù)據(jù)是以列式的形式進(jìn)行存儲,主要的功能是為分析型的場景加速。
保存數(shù)據(jù)需要保證:數(shù)據(jù)不丟、數(shù)據(jù)不錯→Raft協(xié)議。除此之外,還需要考慮以下問題:
1、能否支持跨數(shù)據(jù)中心的容災(zāi)?
2、寫入速度是否夠快?
3、數(shù)據(jù)保存下來后,是否方便讀???
4、保存的數(shù)據(jù)如何修改?如何支持并發(fā)的修改?
5、如何原子地修改多條記錄?
TiKV項(xiàng)目很好的解決了以上問題。那么如何實(shí)現(xiàn) TiKV 這樣一個高性能高可靠性的巨大的(分布式的) Map?
TiKV是一個巨大的 Map,也就是存儲的是 Key-Value pair。
這個 Map 中的 Key-Value pair 按照 Key 的二進(jìn)制順序有序,也就是我們可以 Seek 到某一個 Key 的位置,然后不斷的調(diào)用 Next 方法以遞增的順序獲取比這個 Key 大的 Key-Value。
TiKV 利用 Raft 來做數(shù)據(jù)復(fù)制,每個數(shù)據(jù)變更都會落地為一條 Raft 日志,通過 Raft 的日志復(fù)制功能,將數(shù)據(jù)安全可靠地同步到 Group 的多數(shù)節(jié)點(diǎn)中。
TiKV 沒有選擇直接向磁盤上寫數(shù)據(jù),而是把數(shù)據(jù)保存在 RocksDB 中,具體的數(shù)據(jù)落地由 RocksDB 負(fù)責(zé)?!綬ocksDB 是一個非常優(yōu)秀的開源的單機(jī)存儲引擎?!?/p>
通過使用 Raft 一致性算法,數(shù)據(jù)在各 TiKV 節(jié)點(diǎn)間復(fù)制為多副本,以確保某個節(jié)點(diǎn)掛掉時數(shù)據(jù)的安全性。
實(shí)際上在底層,TiKV 使用復(fù)制日志 + 狀態(tài)機(jī) (State Machine) 的模型來復(fù)制數(shù)據(jù)。對于寫入請求,數(shù)據(jù)被寫入 Leader,然后 Leader 以日志的形式將命令復(fù)制到它的 Follower 中。當(dāng)集群中的大多數(shù)節(jié)點(diǎn)收到此日志時,日志會被提交,狀態(tài)機(jī)會相應(yīng)作出變更。
對于一個 KV 系統(tǒng),將數(shù)據(jù)分散在多臺機(jī)器上有兩種比較典型的方案:一種是按照 Key 做 Hash,根據(jù) Hash 值選擇對應(yīng)的存儲節(jié)點(diǎn);另一種是分 Range,某一段連續(xù)的 Key 都保存在一個存儲節(jié)點(diǎn)上。為了支持范圍查詢,TiKV 選擇了第二種方式,將整個 Key-Value 空間分成很多段,每一段是一系列連續(xù)的 Key,我們將每一段叫做一個 Region,并且我們會盡量保持每個 Region 中保存的數(shù)據(jù)不超過一定的大?。ㄟ@個大小可以配置,目前默認(rèn)是 96Mb)。每一個 Region 都可以用 StartKey 到 EndKey 這樣一個左閉右開區(qū)間來描述。
將數(shù)據(jù)劃分成 Region 后,會做 兩件重要的事情:
以 Region 為單位,將數(shù)據(jù)分散在集群中所有的節(jié)點(diǎn)上,并且盡量保證每個節(jié)點(diǎn)上服務(wù)的 Region 數(shù)量差不多。
數(shù)據(jù)按照 Key 切分成很多 Region,每個 Region 的數(shù)據(jù)只會保存在一個節(jié)點(diǎn)上面。我們的系統(tǒng)會有一個組件【PD】來負(fù)責(zé)將 Region 盡可能均勻的散布在集群中所有的節(jié)點(diǎn)上,這樣一方面實(shí)現(xiàn)了存儲容量的水平擴(kuò)展(增加新的節(jié)點(diǎn)后,會自動將其他節(jié)點(diǎn)上的 Region 調(diào)度過來),另一方面也實(shí)現(xiàn)了負(fù)載均衡(不會出現(xiàn)某個節(jié)點(diǎn)有很多數(shù)據(jù),其他節(jié)點(diǎn)上沒什么數(shù)據(jù)的情況)。同時為了保證上層客戶端能夠訪問所需要的數(shù)據(jù),系統(tǒng)中也會由組件【PD】記錄 Region 在節(jié)點(diǎn)上面的分布情況,也就是通過任意一個 Key 就能查詢到這個 Key 在哪個 Region 中,以及這個 Region 目前在哪個節(jié)點(diǎn)上。
以 Region 為單位做 Raft 的復(fù)制和成員管理。
TiKV 是以 Region 為單位做數(shù)據(jù)的復(fù)制,也就是一個 Region 的數(shù)據(jù)會保存多個副本,將每一個副本叫做一個 Replica。Replica 之間是通過 Raft 來保持?jǐn)?shù)據(jù)的一致(終于提到了 Raft),一個 Region 的多個 Replica 會保存在不同的節(jié)點(diǎn)上,構(gòu)成一個 Raft Group。其中一個 Replica 會作為這個 Group 的 Leader,其它的 Replica 作為 Follower。所有的讀和寫都是通過 Leader 進(jìn)行,再由 Leader 復(fù)制給 Follower。
理解了 Region 之后,應(yīng)該可以理解下面這張圖:
以 Region 為單位做數(shù)據(jù)的分散和復(fù)制,就有了一個分布式的具備一定容災(zāi)能力的 KeyValue 系統(tǒng),不用再擔(dān)心數(shù)據(jù)存不下,或者是磁盤故障丟失數(shù)據(jù)的問題。
如果兩個 Client 同時去修改一個 Key 的 Value,如果沒有 MVCC,就需要對數(shù)據(jù)上鎖,在分布式場景下,可能會帶來性能以及死鎖問題。 TiKV 的 MVCC 實(shí)現(xiàn)是通過在 Key 后面添加 Version 來實(shí)現(xiàn)。
對于同一個 Key 的多個版本,把版本號較大的放在前面,版本號小的放在后面。這樣當(dāng)用戶通過一個 Key + Version 來獲取 Value 的時候,可以將 Key 和 Version 構(gòu)造出 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
……
TiDB 的事務(wù)的實(shí)現(xiàn)采用了 MVCC(多版本并發(fā)控制)機(jī)制,當(dāng)新寫入的數(shù)據(jù)覆蓋舊的數(shù)據(jù)時,舊的數(shù)據(jù)不會被替換掉,而是與新寫入的數(shù)據(jù)同時保留,并以時間戳來區(qū)分版本。Garbage Collection (GC) 的任務(wù)便是清理不再需要的舊數(shù)據(jù)。
GC整體流程
一個 TiDB 集群中會有一個 TiDB 實(shí)例被選舉為 GC leader,GC 的運(yùn)行由 GC leader 來控制。
GC 會被定期觸發(fā)。每次 GC 時,首先,TiDB 會計(jì)算一個稱為 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”【進(jìn)行GC清理】階段每個 TiKV 節(jié)點(diǎn)將會各自掃描該節(jié)點(diǎn)上的數(shù)據(jù),并對每一個 key 刪除其不再需要的舊版本。
默認(rèn)配置下,GC 每 10 分鐘觸發(fā)一次,每次 GC 會保留最近 10 分鐘內(nèi)的數(shù)據(jù)(即默認(rèn) GC life time 為 10 分鐘,safe point 的計(jì)算方式為當(dāng)前時間減去 GC life time)。如果一輪 GC 運(yùn)行時間太久,那么在一輪 GC 完成之前,即使到了下一次觸發(fā) GC 的時間也不會開始下一輪 GC。另外,為了使持續(xù)時間較長的事務(wù)能在超過 GC life time 之后仍然可以正常運(yùn)行,safe point 不會超過正在執(zhí)行中的事務(wù)的開始時間 (start_ts)。
從 SQL 的角度了解了數(shù)據(jù)是如何存儲,以及如何用于計(jì)算。
TiDB 在 TiKV 提供的分布式存儲能力基礎(chǔ)上,構(gòu)建了兼具優(yōu)異的交易處理能力與良好的數(shù)據(jù)分析能力的計(jì)算引擎。
TiDB Server:SQL 解析層,對外暴露 MySQL 協(xié)議的連接 endpoint,負(fù)責(zé)接受客戶端的連接,執(zhí)行 SQL 解析和優(yōu)化,最終生成分布式執(zhí)行計(jì)劃。TiDB 層本身是無狀態(tài)的,實(shí)踐中可以啟動多個 TiDB 實(shí)例,通過負(fù)載均衡組件(如 LVS、HAProxy 或 F5)對外提供統(tǒng)一的接入地址,客戶端的連接可以均勻地分?jǐn)傇诙鄠€ TiDB 實(shí)例上以達(dá)到負(fù)載均衡的效果。TiDB Server 本身并不存儲數(shù)據(jù),只是解析 SQL,將實(shí)際的數(shù)據(jù)讀取請求轉(zhuǎn)發(fā)給底層的存儲節(jié)點(diǎn) TiKV(或 TiFlash)。
可以將關(guān)系模型簡單理解為 Table 和 SQL 語句,那么問題變?yōu)槿绾卧?KV 結(jié)構(gòu)上保存 Table 以及如何在 KV 結(jié)構(gòu)上運(yùn)行 SQL 語句。 SQL 和 KV 結(jié)構(gòu)之間存在巨大的區(qū)別,那么如何能夠方便高效地進(jìn)行映射,就成為一個很重要的問題。一個好的映射方案必須有利于對數(shù)據(jù)操作的需求。
首先我們需要將計(jì)算盡量靠近存儲節(jié)點(diǎn),以避免大量的 RPC 調(diào)用。其次,我們需要將 Filter 也下推到存儲節(jié)點(diǎn)進(jìn)行計(jì)算,這樣只需要返回有效的行,避免無意義的網(wǎng)絡(luò)傳輸。最后,我們可以將聚合函數(shù)、GroupBy 也下推【計(jì)算下推】到存儲節(jié)點(diǎn),進(jìn)行預(yù)聚合,每個節(jié)點(diǎn)只需要返回一個 Count 值即可,再由 tidb-server 將 Count 值 Sum 起來【并行算子】。 這里有一個數(shù)據(jù)逐層返回的示意圖:
實(shí)際上 TiDB 的 SQL 層要復(fù)雜的多,模塊以及層次非常多,下面這個圖【SQL引擎架構(gòu)】列出了重要的模塊以及調(diào)用關(guān)系:
SQL查詢返回的簡要流程:用戶的 SQL 請求會直接或者通過 Load Balancer 發(fā)送到 tidb-server,tidb-server 會解析 MySQL Protocol Packet,獲取請求內(nèi)容,然后做語法解析、查詢計(jì)劃制定和優(yōu)化、執(zhí)行查詢計(jì)劃獲取和處理數(shù)據(jù)。數(shù)據(jù)全部存儲在 TiKV 集群中,所以在這個過程中 tidb-server 需要和 tikv-server 交互,獲取數(shù)據(jù)。最后 tidb-server 需要將查詢結(jié)果返回給用戶。
在 TiDB 中,從輸入的查詢文本到最終的執(zhí)行計(jì)劃執(zhí)行結(jié)果的過程可以見下圖:
首先經(jīng)過 parser 對原始查詢文本的解析以及一些簡單的合法性驗(yàn)證后,TiDB 首先會對查詢做一些邏輯上的等價變化——查詢邏輯優(yōu)化。
通過這些等價變化,使得這個查詢在邏輯執(zhí)行計(jì)劃上可以變得更易于處理。在等價變化結(jié)束之后,TiDB 會得到一個與原始查詢等價的查詢計(jì)劃結(jié)構(gòu),之后根據(jù)數(shù)據(jù)分布、以及一個算子具體的執(zhí)行開銷,來獲得一個最終的執(zhí)行計(jì)劃——查詢物理優(yōu)化。
同時,TiDB 在執(zhí)行 PREPARE 語句時,可以選擇開啟緩存來降低 TiDB 生成執(zhí)行計(jì)劃的開銷——執(zhí)行計(jì)劃緩存。
PD (Placement Driver) 是 TiDB 集群的管理模塊,同時也負(fù)責(zé)集群數(shù)據(jù)的實(shí)時調(diào)度。
PD (Placement Driver) Server:整個 TiDB 集群的元信息管理模塊,負(fù)責(zé)存儲每個 TiKV 節(jié)點(diǎn)實(shí)時的數(shù)據(jù)分布情況和集群的整體拓?fù)浣Y(jié)構(gòu),提供 TiDB Dashboard 管控界面,并為分布式事務(wù)分配事務(wù) ID。PD 不僅存儲元信息,同時還會根據(jù) TiKV 節(jié)點(diǎn)實(shí)時上報(bào)的數(shù)據(jù)分布狀態(tài),下發(fā)數(shù)據(jù)調(diào)度命令給具體的 TiKV 節(jié)點(diǎn),可以說是整個集群的“大腦”。此外,PD 本身也是由至少 3 個節(jié)點(diǎn)構(gòu)成,從而提供高可用。建議部署奇數(shù)個 PD 節(jié)點(diǎn)。
第一類:作為一個分布式高可用存儲系統(tǒng),必須滿足的需求,包括幾種:【 容災(zāi)功能 】
副本數(shù)量不能多也不能少。
副本需要根據(jù)拓?fù)浣Y(jié)構(gòu)分布在不同屬性的機(jī)器上。
節(jié)點(diǎn)宕機(jī)或異常能夠自動合理快速地進(jìn)行容災(zāi)。
第二類:作為一個良好的分布式系統(tǒng),需要考慮的地方包括:【資源利用率更高且合理,具備良好的擴(kuò)展性】
維持整個集群的 Leader 分布均勻。
維持每個節(jié)點(diǎn)的儲存容量均勻。
維持訪問熱點(diǎn)分布均勻。
控制負(fù)載均衡的速度,避免影響在線服務(wù)。
管理節(jié)點(diǎn)狀態(tài),包括手動上線/下線節(jié)點(diǎn)。
為了滿足這些需求,需要收集足夠的信息,比如每個節(jié)點(diǎn)的狀態(tài)、每個 Raft Group 的信息、業(yè)務(wù)訪問操作的統(tǒng)計(jì)等;其次需要設(shè)置一些策略,PD 根據(jù)這些信息以及調(diào)度的策略,制定出盡量滿足前面所述需求的調(diào)度計(jì)劃。
調(diào)度的基本操作指的是為了滿足調(diào)度的策略。上述調(diào)度需求可整理為以下三個操作:
增加一個副本
刪除一個副本
將 Leader 角色在一個 Raft Group 的不同副本之間 transfer(遷移)
剛好 Raft 協(xié)議通過 AddReplica
、RemoveReplica
、TransferLeader
這三個命令,可以支撐上述三種基本操作。
TiKV Store 的狀態(tài)具體分為 Up,Disconnect,Offline,Down,Tombstone。各狀態(tài)的關(guān)系如下:
一個 Region 的副本數(shù)量正確。
一個 Raft Group 中的多個副本不在同一個位置。
副本在 Store 之間的分布均勻分配。
Leader 數(shù)量在 Store 之間均勻分配。
訪問熱點(diǎn)數(shù)量在 Store 之間均勻分配。
各個 Store 的存儲空間占用大致相等。
控制調(diào)度速度,避免影響在線服務(wù)。
PD 不斷的通過 Store 【即TiKV節(jié)點(diǎn)】或者 Leader 的心跳包收集信息,獲得整個集群的詳細(xì)數(shù)據(jù),并且根據(jù)這些信息以及調(diào)度策略生成調(diào)度操作序列,每次收到 Region Leader 發(fā)來的心跳包時,PD 都會檢查是否有對這個 Region 待進(jìn)行的操作,通過心跳包的回復(fù)消息,將需要進(jìn)行的操作返回給 Region Leader,并在后面的心跳包中監(jiān)測執(zhí)行結(jié)果。注意這里的操作只是給 Region Leader 的建議,并不保證一定能得到執(zhí)行,具體是否會執(zhí)行以及什么時候執(zhí)行,由 Region Leader 自己根據(jù)當(dāng)前自身狀態(tài)來定。
TiDB 的最佳實(shí)踐與其實(shí)現(xiàn)原理密切相關(guān),建議先了解一些基本的實(shí)現(xiàn)機(jī)制,包括 Raft、分布式事務(wù)、數(shù)據(jù)分片、負(fù)載均衡、SQL 到 KV 的映射方案、二級索引的實(shí)現(xiàn)方法、分布式執(zhí)行引擎。
Raft 是一種一致性協(xié)議,能提供強(qiáng)一致的數(shù)據(jù)復(fù)制保證,TiDB 最底層用 Raft 來同步數(shù)據(jù)。每次寫入都要寫入多數(shù)副本,才能對外返回成功,這樣即使丟掉少數(shù)副本,也能保證系統(tǒng)中還有最新的數(shù)據(jù)。比如最大 3 副本的話,每次寫入 2 副本才算成功,任何時候,只丟失一個副本的情況下,存活的兩個副本中至少有一個具有最新的數(shù)據(jù)。
相比 Master-Slave 方式的同步,同樣是保存三副本,Raft 的方式更為高效,因?yàn)閷懭氲难舆t取決于最快的兩個副本,而不是最慢的那個副本。所以使用 Raft 同步的情況下,異地多活成為可能。在典型的兩地三中心場景下,每次寫入只需要本數(shù)據(jù)中心以及離得近的一個數(shù)據(jù)中心寫入成功就能保證數(shù)據(jù)的一致性,而并不需要三個數(shù)據(jù)中心都寫成功。
TiDB 提供完整的分布式事務(wù),事務(wù)模型是在 Google Percolator 的基礎(chǔ)上做了一些優(yōu)化。
樂觀鎖
TiDB 的樂觀事務(wù)模型,只有在真正提交的時候,才會做沖突檢測。如果有沖突,則需要重試。這種模型在沖突嚴(yán)重的場景下,會比較低效,因?yàn)橹卦囍暗牟僮鞫际菬o效的,需要重復(fù)做。舉一個比較極端的例子,就是把數(shù)據(jù)庫當(dāng)做計(jì)數(shù)器用,如果訪問的并發(fā)度比較高,那么一定會有嚴(yán)重的沖突,導(dǎo)致大量的重試甚至是超時。但是如果訪問沖突并不十分嚴(yán)重,那么樂觀鎖模型具備較高的效率。在沖突嚴(yán)重的場景下,推薦使用悲觀鎖,或在系統(tǒng)架構(gòu)層面解決問題,比如將計(jì)數(shù)器放在 redis 中。
悲觀鎖
TiDB 的悲觀事務(wù)模式,悲觀事務(wù)的行為和 MySQL 基本一致,在執(zhí)行階段就會上鎖,先到先得,避免沖突情況下的重試,可以保證有較多沖突的事務(wù)的成功率。悲觀鎖同時解決了希望通過 select for update
對數(shù)據(jù)提前鎖定的場景。但如果業(yè)務(wù)場景本身沖突較少,樂觀鎖的性能會更有優(yōu)勢。
事務(wù)大小限制
由于分布式事務(wù)要做兩階段提交,并且底層還需要做 Raft 復(fù)制,如果一個事務(wù)非常大,會使得提交過程非常慢,并且會卡住下面的 Raft 復(fù)制流程。為了避免系統(tǒng)出現(xiàn)被卡住的情況,我們對事務(wù)的大小做了限制【單個事務(wù)包含的 SQL 語句不超過 5000 條(默認(rèn))】。
TiKV 自動將底層數(shù)據(jù)按照 Key 的 Range 進(jìn)行分片。每個 Region 是一個 Key 的范圍,從 StartKey
到 EndKey
的左閉右開區(qū)間。Region 中的 Key-Value 總量超過一定值,就會自動分裂。這部分對用戶透明。
PD 會根據(jù)整個 TiKV 集群的狀態(tài),對集群的負(fù)載進(jìn)行調(diào)度。調(diào)度是以 Region 為單位,以 PD 配置的策略為調(diào)度邏輯,自動完成。
TiDB 自動將 SQL 結(jié)構(gòu)映射為 KV 結(jié)構(gòu)。簡單來說,TiDB 執(zhí)行了以下操作:
一行數(shù)據(jù)映射為一個 KV,Key 以 TableID
構(gòu)造前綴,以行 ID 為后綴
一條索引映射為一個 KV,Key 以 TableID+IndexID
構(gòu)造前綴,以索引值構(gòu)造后綴
可以看到,對于一個表中的數(shù)據(jù)或者索引,會具有相同的前綴,這樣在 TiKV 的 Key 空間內(nèi),這些 Key-Value 會在相鄰的位置。那么當(dāng)寫入量很大,并且集中在一個表上面時,就會造成寫入的熱點(diǎn),特別是連續(xù)寫入的數(shù)據(jù)中某些索引值也是連續(xù)的(比如 update time 這種按時間遞增的字段),會在很少的幾個 Region 上形成寫入熱點(diǎn),成為整個系統(tǒng)的瓶頸。同樣,如果所有的數(shù)據(jù)讀取操作也都集中在很小的一個范圍內(nèi)(比如在連續(xù)的幾萬或者十幾萬行數(shù)據(jù)上),那么可能造成數(shù)據(jù)的訪問熱點(diǎn)。
TiDB 支持完整的二級索引,并且是全局索引,很多查詢可以通過索引來優(yōu)化。如果利用好二級索引,對業(yè)務(wù)非常重要,很多 MySQL 上的經(jīng)驗(yàn)在 TiDB 這里依然適用,不過 TiDB 還有一些自己的特點(diǎn),需要注意,這一節(jié)主要討論在 TiDB 上使用二級索引的一些注意事項(xiàng)。
二級索引不是越多越好。
對區(qū)分度【基數(shù)】比較大的列建立索引比較合適。有多個查詢條件時,可以選擇組合索引,注意最左前綴原則。
通過索引查詢和直接掃描 Table 的區(qū)別。
查詢并發(fā)度。
數(shù)據(jù)分散在很多 Region 上,所以 TiDB 在做查詢的時候會并發(fā)進(jìn)行,默認(rèn)的并發(fā)度比較保守,因?yàn)檫^高的并發(fā)度會消耗大量的系統(tǒng)資源。
對于 OLTP 類型的查詢,往往不會涉及到大量的數(shù)據(jù),較低的并發(fā)度已經(jīng)可以滿足需求。
對于 OLAP 類型的 Query,往往需要較高的并發(fā)度。
所以 TiDB 支持通過 System Variable 來調(diào)整查詢并發(fā)度。【tidb_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è)相關(guān)的知識可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!