“讓我們看看未來(lái)的數(shù)據(jù)庫(kù)到底應(yīng)該是什么樣子吧。”
其實(shí)想寫這個(gè)蠻久了,趁著整個(gè) TiDB 項(xiàng)目即將 release beta 的時(shí)機(jī),作為 NewSQL 領(lǐng)域走在全球前沿的開源項(xiàng)目,我試著整理一下關(guān)于 TiDB 背后的一些理念和關(guān)鍵設(shè)計(jì)背后的想法,對(duì)于一起現(xiàn)在或者未來(lái)一起工作的 PingCAP 的小伙伴,也可以了解到目前為止這個(gè)項(xiàng)目是一步步走過(guò)來(lái)的,算是留個(gè)記錄。另外對(duì)于分布式系統(tǒng)和數(shù)據(jù)庫(kù)感興趣的朋友如果能從我的文章中得到一點(diǎn)啟發(fā),也算是沒白寫。還有我們也在招聘,我的郵箱是 huang at pingcap.com
TiDB 和 TiKV 項(xiàng)目均在 Github 上開源,歡迎 Star & Fork :)
https://github.com/pingcap/tidb
https://github.com/pingcap/tikv
緣起
在 2015 年初,我和 goroutine 做完 Codis 后,陷入了一個(gè)比較迷茫的狀態(tài),我們開始了一個(gè)新的項(xiàng)目,希望能在緩存之下解決關(guān)系型數(shù)據(jù)庫(kù)的水平擴(kuò)展問(wèn)題,也就是的 mp 這個(gè)項(xiàng)目,那時(shí)在豌豆莢內(nèi)部,使用的是基于阿里開源的 cobar 的 MySQL sharding 方案,不管是從水平擴(kuò)展能力和易用性來(lái)說(shuō),都是達(dá)到了一些瓶頸,希望尋求更好的方案,當(dāng)時(shí)希望參考 vitess,但在不損失 MySQL 兼容的基礎(chǔ)之上,加入一些特性進(jìn)來(lái),總之就是一個(gè)不那么重的 vitess,但是本質(zhì)上仍然是一個(gè) MySQL 中間件。當(dāng)時(shí)做的特沮喪,業(yè)務(wù)層仍然沒有透明的事務(wù)支持,仍然沒有辦法做很優(yōu)雅的擴(kuò)容,MySQL 的同步機(jī)制仍然原始,我們還沒法動(dòng),總而言之,后來(lái)我們的判斷是:中間件的方案實(shí)在是太丑了。在一個(gè)幾乎所有東西都有水平擴(kuò)展方案的今天,我們發(fā)現(xiàn)關(guān)系型數(shù)據(jù)庫(kù)上,仍然沒有任何比較優(yōu)雅的方案,唯一能找到的我們認(rèn)可方案是 Google 的 Spanner,正好 goroutine 之前一直在 follow 著 CockroachDB 這個(gè)項(xiàng)目,但是對(duì)于 Cockroach 的一些理念有著自己不同的看法,于是我們就萌生了自己去做更加 "正統(tǒng)" 的 Spanner 和 F1 開源實(shí)現(xiàn)的想法,出于一些機(jī)緣巧合,拿到了一筆相當(dāng)不錯(cuò)的天使投資(嗯,我們的早期天使很有眼光 :D,不過(guò)因?yàn)檫@是技術(shù) blog,就不提融資和創(chuàng)業(yè)的事情了),拉上了 cuiqiu,三個(gè)碼農(nóng)從豌豆莢出來(lái)自己開搞。
初探
我們最早還是很天真的,覺得既然要兼容 MySQL,那最簡(jiǎn)單的方法就是給 MySQL 寫個(gè)存儲(chǔ)引擎唄,這還不簡(jiǎn)單,然后我們花了幾天時(shí)間,寫了一個(gè) MySQL 的存儲(chǔ)引擎接入 CockroachDB,當(dāng)然結(jié)果可想而知,效果并不理想,原因是多方面的,主要的原因還是 MySQL 這樣的單機(jī)數(shù)據(jù)庫(kù)的 SQL 優(yōu)化器其實(shí)并不是為底層是分布式存儲(chǔ)設(shè)計(jì)的,其實(shí)后來(lái)看看,SQL 優(yōu)化器這邊需要很多存儲(chǔ)引擎的很多信息,比如數(shù)據(jù)的分布,表的大小等等,而且對(duì)于分布式數(shù)據(jù)庫(kù)來(lái)說(shuō),盡可能的將計(jì)算推到存儲(chǔ)節(jié)點(diǎn)帶來(lái)的性能提升會(huì)更大,也就是 MPP,復(fù)用 MySQL 幾乎完全沒可能。
接下來(lái),大概 2015 年的 5 月下旬,我們開始了 TiDB 項(xiàng)目,目標(biāo)就是先完成 Google F1 的實(shí)現(xiàn),也就是分布式 SQL 引擎這一層。
不同于 CockroachDB,我們先做的是 SQL Layer,其實(shí)背后的理由也很簡(jiǎn)單:SQL 是我們希望用戶最終的用戶接口,用戶并不需要關(guān)心底層的存儲(chǔ)實(shí)現(xiàn),只需要無(wú)心智負(fù)擔(dān)的當(dāng) MySQL 使用就好,這層是最接近用戶的一層。從某方面來(lái)講,用戶的使用方式?jīng)Q定了你下層的存儲(chǔ)引擎的實(shí)現(xiàn),如果你早期并沒有對(duì)用戶的使用模型進(jìn)行限制和設(shè)定,直接從底層開始寫,很容易導(dǎo)致缺乏方向感,很可能做很多無(wú)用功,如果有對(duì) Cockroach 熟悉的同學(xué)可能還記得,在去年年中時(shí),Cockroach 拋棄掉了 Structure API,后來(lái)也拋棄了他們從 vitess 中提取出來(lái)的 SQL Parser,就是典型的例子。
同時(shí)早期 SQL Layer 的目標(biāo)非常明確,就是 MySQL 的語(yǔ)法及協(xié)議級(jí)別的兼容,但是麻雀雖小五臟俱全,需要有一個(gè)可用而且可控的 Parser 和 SQL 優(yōu)化器,看上去很難,但是這個(gè)工作其實(shí)相對(duì)于去 hack MySQL 是簡(jiǎn)單很多的。而且我們選擇了 Go 語(yǔ)言來(lái)開發(fā),開發(fā)效率會(huì)比 C/C++ 高很多。
早期我們堅(jiān)決選擇 MySQL 兼容帶來(lái)的另一個(gè)好處就是測(cè)試可以做得比較充分,MySQL 社區(qū)積累了那么多年的集成用例,ORM 框架的測(cè)試,各種語(yǔ)言客戶端的測(cè)試,SQL logic tests 數(shù)不勝數(shù)。做數(shù)據(jù)庫(kù)最困難并不在于寫出來(lái),而是在于去證明它是正確的,如果你憑空發(fā)明一套協(xié)議和語(yǔ)法,光是寫測(cè)試用例對(duì)于初創(chuàng)團(tuán)隊(duì)就是不可能的事情。到現(xiàn)在,我們每次提交,我們的 CI 會(huì)跑六百萬(wàn)以上個(gè)測(cè)試用例,當(dāng)然這比起 Oracle 的級(jí)別還有很長(zhǎng)的距離,但是我們已經(jīng)在路上。另外獨(dú)立的 SQL Layer 暗示著我們并不需要一個(gè)真正的分布式存儲(chǔ)就可以開始進(jìn)行測(cè)試,同時(shí)很多工作可以并行起來(lái),事實(shí)上我們甚至在去年 11 月時(shí)嘗試接入了 HBase 作為第一個(gè)分布式的底層存儲(chǔ),這個(gè)事情后續(xù)再說(shuō)。選擇從 SQL 入手從現(xiàn)在看來(lái),這是一個(gè)非常正確的決定。
未完待續(xù),明天再寫。