MySQL水平擴展

http://www.gpfeng.com/?p=657

問題背景

工作中遇到數據庫數據增長過快,單表一年之后預計到達35M行數據,可以預見MySQL性能將下降厲害,并且隨著業務的規模化,擔心單表將很難抗住并發壓力,出現故障后恢復時間變長對業務影響也會變大,因此需要考慮數據水平擴展,目前項目采用Golang開發,一個Google開發的以簡潔的語法,內建高并發模型,支持垃圾回收為主要特點的編譯型語言,性能比Java好,開發效率比C/C++高,其目標是替代C/C++

分庫分表

這四個字在阿里聽得最多,其實這也是被問題和壓力推動的,畢竟要支撐起那么大的業務,等著Oracle這樣的公司提供解決方案是不靠譜的,還不如卷起袖子自己干,接著就陸續搞出并開源了Cobar,TDDL(不給出鏈接了,太容易搜到)這些數據庫中間件,Cobar應該在TDDL之前,這個東西采用proxy方式,性能肯定不如以后續jdbc層面實現的TDDL,畢竟少了一次網絡轉發,現在TDDL在阿里核心系統上大量使用,不過外部用戶想用起來這個沒有那么容易,首先語言限制在了Java,另外還需要阿里配置管理服務Diamond的支持

要想水平擴展,就需要分庫分表的支持,分庫分表這四個字說起來很容易,按照id取模將數據打散分攤壓力,但是干完這些之后需要解決由此帶來的問題,這些很難:

1. 事務支持,擴庫/擴表后事務就成分布式的了,問題難度顯然上升了一個級別

2. 查詢結果合并,這個看起來不難,但是把order by/limit/查詢中不帶分表字段等加上,要解決的問題還也不少

3. join,這個更難

4. 分庫?分表?還是分庫分表?這個需要考慮并做一個決定

5. 分完后能否合并?分容易,和很難

6.。。。

開源解決方案

數據庫分庫分表開源產品有很多,下圖中列出了6個,它們已經在線上承載了較大壓力,主要分為2類:代理及非代理,非代理方式是以library方式提供,library負責SQL解析,路由計算等,位于driver層,實現難度較大,一般僅支持少數幾種語言;代理方式相當于一個多了一次轉發,應用程序連接的是代理服務器,由代理服務器負責路由計算并發送SQL到目的DB,多一次網絡,因此在性能上代理方式比非代理方式性能稍低

這些解決方案中MySQL Fabric/TDDL兩個為非代理方式,直接提供語言層面的支持,優點是性能會很好,劣勢是支持的語言很受限制,TDDL支持支Java,MySQL Faric支持Java/PHP/Python,想實現其他語言支持,相當于再次實現一次,不過目前Java/PHP/Python非常流行,能夠覆蓋的用戶很多了,TDDL對于外部用戶來說,先用起來沒有那么容易,和阿里平臺緊密綁定,如果有時間配置Diamond的話,可以好好研究,這里不進行深入探討

另外四個全部都是Proxy方式,以部分性能換來靈活性,這個就是仁者見仁智者見智的決定了,值得一提的是BAT中B也實現了一個Heisenberg的中間件,從部分代碼、配置以及文件結構來看,這個是從Cobar來的,應該優化了部分特性,不進行贅述,有興趣可以自己研究

MySQL Fabric

這個是MySQL官方水平擴展方案,號稱管理目標為:farm of mysqld,其實我比較看好這個東西,原因是個人喜歡簡潔的東西,總感覺Proxy方式多了一層轉發帶來了麻煩,除了性能外還有復雜性,運維起來也多了不少事情,畢竟這個進程down掉后可用性會受到影響,簡單才是美,希望MySQL Fabric能夠提供更多語言支持

Cobar

Cobar是阿里的中間件,以Proxy方式提供服務,在阿里內部大量使用,目前已經開源在github了,贊開源精神,據說在很多外部公司有一些成功使用的案例,配置比較容易,不需要依賴其他東西,有Java環境就OK,小試了一把,事務支持比較麻煩,需要通過set autocommit=0來實現,如果想要完美支持的話,還是需要修改JDBC或對應語言的MySQL library,分庫示意圖(Cobar中d.t分到兩個庫中:d1.t,d2.t):

Cobar支持分布式分表,但是不支持單庫分多表,前段(對接APP)和后端(對接MySQL)都實現了MySQL客戶端協議,比較友好,對于擴表結果集的合并也支持,寫其內部的SQL parse工程師功底應該比較深,顯示起事務會報錯,應該是“BEGIN”或者“Start transaction”不包含分表信息的緣故,但是這個可以通過defer到后面一個包含分表信息的SQL過來一起發到目標庫中執行或者通過分布式事務,比如2PC來支持,執行效果:

Atlas

雖然個人對數字公司沒啥好感,但是這個Atlas還是非常有特點的,它是基于MySQL-Proxy上二次開發的,主要支持兩個特性:分表和讀寫分離,但是分表的話只支持單庫多表,即事實上是不支持分布式分表的,所有分表都在同一個庫中,小試了一把,下面是分庫示意圖(四個分表t_0,t_1,t_2,t_3在同一個庫中):

Atlas擴展性限制在單實例最大性能,但是好處是:事務支持的很好,因為不存在跨庫事務,有些事情反而變得簡單,讀寫分離這個東西其實沒有水平擴展那么難,畢竟MySQL的備庫很好搭,不得不吐槽一下,通過atlas看到的不是一張完整的表,而是各個分表,只能通過分表的字段定位和操作數據,否則會報錯,與Cobar對比后,Atlas這個產品其實簡潔也粗糙很多,但是的確有它特有的應用場景:

另外,Atlas配置稍微簡單一些,但是分表算法支持上相對于Cobar顯得并不完善

Vitess

Vitess是Youtube開源的數據庫擴展及高可用方案,已經用于生產環境,功能強大,但是構架復雜,部署及運維成本較高,構架圖:

Vitess在app與database之間存在vtgate及vttablet兩個server,vttablet實現了MySQL連接池及row cache,與MySQL實例是一對一關系,可以當成是MySQL前端,一般與MySQL部署在一起,所有落到MySQL的query都需要經過vttablet,vtgate是一個proxy,負責路由計算以及app及vttablet之間的數據轉發,分表規則及配置數據存放在topology中(zookeeper實現),因此每個query執行需要走的路徑較長,雖然vttablet實現的連接池和row cache可以加速query執行速度,但是zookeeper訪問,app與vtgage、vtgate與vttablet之間兩次數據轉發都要走網絡,如果網絡不夠穩定可以預見性能損失較大

通過與vitess開發者確認,vtgate會緩存topology的分表規則數據,因此相對于其他proxy方案,只是多了一層vttablet的轉發代價,但是考慮到row cache的加速,最后性能應該相差不大

另外,這個項目是采用Golang語言的,這對于Golang項目優勢非常明顯,采用本文中Vitess之外的方案,go-sql-driver無法支持事務,詳見google-group vitess討論

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容