談談MySQL水平擴展

問題背景

工作中遇到數據庫數據增長過快,單表一年之後預計到達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,多一次網絡,因此在性能上代理方式比非代理方式性能稍低

db-scale

這些解決方案中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-frame

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

cobar-mysql

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

atlas-frame

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

atlas-cmd

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

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

vitess

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討論

總結

本文源於項目實際需求,對國內外開源的MySQL水平擴展方案做了一個簡單總結,可以看到國內互聯網公司這這方面做得很不錯,再次爲他們的開源精神點贊


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章