TiDB:支持MySQL协议的分布式数据库解决方案
【編者按】TiDB 是國(guó)內(nèi) PingCAP 團(tuán)隊(duì)開(kāi)發(fā)的一個(gè)分布式 SQL 數(shù)據(jù)庫(kù)。其靈感來(lái)自于 Google 的 F1,TiDB 支持包括傳統(tǒng) RDBMS 和 NoSQL 的特性。在國(guó)內(nèi)ITOM 管理平臺(tái)OneAPM 舉辦的技術(shù)公開(kāi)課中,TiDB的高級(jí)工程師劉奇從HBase特性、TiDB的優(yōu)勢(shì)和系統(tǒng)架構(gòu)等方面進(jìn)行了詳細(xì)闡述。以下為演講整理:
HBase簡(jiǎn)介
眾所周知,在SQL方面處于頂級(jí)的有兩個(gè)公司,一個(gè)是Oracle,他們已經(jīng)積累了大量的經(jīng)驗(yàn),另一個(gè)是谷歌,谷歌 F1在2012年發(fā)布了一篇論文,個(gè)人認(rèn)為它是全球最優(yōu)秀的SQL OLTP數(shù)據(jù)庫(kù)。
1978年左右,數(shù)據(jù)庫(kù)剛剛發(fā)展時(shí)出現(xiàn)了SQL RDBMS。2000年左右,國(guó)內(nèi)開(kāi)始流行互聯(lián)網(wǎng),互聯(lián)網(wǎng)對(duì)Oracle數(shù)據(jù)庫(kù)也產(chǎn)生較大的沖擊?,F(xiàn)在,傳統(tǒng)的數(shù)據(jù)庫(kù)大部分是集中在傳統(tǒng)領(lǐng)域,互聯(lián)網(wǎng)方面用得比較多的是MySQL,其次HBase等 NoSQL 也吸引了大量的用戶。
為什么會(huì)出現(xiàn)NoSQL?最開(kāi)始所有人都用SQL Database,那時(shí)比較高端有Oracle,開(kāi)源的還有MySQL、PostgreSQL??墒请S著業(yè)務(wù)的迅速發(fā)展,數(shù)據(jù)庫(kù)成為了瓶頸,于是促使了NoSQL的誕生,NoSQL將Scale放在第一位。如果業(yè)務(wù)快速發(fā)展,擴(kuò)容會(huì)成為亟待解決的首要問(wèn)題。這時(shí),大多數(shù)人會(huì)選擇放棄事務(wù)一致性。什么是一致性?比如使用微信時(shí),如果我加你為好友,這是一個(gè)雙向關(guān)系,對(duì)應(yīng)到數(shù)據(jù)庫(kù)中至少是兩個(gè)操作,第一是在好友列表里把你加進(jìn)來(lái),第二個(gè)是你的好友列表里把我加進(jìn)去。如果這兩個(gè)列表的數(shù)據(jù)庫(kù)放在不同的機(jī)器上,就需要保證一致性。否則可能會(huì)出現(xiàn)我是你的好友,但你的好友中卻找不到我的這種情況。但這中間可能會(huì)出現(xiàn)多種情況,比如我把你加為好友,然后修改數(shù)據(jù)的時(shí)候Crush掉了,這個(gè)時(shí)候傳統(tǒng)方案是會(huì)引入一個(gè)消息隊(duì)列,有的還需要做一些補(bǔ)償,這些問(wèn)題在NoSQL里處理起來(lái)相對(duì)麻煩。
國(guó)內(nèi)最大的HBase使用者是小米公司,有幾個(gè)HBase的Committer,所以經(jīng)過(guò)一些修改后可以支持分布式事務(wù),于是能夠解決之前的問(wèn)題。為什么在面臨諸多選擇時(shí),小米會(huì)選擇HBase呢?就目前情況來(lái)說(shuō),主要還是技術(shù)選型和人才儲(chǔ)備上的考慮。MongoDB大家應(yīng)該不陌生,但用到一定程度后,總會(huì)出現(xiàn)各種問(wèn)題,甚至有文章呼吁大家放棄MongoDB。但所有數(shù)據(jù)庫(kù)都不是“十全十美”的,沒(méi)有最好,選擇最適合的尤為重要。
很多時(shí)候產(chǎn)品都有其特性,在滿足其特性或者規(guī)格的情況下,使用起來(lái)可能非常順手,否則十之八九都遇到各種麻煩。比如小米使用HBase就非常順手,但其他的公司則不一定。道理很簡(jiǎn)單,如果不熟悉其使用場(chǎng)景,也不知道在相應(yīng)場(chǎng)景下配什么參數(shù),所以會(huì)出現(xiàn)各種各樣的問(wèn)題。
事實(shí)上,HBase有非常好的特性,目前在小米公司可以每秒跑一百萬(wàn)OPS,最近Pinterest公布他們的HBase每秒可以跑三百萬(wàn)個(gè)OPS,這個(gè)數(shù)量級(jí)可以遠(yuǎn)超很多互聯(lián)網(wǎng)公司。HBase在讀寫(xiě)一致性方面非常出色,有很好的自動(dòng)Scale的能力,通過(guò)Block Cache和Bloom Filters可以很好的解決查詢問(wèn)題,是否在磁盤(pán)上也可以通過(guò)Bloom Filters來(lái)判定。
另一方面,Oracle把一部分邏輯會(huì)放在CPU/硬件里,對(duì)應(yīng)的HBase也會(huì)把一部分邏輯下推到對(duì)應(yīng)的RegionServer 上。對(duì)于一個(gè)分布系統(tǒng)來(lái)說(shuō),如果需要查詢一個(gè)條件,可以直接把這個(gè)簡(jiǎn)單調(diào)節(jié)推到對(duì)應(yīng)的RegionServer上執(zhí)行。再比如求和運(yùn)算,現(xiàn)在有一百億數(shù)據(jù),甚至一千億條數(shù)據(jù),分布在10個(gè)節(jié)點(diǎn)上,最快的求和方法是讓所有節(jié)點(diǎn)同時(shí)運(yùn)算,將這個(gè)條件下推得到所有對(duì)應(yīng)數(shù)據(jù)的和,最后收集到10個(gè)數(shù)據(jù)的和即可。其實(shí)還可以繼續(xù)往下推,這是比較復(fù)雜的數(shù)據(jù)庫(kù)優(yōu)化技術(shù),實(shí)際情況還會(huì)更復(fù)雜。這在 HBase 里面依賴 Coprocessor 來(lái)實(shí)現(xiàn)。
大家應(yīng)該對(duì)MVCC比較熟悉,也就是多版本,它的優(yōu)點(diǎn)在于可以多次讀取而不會(huì)block。然后還有一個(gè)很好的特性,假設(shè)你用的Database,MVCC在你沒(méi)有做compaction之前可以回到任何時(shí)間的數(shù)據(jù)?,F(xiàn)在云服務(wù)上也可以每隔半小時(shí)做一次快照,實(shí)際上如果使用MVCC回到任意一秒的話,可以完全不需要快照。
TiDB的優(yōu)勢(shì)
下面再介紹一下我們的產(chǎn)品 TiDB,Ti是元素周期表里的元素。大家如果了解我們團(tuán)隊(duì)的程序員,就知道他們都比較 Geek,取名字要么在希臘神話里選一個(gè)神的名字,或者在數(shù)學(xué)里找一個(gè)希臘字母, 但是看了一圈,好坑都已經(jīng)被占上了。于是,我們?cè)诨瘜W(xué)元素周期表里找了一個(gè)金屬作為項(xiàng)目名稱,對(duì)于Database而言,它必須是高速穩(wěn)定的,剛好鈦金屬有很強(qiáng)的防腐蝕性,所以選擇了鈦(Ti)。
因?yàn)門(mén)iDB的目標(biāo)是谷歌F1,所以自然會(huì)滿足以上特性。首先是可以滿足分布式一致,也就是說(shuō)對(duì)于應(yīng)用來(lái)說(shuō),不用關(guān)心后面分成多少個(gè)機(jī)器,事務(wù)的一致性是必須保證的,比如我們之前提到的A關(guān)注B,兩個(gè)互相加好友或者轉(zhuǎn)帳,可以直接利用一條SQL搞定,而無(wú)需擔(dān)心中間過(guò)程。另外一個(gè)特性是兼容MySQL協(xié)議,國(guó)內(nèi)大概有70% 的互聯(lián)網(wǎng)公司都在使用MySQL,為了考慮大家的遷移成本,我們會(huì)兼容MySQL協(xié)議。同時(shí),由于已經(jīng)很多APP在MySQL上運(yùn)行,為我們提供了充足的測(cè)試樣本。TiDB的測(cè)試有五百多萬(wàn)個(gè),每次提交一行代碼時(shí),后面大概有6個(gè)機(jī)器并行地跑Test,五百多萬(wàn)Test所需時(shí)間大約是十分鐘。為了照顧各種引擎愛(ài)好者,我們還支持了LevelDB 、RocksDB、LMDB、BoltDB等。TiDB主要是采用 Go 語(yǔ)言開(kāi)發(fā)的,其代碼簡(jiǎn)單、易于理解,而且性能非常高。
系統(tǒng)架構(gòu)
任何用MySQL協(xié)議寫(xiě)的程序都可以直接使用TiDB,其中間是MySQL協(xié)議相關(guān)的內(nèi)容,再往下是SQL Layer。其次是事務(wù)KV層,這正是F1和Spanner構(gòu)造得最為精密的地方。最底層的構(gòu)造是從KV開(kāi)始,在KV基礎(chǔ)上架一個(gè)分布式的KV層用于支持事務(wù),然后再讓SQL語(yǔ)句直接映射到KV層上。
接下來(lái),向大家介紹 現(xiàn)階段 TiDB 使用的分布式事務(wù)是如何在HBase上實(shí)現(xiàn)的,早期版本中,我們參考的是 Google 的 Percolator 的模型。首先假設(shè)有一個(gè)Client,先為其分配一個(gè) Timestamp,在Google論文中叫做Time Oracle,用來(lái)分配時(shí)間戳。分配之后可以做讀寫(xiě)操作,根據(jù)時(shí)間戳進(jìn)行快照讀。最后提交之前要先Prepare,Prepare的時(shí)候會(huì)檢測(cè)是否沖突,最后提交時(shí)會(huì)得到Commit,如果整個(gè)過(guò)程沒(méi)有任何沖突就可以提交。
上圖代表了一個(gè)實(shí)例,最初帳戶情況是Bob有10美金,而Joe有5美金。前面的數(shù)字代表其版本,當(dāng)前是第6個(gè)版本,指向的是第5個(gè)版本,為10美金,Joe是2美金。
假設(shè)Bob要轉(zhuǎn)4美金給Joe。第一步,要先轉(zhuǎn)出去4美金,10美金變成6美金,由于被扣掉4美金,然后會(huì)標(biāo)注一下自己是主鎖。
Joe當(dāng)前是第7個(gè)版本,因?yàn)樗玫搅?美金,所以余額變成了6美金,同時(shí)標(biāo)記自己指向另外一個(gè)主鎖Bob。
到第八個(gè)版本時(shí),主鎖會(huì)指向現(xiàn)在的7,這時(shí)可以把主鎖刪掉。如果訪問(wèn)的時(shí)候發(fā)現(xiàn)主鎖被刪除,那么主鎖沖突已不存在,可以進(jìn)行提交。同時(shí),它會(huì)把自己的鎖刪掉,中間還有一些其它的清理過(guò)程。
整個(gè)事務(wù)模型中會(huì)有單點(diǎn),從Time Oracle分配一個(gè)時(shí)間戳,單點(diǎn)決定了整個(gè)系統(tǒng)的性能。Google論文里有一個(gè)對(duì)應(yīng)描述,可以跑到兩百萬(wàn)每秒。因?yàn)槭聞?wù)開(kāi)始和結(jié)束的時(shí)候都需要取一個(gè)Timestamp,所以他們最快讀寫(xiě)事務(wù)的速度是一百萬(wàn)每秒,他們已經(jīng)在論文中實(shí)現(xiàn)。實(shí)際上,現(xiàn)在有更好的方式可以提高速度,如HLC和一些Time Oracle的改進(jìn)算法。
關(guān)于Spanner,我們重點(diǎn)參考對(duì)象是谷歌Spanner和F1。由于Spanner高度依賴于時(shí)鐘,所以谷歌有一套原子鐘和GPS時(shí)鐘,GPS信號(hào)可以給出地理位置和時(shí)間。為什么需要原子鐘呢?由于GPS時(shí)鐘特別容易受到干擾,比如天氣惡劣時(shí)GPS時(shí)鐘就不能運(yùn)行,而原子鐘仍然適用。
上圖是谷歌F1的一些信息,其中單獨(dú)標(biāo)記了谷歌F1的這篇論文,大家有興趣的話不妨細(xì)讀一番,目前整個(gè)TiDB所做的都是在實(shí)現(xiàn)這篇論文。假設(shè)有一千億數(shù)據(jù),你現(xiàn)在要給某一列加索引時(shí),在傳統(tǒng)數(shù)據(jù)庫(kù)上應(yīng)該如何操作?比如說(shuō)在分布式環(huán)境下,你用MySQL給一列添加一個(gè)索引,這幾乎很難實(shí)現(xiàn),而且還必須保證index的一致性。更多細(xì)節(jié)請(qǐng)參考論文。
TiDB是如何從SQL遷移到KV上的呢?由基礎(chǔ)知識(shí)可知,傳統(tǒng)的 RDBMS數(shù)據(jù)庫(kù)底下一般是一個(gè)B-Tree。對(duì)于分布式關(guān)系型數(shù)據(jù)庫(kù),站在更上層一點(diǎn)看,比如谷歌的F1,數(shù)據(jù)庫(kù)底層都是KV層,都在KV層邏輯下操作。如果有一個(gè)User Table,在TiDB里假設(shè)你的Table的結(jié)構(gòu)是由uid、name和email構(gòu)成。在TiDB里有一個(gè)隱藏列叫做RowID,所有的操作包括行鎖都是鎖的RowID。假設(shè)RowID是1,uid是XX,Name是Bob,Email是bob@Email.com,這都屬于元信息。即便你的Column name很長(zhǎng),但最后在數(shù)據(jù)庫(kù)里存儲(chǔ)的是原信息。在TiDB中, 每一列都有唯一的UID。
假設(shè)Table的ID是1,uid的 ID 是2,name的ID是3,email的ID是4。在數(shù)據(jù)庫(kù)中存儲(chǔ)為一個(gè)KV結(jié)構(gòu),然后對(duì)TableID、RowID 、ColumnID進(jìn)行重新編碼,直接將這個(gè)表的一行切成4個(gè)KV。這時(shí)候如果進(jìn)行select,Email等于某一個(gè)值的話,于是可以直接取出來(lái)相應(yīng)的值,速度非??臁?
兼容MySQL
TiDB對(duì)MySQL協(xié)議有很好的兼容性。有一些比較知名的MySQL應(yīng)用和管理工具,比如WordPress、PhpMyAdmin, MySQL Workbench,都可以直接基于TiDB運(yùn)行。而且數(shù)據(jù)可以無(wú)限擴(kuò)展,不再是單機(jī)數(shù)據(jù)庫(kù)。其次,TiDB還兼容各種ORM,比如XORM、Beego ORM等,能夠支持很多MySQL的應(yīng)用。每一次代碼更新,這些ORM Test會(huì)自動(dòng)運(yùn)行一次,從而保證與MySQL的兼容性,雖然還有一些比較細(xì)微的特性暫時(shí)沒(méi)有支持。現(xiàn)在已經(jīng)支持異步的 Schema 變更,對(duì)于 DDL 操作,不會(huì)阻塞線上的業(yè)務(wù)。
關(guān)于社區(qū)
目前 TiDB 完全開(kāi)源在Github上面。開(kāi)源和開(kāi)放的概念是兩回事,很多大公司,所謂的開(kāi)源只是把代碼上傳一下,國(guó)內(nèi)比較知名的案例也挺多的,大家知道很多項(xiàng)目都已經(jīng)放棄了維護(hù)。但是我們是打算完全以一個(gè)開(kāi)放的心態(tài)來(lái)做整個(gè)事情,全部的代碼,全部的討論, Code Review,Bug Tracking,Roadmap 都是開(kāi)源的,畢竟通用的分布式 OLTP 關(guān)系型數(shù)據(jù)庫(kù)是一個(gè)非常前沿而且極端重要的領(lǐng)域,未來(lái)是云上的 DBaaS 的重要組成部分,但是在這塊目前整個(gè)技術(shù)社區(qū),即使全球來(lái)看都沒(méi)有一個(gè)太成熟開(kāi)源解決方案,TiDB也目前也處于早期,從架構(gòu)上來(lái)看,我們將 SQL 層和 KV 層做了很徹底的分離,這也是我們希望更多開(kāi)發(fā)者能根據(jù)自己的需要更方便的進(jìn)行定制,我們也想得很清楚,依靠某一家公司,或者某幾個(gè)人的力量是不夠的,我們 PingCAP 只是將這一把火點(diǎn)起來(lái),將框架搭好,制定好透明和公平的規(guī)則,吸引更多的合作公司和獨(dú)立開(kāi)發(fā)者,一起將 TiDB 做成中國(guó)第一個(gè)世界頂級(jí)的開(kāi)源項(xiàng)目,實(shí)現(xiàn)共贏。
好的項(xiàng)目可以由社區(qū)進(jìn)行推動(dòng),就比如HBase,HBase不屬于任何一個(gè)公司,但是社區(qū)一直推動(dòng)它進(jìn)步。目前我們?cè)贕itHub狀態(tài)是有3200+的Star,有32個(gè)Contributors,算是開(kāi)了一個(gè)好頭,非常感謝大家,希望大家都能參與進(jìn)來(lái)。
(作者:OneAPM工程師 責(zé)編/仲浩)
總結(jié)
以上是生活随笔為你收集整理的TiDB:支持MySQL协议的分布式数据库解决方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 易维帮助台:连接客户,推动企业业务高速发
- 下一篇: MySQL-mysqldump备份方法