《云數據庫AWS Aurora最詳解讀!》要點:
本文介紹了云數據庫AWS Aurora最詳解讀!,希望對您有用。如果有疑問,可以聯系我們。
作者介紹
朱閱岸,中國人民大學博士,現供職于騰訊云數據庫團隊.研究方向主要為數據庫系統理論與實現、新硬件平臺下的數據庫系統以及TP+AP型混合系統.
Aurora作為AWS云上的關系數據庫,完美契合了企業級數據庫系統對高可用性、性能和擴展性、云服務托管的需求.在本月中旬剛剛結束的AWS re:Invent 2017大會與數據庫頂級會議SIGMOD上,Amazon首度公開了Aurora的技術細節,本文系作者結合自身理解寫作而成,權當拋磚引玉.
Aurora是Amazon為云計算而專門定制的一款關系型數據庫.其目標主要是最小化網絡IO,提升系統的可擴展性與可用性.Aurora的設計哲學是log?is?database,對數據的更改只寫日志,也即write-once.Aurora系統設計人員認為傳統的數據庫不論如何擴展都在復制整個系統棧,在不同的層面做耦合;為了更好地適應云計算,他們認為應該將數據庫系統這個“盒子”打開,在不同的層面進行擴展.Aurora將恢復子系統委托給底層可靠的存儲系統,依賴這個來保障系統服務層級(Service?Level?Agreement,?SLA).
針對Amazon云生態環境做了相應優化以后,在某些工作負載下,Aurora的性能可以比MySQL5.7高出10倍以上.下面我們從不同方面深入解讀Aurora的設計理念.
關系數據庫系統中,處理事務的過程通常被視為一種分層的行為.系統在頂層對SQL語句進行解析,然后將得到的語法樹傳遞給查詢優化器層.查詢優化器利用啟發式規則和統計信息為每個關系操作符選取最優的策略.這個階段產生的物理執行計劃與邏輯存儲層交互,完成相應的操作.
在本文中,將事務處理引擎簡化為兩層模型:查詢解析、查詢執行以及查詢優化視為查詢處理引擎(Process Engine,PE);邏輯層存儲和物理層存儲統稱存儲引擎(Storage Engine,SE).這對應MySQL可插拔存儲的兩層架構.
定義數據庫服務器集群的架構決策的關鍵點在于集群共享發生的程度,它定義協調動作發生在什么層以及哪個層(PE和SE)將被復制或者共享.這不僅確定了系統在可擴展性和靈活性上的權衡,而且關系到每一種架構在現成的數據庫服務器上的適用性.以下是四個具有代表性的架構:
圖1. 不同的數據庫系統架構
集群管理軟件確保DBMS服務器只在連接到共享磁盤上的一個節點上運行,節點之間通常使用存儲區域網絡(SAN)互聯.如果當前活動節點崩潰,強制卸載該服務,并在不同的節點上啟動服務器.標準日志恢復過程可確保在磁盤上的數據的一致性,因此SDF適用任何DBMS.這種方法的一個變體可以在沒有物理共享磁盤的情況下通過使用諸如DRBD的卷復制器達到相同效果.否則,磁盤冗余由RAID配置提供.
這種架構專門為解決服務器崩潰問題而設計,它通常部署在一個簡單的兩服務器配置.如在圖1(b)所示,協調僅發生在DBMS外部,確保僅有一個服務器加載共享卷.如果文件安裝在多個節點上,它甚至不能分發只讀負載到備用節點,因為緩存一致性的問題會出現.由于復制是在裸盤上執行,在面對更新的時候,無論是PE或SE都不需要被復制,該架構在系統崩潰的時候會導致短暫的不可用情況發生.
允許多個節點同時訪問共享存儲需要保證緩存一致.具體地說,每個數據塊的所有權隨著時間的變化而不同,特別是當集群應用觸發一個寫操作.分布式并發控制機制負責將頁面所有權移交到對應實例.在這過程中,即使頁面變臟,也無需進行I/O操作.讀操作是共享操作,每當應用發送讀請求,數據頁的所有者復制該頁面.任何時候數據塊的寫回操作僅由一個副本進行.
如在圖1(c)所示,協調動作在存儲引擎層內進行.這種體系結構的一個例子是Oracle的RAC,這是基于Oracle并行服務器(OPS)和Cache Fusion技術.
這種架構主要是針對服務器可用的CPU和內存帶寬上進行擴展.它提供與SDF等同的容錯能力,因為大多數服務堆棧在面對更新事務的時候仍然沒有被復制.
通過完全隔離后端服務器,中間件層攔截所有客戶機請求并將其轉發到獨立副本.因為只讀請求在可用節點之間得到平衡從而達到系統可擴展.因此,只有更新事務需要積極地在所有副本進行復制.控制器扮演包裝器的角色.對于請求者而言,它充當服務器,提供相同的客戶端接口.對于原始的服務器而言,該中間層作為客戶端.群集節點之間沒有直接的溝通,因為協調發生在服務器之外,如圖1(d)所示.一個流行的實現是由Sequoia提供的,之前叫做C-JDBC,可以移植到多種后端服務器.
可擴展性上的主要缺點就是更新語句必須是完全確定的,并且需要小心調度以避免沖突從而導致非確定的執行結果和數據庫不一致. 實際上,這通常意味著不允許并發執行更新事務.這個架構的目標主要還是增強服務器在面對大多以讀為主的工作負載能力.通過完全隔離后端服務器,在處理更新事務的時候,它在所有數據庫系統的軟件層重復執行,從而容許PE和SE的故障情況.事實上,可移植的實現,例如Sequoia,甚至支持多樣的DBMS.它甚至可以在崩潰的狀態上進行投票,以掩蓋錯誤的備份.
在無共享集群,可以使用基于認證協議避免主動復制更新事務.每個事務直接在副本上執行,而沒有任何先驗協調.因此,事務僅需要根據本地的并發控制協議在本地進行同步.僅在提交之前,協調的過程才開始.這個時候,發起協調的副本采用全序組通信原語廣播更新.這將導致所有節點采用完全相同的更新序列,然后通過測試可能的沖突獲取認證.PostgreSQL-R,Group Replication,Garela等屬于這類架構的范疇.由于協調發生在PE與SE之間如圖1(e),它能夠隨著更新密集型工作負載的擴展而執行更細粒度的同步.這方法能夠接受存儲引擎和磁盤層的物理損壞.
Aurora給人眼前一亮的是它的架構.其體系架構更類似SDP,但是它將更新局限在一個DB服務器上,避免了分布式并發控制協議.Aurora設計者們認為,傳統的數據庫實現可擴展不管是做Sharding、還是分布式、或者共享存儲(Oracle RAC),本質上都是在數據庫的不同層面耦合(SNA在應用層,分布式是在SQL層,SDP是在緩存層),擴展后的每個實例的程序棧仍然是原來的多層結構.Aurora認為從成本、部署靈活性及可用性等因素考慮,應該考慮把數據庫的各層打開,然后在每個層單獨做擴展.傳統的數據庫系統,例如MySQL、PostgreSQL以及Oracle,將所有的功能模塊封裝成一個整體,而Aurora則是將數據庫的緩沖區管理、恢復子系統從這個整體剝離出來,單獨定制擴展.
Amazon聲稱Aurora完全兼容MySQL,具備商業數據庫的性能與穩定以及開源項目的低成本和易用性.下面詳細介紹Aurora的設計理念.
相比傳統的數據庫系統架構,Aurora具有以下三個明顯的優點.
首先,在跨數據中心環境將存儲作為一個獨立的、具有容錯以及自修復能力的服務模塊,使得數據庫系統免受性能抖動和存儲或者網絡故障的干擾.Aurora設計人員觀察到持久層的故障可以認為是系統長時間不可用事件,而系統不可用事件又可以建模為長時間的系統性能抖動.一個設計良好的系統可以無差別地處理這些問題.也就是,Aurora通過底層可靠的存儲系統保證數據庫系統的服務層級(Service Level Agreement, SLA).
第二,Aurora的設計理念是日志即數據.通過只將重做日志記錄寫入存儲層,系統可以將網絡的IOPS減少一個數據量級.一旦移除了網絡I/O瓶頸,在MySQL的代碼基礎上可以針對各種資源競爭進行大量優化,獲得大幅的性能提升.
第三,將數據庫系統中一度被認為最復雜與關鍵的功能(例如重做、備份等)委托給底層的分布式存儲.存儲系統以異步方式持續在后臺并行構造最新版本的數據.這使得Aurora可以達到即時恢復的效果.
存儲與計算分離,對于Aurora來說,并不是一個選擇題.在Amazon生態下,存儲本來就是和計算分離的,從邏輯上看,可以認為系統有一個巨大的共享存儲(或許使用的共享存儲就是計算節點的本地存儲).Aurora能夠做的事情,就是盡可能減少計算與存儲之間的帶寬需求,這是整個架構的關鍵所在.
Aurora通過只傳輸重做日志記錄以消除不必要的IO操作,降低成本,并確保資源可服務于讀/寫流量.與傳統的數據庫引擎不同,Amazon Aurora不會將修改后的數據庫頁面推送到存儲層,進一步節省了IO消耗.
在開始介紹實現細節之前,我們先給出如下術語定義.
表一 Aurora術語定義
下面具體介紹Aurora事務的正常讀寫、提交以及恢復過程.
1、Aurora寫流程
圖2. Aurora I/O流程
圖2所示,系統將數據庫文件切分成大小均等的存儲塊(一個存儲塊的大小為10GB),這些存儲塊分布在不同的存儲設備上.每個存儲塊都有專屬的redo日志.更新操作只寫日志而不寫數據頁.在適當的時機底層的存儲將日志合并成數據頁.也就是,計算與存儲之間只傳遞日志,而不傳遞臟頁,頁面的合并由存儲端來完成(不要把存儲端看做是一組單純的硬盤,它也包含了計算節點,可以把他看成是一組磁盤服務器,類似Oracle ExaData),注意到Aurora的存儲格式是基于日志結構的,所以這是一個整體的設計;系統對每個數據塊復制六次,分散在三個不同的可用區域AZs.Aurora認為寫操作已經持久化,僅當數據(redo日志)至少寫入六個備份數據的其中四份.Aurora不支持跨region復制.
系統設計人員采用如此數據副本放置策略的原因主要如下:
在大規模的云計算環境下,底層的磁盤、數據節點以及網絡的故障持續發生.每種故障有不同的持續時間以及波及范圍,例如,可能節點網絡的暫時不可用,重新啟動帶來的短暫的停機,或磁盤、節點、機架、網絡交換機等的永久性故障,甚至是整個數據中心的不可用.在備份系統里面一個常用的容錯方法是多數派投票協議.復制的數據項的每個副本都關聯一個投票,讀寫分別對應副本數Vr以及Vw.
為了滿足一致性,必須遵循以下兩條規則:
1)為了讀到最新的數據,必須滿足Vr + Vw > V.
這條法則確保寫操作涉及的副本與讀操作涉及的副本有交集,讀操作可以讀到最新版本的數據.
2)為了避免沖突,感知最新的寫入操作,寫操作涉及的副本數Vw 必須滿足 Vw > V/2.
通常的做法是容忍一個節點不能正常工作,設置V=3,讀多數派為Vr = 2,寫多數派為Vw = 2.Aurora的設計人員認為2/3的多數派是不夠的.他們將副本數提升為6個.每個AZ上兩個數據副本.這樣子的話,為了使得讀寫條件成立,那么Vr = 3,Vw = 4.這樣的配置使得系統可以容忍:
那這樣子的配置是否足夠健壯去容錯呢?
Aurora的設計者認為很難去降低兩個不相關事件的故障概率(兩個副本不可用),于是轉而限制平均修復時間,使得在平均修復時間內發生故障的概率幾乎不可能.他們將數據庫分片限制在10GB大小,在萬兆以太網下修復的時間低于10s,而在這個時間段內,一個機房不可用外加一個數據副本不可用的概率幾乎為0.這就是他們選擇10GB大小的數據分片以及每個分片需要復制6個副本的原因.
在介紹Aurora的更新事務流程之前,我們先看看傳統的數據庫系統的更新步驟.在類似MySQL的系統中需要將臟數據頁寫回堆文件或者b樹等對象中(延遲寫).此外,還需要將WAL日志寫入持久層存儲.通過重放WAL日志可以產生數據頁修改后鏡像.實際上,需要寫回的數據遠不止這些.Aurora設計人員給出了一個MySQL同步鏡像的例子.在這個例子中,寫回的數據除了數據頁、redo日志還包括binlog、避免數據頁損壞的雙寫文件以及元數據文件.寫回這些數據會帶來的巨大網絡I/O, 還有就是同步這些文件帶來的延遲太大了.
Aurora另辟蹊徑,采用并行寫多個副本保證可靠性,以及利用“log is database”的思想減少傳輸的數據.在Aurora中,一個更新事務的完整操作流程如下:
具體來講存儲節點執行如下工作:
以上8個步驟具體見圖3.
圖3 主實例與存儲節點的交互
當主實例收到4個以上的日志持久化ACK以后就完成事務提交,可以將執行結果返回給客戶端.
從Aurora的寫步驟看來,系統只需要等待寫入存儲節點的日志返回ACK即可,這是寫操作的唯一需要同步執行的地方.系統將大部分計算下推到底層的存儲層.因為只需寫入redo日志,Aurora也可以極大地減少網絡IO.從這個角度看來,評價Aurora是一款優秀的專為云計算而設計的DBMS,一點都不為過.
2、Aurora讀操作
雖然Aurora對寫操作進行了優化,僅僅寫入delta更新(redo日志);但是系統的讀操作還是以塊為單位.如同傳統的數據庫系統的做法,讀事務首先在緩沖區里查找所需的數據塊.如果存在,直接讀取即可;否則將請求下發到存儲系統.如果系統緩沖區已滿,那么需要淘汰一個頁面來裝下新讀入的數據頁.在已有的系統中,如果被淘汰的數據頁是臟頁,那么需要寫回磁盤.這可以確保隨后的事務都可以讀到最新版本的數據.
上面我們已經介紹了,Aurora并沒有將數據頁寫回存儲系統,只是簡單地將相應內存空間標記為free.但是,Aurora滿足類似的條件:緩沖區里的數據都是最新的.這個條件的保證通過將緩沖區里頁面LSN(關聯該頁面最新修改操作的日志記錄的LSN)大于文件持久化位點VDL的數據頁置換掉.
這個協議確保了:
1)頁面的所有改動都已經持久化到日志
2)在緩沖沒有該數據頁的情況下,可以構造出當前VDL的頁面.
隨著系統提交事務的不斷確定,VDL會不斷往前推移.最終VDL會大于修改頁面的PageLSN.此時,為了讓讀操作能夠讀到最新的數據,系統有兩種選擇:
系統只有在故障恢復重啟的時候會采用多數派讀的方式來確定系統的VDL.正常情況下,讀操作并沒有采用多數派讀的方法.Aurora給讀操作指派一個讀位點(read point),代表著讀請求產生時刻的VDL.系統維護著對應存儲節點的SCL,知道哪些節點可以滿足當前的讀操作.
3、事務提交
Aurora采用的是異步成組提交技術.在傳統的數據庫中,例如MySQL,為了減少磁盤IO采用成組提交技術.第一個寫日志緩沖區的線程需要等待預先設定的時間,然后再執行磁盤IO操作;或者等到日志緩沖區頁寫滿以后再執行IO操作.這樣子做的結果是第一個寫日志緩沖區的線程需要掛起等待,耗費時間.這是一個同步操作,在持久層存儲的ACK返回之前不能進行其它工作.
在Aurora中,寫操作不僅僅依賴Linux文件系統,還需要跟網絡交互.第一個寫日志緩沖區的線程可以馬上開始執行IO操作.每個提交事務都無需等待.線程將事務移動到提交列表,寫下該事務的commit LSN,轉而執行其他工作.在某個時刻,后臺進程負責將這些日志記錄收集起來,批量發送到存儲節點.當主實例收到對應某批次的日志記錄的4個ACK,VDL向前推移.系統有一個專門的線程不斷檢查提交事務隊列中commit LSN ≤ VDL的事務,然后回復客戶端.這等價于WAL協議.
在圖3中,提交隊列里面有3個掛起的提交請求,分別是Pending commit group1,Pending commit group2,以及Pending commit group3.主實例收到針對Pending group commit1的4個以上的日志持久化ACK以后,將系統VDL前移至22,第一組的狀態從pending變成committed.此時后臺線程檢查提交隊列,然后成批提交LSN小于等于22的事務T1,T2,T3.
注意,即使后面Pending commit group3先于Pending commit group2收集4個以上的存儲節點返回的持久化ACK,那么也不能移動數據庫持久化位點.因為,這個數據庫持久化位點是Aurora崩潰恢復以后決定開始重做的位點.跳過前面的成組提交的LSN會導致數據庫丟失某些數據.在系統崩潰恢復的時候,系統檢索最新的數據快照與相應的日志記錄(其LSN大于數據庫持久化位點),即可將數據庫恢復到最新的一致性狀態.
圖4. Aurora成組提交細節
4、恢復
大多數據庫系統的恢復協議采用類ARIES算法,依賴WAL日志將數據庫系統向前滾動到最新狀態.系統周期性地建立檢查點,將臟頁寫回磁盤,同時將檢查點記錄寫入日志.系統重啟的時候,頁面遇到丟失提交數據或者包含未提交數據.此時,恢復子系統將最新檢查點以后的redo日志進行重放,然后利用undo日志撤銷未提交事務的修改.通過這兩個步驟就可以將數據庫恢復到最新一致性狀態.災難恢復是一個很昂貴的操作,增加系統建立檢查點的頻率可以減少恢復時間.但是,建立檢查點會干擾正常執行的事務.Aurora并不需要做這樣子折中.
Aurora將恢復子系統的功能完全從事務的執行路徑上剝離出來,交給下面的存儲層.存儲節點持續以并行、異步、分布式的方式進行redo操作無需在性能與恢復時間上進行權衡.圖5給出了傳統DBMS與Aurora的恢復方式對比.
Aurora將數據庫文件切分成10GB大小的塊,每個塊都有專屬的日志記錄.在崩潰恢復的時候,系統利用多數派讀,確定運行時的一致性狀態.恢復模塊首先確定最大VCL(最大的順序LSN),截斷此后日志.進一步,可以將需要重放的日志限制在其LSN ≤ CPL.VDL取最大的CPL,LSN大于VDL的日志記錄都可以安全地截斷.例如,最大已完成的日志記錄的LSN為1007(尚未提交),但是系統的CPL為990,1000, 1100.系統可以確定LSN大于1000的日志記錄都可以忽略.確定完重放日志的LSN最大值以后,redo操作就可以并行在不同segment上執行了.
根據官方記載,Aurora完成崩潰恢復所耗費的時間大概是60S~120S左右.如果有其它副本存在,用戶可以指定主實例發生故障以后各副本提升為主實例的優先級,不會出現單點故障的情況.對比MySQL,重放操作只是單線程的模式進行,在系統更新負載較大的情況下,MySQL的故障恢復時間通常會比較長.為了及時更新備機上的數據,主實例需要將redo日志發送備機.備機收到redo日志以后,查找數據緩沖區.如果存在對應的數據塊,則將根據redo日志描述的操作應用在該數據塊上(日志LSN需要滿足小于等于VDL).否則,簡單地拋棄對應的日志記錄即可.數據頁的讀入操作要等到對該數據頁的請求到來的時候.
圖5. 傳統DBMS與Aurora的恢復方式對比
Aurora的設計讓我想起PBXT DBMS.PBXT作為MySQL的可插拔存儲引擎,定位在支持高并發場景.它沒有采用update-in-place的做法,而是利用append的方式進行更新,這減少了維護高速緩存一致性的開銷.同時,最近的工業界與學術界也都大致認同append更新方式對于Flash比較友好.最主要的是PBXT的設計哲學也是“log is database,write-once”,可以看見Aurora的影子.有興趣的同學可以看看研究下PBXT的源碼,或許更能加深對Aurora的理解.
總而言之,Aurora是針對云將MySQL進行深層定制的數據庫.Amazon通過緊密集成數據庫引擎和基于SSD的虛擬化存儲層(專為數據庫工作負載而開發),其性能和可用性相較于MySQL有大幅提升.通過降低了存儲系統的寫入次數使之更好的適應云環境的特點.Aurora在自動拓展存儲容量、自動修復數據、服務宕掉或者重啟時對緩存持久化的處理方式都是很有創新性的.最后是Aurora在RPO,RTO,兼容性以及擴展性方面的總結.
根據amazon官方文檔提供的參數[1],Aurora支持Point-In-Time?Recovery將數據庫還原到指定時間點,通常能夠在60s左右的時間完成故障恢復,不會高于120s.在2017年數據庫頂級會議SIGMOD上[2],Amazon公布了Aurora與MySQL5.6&5.7的性能對比:r3.8xlarge實例規格,sysbench壓測,Aurora的性能要比MySQL5.6與5.7優10倍以上.
表二 Aurora特性描述
參考文獻:
[1]?http://docs.aws.amazon.com/zh_cn/AmazonRDS/latest/UserGuide/Aurora.Managing.html
[2]?Amazon?Aurora:?Design?Considerations?for?High?Throughput Cloud-Native?Relational?Databases
文章來自微信公眾號:DBAplus社群
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/4085.html