雲計算爲現在的互聯網時代提供了更多的計算能力,乃至創造能力,關係型數據庫做爲全部應用不可或缺的重要部件,開箱即用,高性價加比特性的雲數據庫深受開發者的喜好。做爲一線的開發和運維人員,在阿里雲的線上值班中,咱們常常會碰到如下經典的客戶抱怨。
"你好,大家RDS的產品很棒,可是就是有點小貴,尤爲是我要買只讀實例的時候,成本是線性增長的,大家何時能便宜點?"
"我在4天前,手工作了一個備份,數據庫比較大,3T,大家說差很少要70個小時備份,這個。。有沒有什麼辦法加快一點,我老闆還着急要數據呢"
"我昨天花錢買了一個只讀實例,可是實例到今天還沒建立好,3T數據量是大了一點,有沒有方法能加快一點?"
"我拿大家的RDS MySQL測試了一下性能,可是貌似不太給力,跟我以前用的Oracle/SQL Server等一些商業數據庫差的有點多,有什麼辦法提升性能麼?若是不行,我仍是遷回自建的數據中心吧"
"你好,咱們公司有個數據庫,想遷到阿里雲RDS上,對RDS的產品品質咱們很滿意,只是咱們的數據庫有10T,請問一下,支持這麼大的實例麼?"
"你好,我用了大家的MySQL數據庫,最近幾天在作活動,主庫壓力比較大,只讀實例就延遲了,如今看過去貌似很難跟上,有什麼辦法麼?"mysql
上述抱怨/吐槽都來自用戶真實的案例,總結起來,傳統的雲數據庫因爲自身架構緣由,會遇到以下問題:算法
PolarDB是阿里雲ApsaraDB數據庫團隊研發的基於雲計算架構的下一代關係型數據庫(暫時僅支持MySQL,PostgreSQL正在緊鑼密鼓的開發中),其最大的特點是計算節點(主要作SQL解析以及存儲引擎計算的服務器)與存儲節點(主要作數據塊存儲,數據庫快照的服務器)分離,其次,與傳統的雲數據庫一個實例一份數據拷貝不一樣,同一個實例的全部節點(包括讀寫節點和只讀節點)都訪問存儲節點上的同一份數據,最後,藉助優秀的RDMA網絡以及最新的塊存儲技術,PolarDB的數據備份耗時能夠作到秒級別(備份時間與底層數據量無關),這三點相結合,咱們能夠推斷出PolarDB不但知足了公有云計算環境下用戶業務快速彈性擴展的剛性需求(只讀實例擴展時間與底層數據量無關),同時也知足了互聯網環境下用戶對數據庫服務器高可用的需求(服務器宕機後無需搬運數據重啓進程便可服務)。sql
圖1是PolarDB公測版本的整體架構圖。圖2是PolarDB數據庫內核上的架構。
解釋一下圖1中的各個組件。
上部分三個黑色框表示三臺計算節點,下部分三個藍色框表示三臺存儲節點。
在計算節點上,主要有三個重要部件:docker
DB Server: 即數據庫進程(Polar DataBase, 簡稱PolarDB)。PolarDB數據庫內核區分實例角色,目前包括三種角色,Primary,Standby和Replica。Primary即爲擁有讀寫權限的讀寫庫,Replica即爲只讀實例,僅僅擁有讀取數據的權限(後臺線程也不能修改數據),Primary和Replica採用Shared Everything架構,即底層共享同一份數據文件和日誌文件。StandBy節點擁有一份獨立的數據和日誌文件(如圖2所示),雖然用戶線程依然只有讀取數據的權限,可是後臺線程能夠更新數據,例如經過物理複製的方式從Primary節點更新增量數據。StandBy節點主要用來機房級別的容災以及建立跨可用區的只讀實例,公測階段暫時不開放。因爲只讀實例的擴展不須要拷貝數據,建立新的只讀實例不但速度快,並且很便宜,用戶只須要支付相應計算節點的成本便可。咱們稱StandBy和Replica節點爲Slave節點,Primary節點也可稱爲Master節點。數據庫
User Space File System: 即用戶態文件系統(Polar File Sytem, 簡稱PolarFS)。因爲多個主機的數據庫實例須要訪問塊存儲上的同一份數據,經常使用的Ext4等文件系統不支持多點掛載,PolarDB數據庫團隊自行研發了專用的用戶態文件系統,提供常見的文件讀寫查看接口,便於MySQL和相關的外圍運維工具使用文件系統支持相似O_DIRECT的非緩存方式讀寫數據,還支持數據頁原子寫,IO優先級等優秀的特性,爲上層數據庫的高性能提供告終實的保障。傳統的文件系統,因爲嵌入在操做系統內核中,每次系統文件讀寫操做都須要先陷入內核態,完成後再返回用戶態,形成效率低下。PolarFS以函數庫形式編譯在MySQL中,所以都運行在用戶態,從而減小了操做系統切換的開銷。緩存
Data Router & Cache: 即塊存儲系統客戶端(Polar Store Client, 別名PolarSwitch)。PolarFS收到讀寫請求後,會經過共享內存的方式把數據發送給PolarSwitch,PolarSwith是一個計算節點主機維度的後臺守護進程,接收主機上全部實例以及工具發來的讀寫塊存儲的請求。PolarSwith作簡單的聚合,統計後分發給相應的存儲節點上的守護進程。因而可知PolarSwitch是一個重資源的進程,若是處理很差,對計算節點上的數據庫實例有很大的影響,所以咱們的管控程序對其使用了CPU綁定,內存預分配,資源隔離等一些手段,而且同時部署了高效可靠的監控系統,保證其穩定運行。安全
Data Chunk Server: 即塊存儲系統服務器端(Polar Store Server, 別名ChunkSever)。上述三個部件都運行在計算節點上,這個部件則運行在存儲節點上。主要負責相應數據塊的讀取。數據塊的大小目前爲10GB,每一個數據塊都有三個副本(位於三臺不一樣的存儲節點上),兩個副本寫成功,纔給客戶端返回成功。支持數據塊維度的高可用,即若是一個數據塊發生不可用,能夠在上層無感知的狀況下秒級恢復。此外,PolarStore使用了相似Copy On Write技術,支持秒級快照,即對數據庫來講,無論底層數據有多大,都能快速完成全量數據備份,所以PolarDB支持高達100T的磁盤規格。
計算節點和存儲節點之間經過25G RDMA網絡鏈接,保證數據的傳輸瓶頸不會出如今網絡上。
此外,PolarDB還有一套完善的基於docker的管控系統,處理用戶下發的建立實例,刪除實例,建立帳號等任務,還包括完善詳細的監控,以及可靠的高可用切換。管控系統還維護了一套元數據庫,用以記錄各個數據塊的位置信息,提供給PolarSwitch,便於其轉發。
能夠說,PolarDB整個項目用了不少不少的新技術黑科技,給用戶直接的感覺是,又快(性能是官方MySQL6倍)又大(磁盤規格支持高達100T)又便宜(價格只有商業數據庫的1/10)。
接下里,咱們重點分析PolarDB在MySQL內核方面的功能加強、性能優化以及將來的規劃。便於讀者瞭解PolarDB數據庫內部運行的機制。性能優化
簡單的想,若是讀寫實例和只讀實例共享了底層的數據和日誌,只要把只讀數據庫配置文件中的數據目錄換成讀寫實例的目錄,貌似就能夠直接工做了。可是這樣會遇到不少問題,隨便列舉幾條:服務器
因此,仔細思考一下,多個數據庫實例共享同一份數據不是一件容易的事情。爲了解決上述問題,咱們須要只讀實例也按照讀寫實例更新數據的節奏來更新數據而且須要一套完善的髒頁刷盤機制。現代關係型數據庫中其實已經有一份記錄數據頁更新的Redolog事務日誌了,在MySQL中,就是ib_logfileXX相似這種文件,所以參考Binlog複製框架,PolarDB使用這種事務日誌構建了一套數據複製方法,在只讀實例上只須要順序應用讀寫實例產生的日誌便可,StandBy節點和Replica節點二者都須要更新內存中的數據結構,可是StandBy節點因爲獨立維護一份數據和日誌,因此須要把更新的增量數據寫入到本身的數據文件和日誌中,而Replica則不須要。因爲MySQL的Redolog相比於Binlog記錄的都是物理的數據頁(固然也有邏輯部分),因此咱們把這種複製稱爲物理複製。
因爲Redolog並無記錄用戶的SQL,僅僅記錄了最終的結果,即這個SQL執行後形成的數據頁變化,因此依賴這種複製架構,不須要SQL解析SQL優化,MySQL直接找到對應的文件中的數據頁,定位到指定偏移,直接更新便可。所以性能上能夠作到極致,畢竟併發粒度從以前的表級別變爲了數據頁級別。固然也會帶進來不少新的問題,簡單列舉幾個:
物理複製中的MVCC。MySQL的MVCC依賴Undo來獲取數據的多版本,若是Primary節點須要刪除一個Undo數據頁,這個時候若是Replica節點還在讀取的話就會有問題,同理,StandBy節點也有這個問題,所以咱們給客戶提供兩種方式,一種是全部Slave按期向Primary彙報本身的最大能刪除的Undo數據頁,Primary節點統籌安排,另一種是當Primary節點刪除Undo數據頁時候,Slave接收到日誌後,判斷即將被刪除的數據頁是否還在被使用,若是在使用則等待,超過一個時間後直接給客戶端報錯。此外,爲了讓Slave節點感知到事務的開始和結束以及時間點,咱們也在日誌中增長了很多邏輯日誌類型。
物理複製中的DDL。Primary節點刪除一個表以後,Replica可能還會有對此表的請求。所以,咱們約定,若是主庫對一個表進行了表結構變動操做,在操做返回成功前,必須通知到全部的Replica(有一個最大的超時時間),告訴他們,這個表已經被刪除了,後續的請求都失敗吧,具體實現上可使用MDL鎖來控制。固然這種強同步操做會給性能帶來極大的影響,後續咱們會對DDL作進一步的優化。
物理複製中的數據複製。除了複製引擎層的數據以外,PolarDB還須要考慮MySQL Server層表結構的一些文件複製,例如frm, opt文件等。此外,還須要考慮一些Server層的Cache一致性問題,包括權限信息,表級別的統計信息等。
物理複製中的日誌併發應用。既然物理日誌可讓咱們按照數據頁的維度來支持併發,那麼PolarDB須要充分的利用這個特性,同時保證在數據庫奔潰後也能正確的應用日誌和回滾事務。其實這部分的代碼邏輯與MySQL崩潰恢復的邏輯很像,PolarDB對其進行了複用和改造,作了大量的性能上的優化,保證物理複製又快有穩。
物理複製中的Change Buffer問題。Change Buffer本質上是爲了減小二級索引帶來的IO開銷而產生的一種特殊緩存機制。當對應的二級索引頁沒有被讀入內存時,暫時緩存起來,當數據頁後續被讀進內存時,再進行應用,這個特性也帶來的一些問題,例如Primary節點可能由於數據頁還未讀入內存,相應的操做還緩存在Change Buffer中,可是StandBy節點則由於不一樣的查詢請求致使這個數據頁已經讀入內存,發生了Change Buffer Merge操做,從而致使數據不一致,爲了解決這個問題,咱們引入shadow page的概念,把未修改的數據頁保存到其中,將change buffer記錄合併到原來的數據頁上,同時關閉該Mtr的redo log,這樣修改後的Page就不會放到flush list上了。此外,爲了保證Change Buffer merge中,不被用戶線程看到中間狀態,咱們須要加入新的日誌類型來控制。
物理複製中的髒頁控制。Primary節點不能毫無控制的刷髒頁,由於這樣Replica會讀取到不一致的數據頁,也會讀取到未提交事務的數據頁。咱們給出了一個策略,replica須要緩存全部未刷盤的數據變動(即RedoLog),只有primary節點把髒頁刷入盤後,replica緩存的日誌才能被釋放。採用這個策略後,replica內存的使用率與primary的刷髒速度就相關量起來,因此須要對primary節點的刷髒算法進行調整,同時也要考慮一些頻繁更新的數據頁致使primary節點刷髒緩慢的問題。
物理複製中的Query Cache問題,discard/import表空間問題,都須要考慮。
此外,在兼容性方面,因爲PolarDB存儲引擎暫時只兼容InnoDB數據表,Myisam和Tokudb暫時都不兼容,而系統表不少都是Myisam的,因此也須要轉換。
物理複製能帶來性能上的巨大提高,可是邏輯日誌因爲其良好的兼容性也並非一無可取,因此PolarDB依然保留了Binlog的邏輯,方便用戶開啓。網絡
傳統的MySQL數據庫並無實例角色這個概念,咱們只能經過查詢read_only這個變量還判斷實例當前的角色。PolarDB中引入三種角色,知足不一樣場景下的需求。Primary節點在初始化的時候指定,StandBy和Replica則經過後續的配置文件指定。
目前支持三種類型的切換,Primary降級爲StandBy,StandBy提高爲Primary以及Replica提高爲Primary。每次切換後,都會在系統表中記錄,便於後續查詢。Primary節點和StandBy節點因爲擁有各自的數據文件,在異步複製的模式下,容易形成數據不一致,咱們提供了一種機制,保證新StandBy的數據必定與新Primary的數據一致。想法很簡單,當新StandBy再次啓動時,去新Primary查詢,回滾掉多餘的數據便可,只是咱們這裏不使用基於Binlog的SQL FlashBack,而是基於Redolog的數據頁FlashBack,更加高效和準確。Primary節點和Replica節點,因爲共享同一份數據,不存在數據不一致的分享,當發生切換的時候,新Primary只須要把老Primary未應用完的日誌應用完便可,因爲這個也是並行的操做,速度很快。
這裏簡單提一下,目前公測階段的故障切換邏輯:首先是管控系統檢測到Primary不可用(或者發起主動運維操做),則鏈接上Primary(若是還能夠),kill全部用戶鏈接,設置read_only,設置PolarStore對此IP只讀(Primary節點和Replica節點必定在不一樣的計算節點上),接着,鏈接到即將升級的Replica上,設置PolarStore對此IP讀寫,MySQL從新以讀寫模式掛載PolarFS,最後執行Replica提高爲Primary的語句。正常狀況下,整個過程時間很短,30秒內便可切換完成,可是當Primary和Replica延遲比較大的時候,須要更多的時間,可是相比於以前Binlog的複製,延遲時間至少降低2個數量級。後續咱們會對這塊繼續進行深度優化,進一步提升實例可用性。
傳統的Binlog複製模式只有異步複製和半同步複製兩種。在PolarDB中,咱們還增長了強同步複製,即要求Slave節點應用完數據才返回成功,這個特性對複製特別敏感的用戶來講,是個好消息,能保證只讀實例查詢出來的數據必定與讀寫庫上查詢出來的同樣。此外,PolarDB還支持延遲複製功能,複製到指定事務,複製到指定時間點等,固然這幾個特性主要是提供給災備角色StandBy的。此外,爲了進一步減小複製延遲,若是Replica發現自身延遲超過某個閾值,就會自動開啓Boost模式(會影響實例上的讀),加速複製。若是Primary節點發現某個Replica延遲實在太大,出於安全考慮,會暫時把這個Replica踢出複製拓撲,這個時候只須要從新啓動一下Replica便可(因爲Replica不須要作奔潰恢復,重啓操做很快)。PolarDB還支持複製過濾功能,即只複製指定的幾個數據庫或者指定幾個表,這樣因爲不須要複製查詢不感興趣的數據,從而能夠進一步下降複製延遲。這裏提到的各類有趣的特性,在公測階段還暫時不支持,在不久的未來,會陸續開放給你們。
相似Binlog的日誌管理,PolarDB也提供了相似的機制和工具來管理Redolog。首先,與傳統MySQL循環使用Redolog不一樣,與Binlog相似,PolarDB中Redolog也是以文件編號遞增的方式來管理,並提供相應的刪除命令給管控系統使用。PolarDB依據PolarStore的全量備份和Redolog增量日誌爲客戶提供還原到任意時間點的功能。PolarDB還有一個專門用來解析Redolog日誌的工具mysqlredolog,相似Binlog解析工具mysqlbinlog,這個工具在系統診斷中很是有用。Redolog中,PolarDB也增長了很多獨特的日誌類型,爲了作到兼容性,Redolog也有版本管理機制。傳統的MySQL僅僅數據文件支持O_DIRECT,PolarDB爲了適配新的文件系統,Redolog日誌也支持O_DIRECT方式寫入。
此外,PolarDB對Undo日誌也進行了深度的開發,目前支持Online Undo Truncate,媽媽不再用擔憂個人ibdata數據文件過大啦。
PolarDB增長了那麼多功能,天然也會提供不少新的命令,例如用戶可使用SHOW POLAR STATUS
來查看相關信息,使用SHOW POLAR REPLICAS
來查看全部已經鏈接的replica節點。使用START POLAR SLAVE
來啓動複製,使用SHOW POLAR LOGS
來查看產生的Redolog文件,等等等。PolarDB在information_schema中也增長了好多表,有興趣的讀者能夠去看一下,這裏面到底存的是什麼。
目前數據庫內核支持(大概再過幾個月會提供給用戶使用)從RDS 5.6遷移到PolarDB上,流程主要以下,首先在RDS 5.6上使用xtrabackup作個全量的數據備份,接着在計算節點上,xtrabackup作恢復,成功後,經過PolarFS提供的運維工具把全部的數據文件放到PolarStore上,而後使用特定的參數啓動PolarDB,PolarDB會把RDS 5.6日誌文件格式轉換成PolarDB的Redolog,接着可使用Binlog方式追增量數據,當追上RDS 5.6的讀寫庫且到達用戶指定的切換時間,設置RDS 5.6讀寫庫只讀,而且PolarDB作一次重啓,關閉Binlog複製,最後把VIP切換到PolarDB上便可完成遷移工做。
除了上文提到的解析Redolog日誌工具外,因爲對源碼進行了大幅度的改動,PolarDB還對MySQL原生的TestCase Framework進行了改動,保證在共享數據日誌的場景下(Local FS/Disk and PolarFS/PolarStore)全部的Testcase能經過。
PolarDB除了擁有大量新的特性外,咱們還作了不少性能上的優化,這裏簡單列舉一些:
PolarDB目前已經公測,可是將來咱們還有不少有趣的特性能夠作,在性能方面也有不少的優化點,例如:
總之,PolarDB是阿里雲數據庫團隊爲雲計算時代定製的數據庫,擁有不少優秀的特性,是雲計算2.0時代產品進化的關鍵里程碑之一,也是開源數據庫生態的積極推進力。咱們將在9月下旬開放公測,期待你們的反饋。
http://www.infoq.com/cn/news/2017/08/ali-polardb
https://www.percona.com/live/data-performance-conference-2016/users/zhai-weixiang
https://www.percona.com/live/17/users/zhai-weixiang