作者簡介:李海翔,騰訊金融云數據庫技術專家。網名那海藍藍,熟悉PostgreSQL、MySQL、Informix等。數據庫內核技術。騰訊金融云數據庫技術專家。著有《數據庫查詢優化器的藝術》,即將出版新書《數據庫事務處理的藝術》。
導語:Amazon的Aurora自從問世,就備受關注,其性能和實現架構是被關注的熱點。2017年,Amazon發表了一篇論文,披露其實現的一些技術細節。本文在此背景下,對Aurora系統的實現從整體架構、存儲、事務處理三個方面進行深入探討,基于其論文和相關資料討論具體實現細節,又跳出其外、從數據庫內核技術實現的角度對Aurora做了一定的推測。接著對Aurora用技術構建起的強大云數據庫服務能力進行探索。最后總結了一些問題,以期有更多的討論和思考,一起來探索云數據庫的技術未來。
目錄
Amazon Aurora深度探索
1 Aurora的整體架構
1.1 物理設施與架構
1.2 核心技術與架構
1.3 其他組件
2 Aurora的存儲架構
2.1 存儲層的工作
2.2 儲存層的設計討論
2.3 Aurora設計的優點
3 Aurora的事務處理
3.1 持久性
3.2 事務與數據分布
3.3 事務處理
3.4 鎖管理
4 云服務能力
4.1 強化的云服務能力
4.2 萬能數據庫
5 小結
附錄
Amazon Aurora深度探索
2017年,Amazon在SIGMOD上發表了論文《Amazon Aurora: Design Considerations for High Throughput CloudNative Relational Databases》。
這篇論文,描述了Amazon的云數據庫Aurora的架構?;贛ySQL的Aurora對于單點寫多點讀的主從架構做了進一步的發展,使得事務和存儲引擎分離,為數據庫架構的發展提供了具有實戰意義的已實踐用例。其主要特點如下:
- 實踐了“日志即數據庫”[①]的理念。
- 事務引擎和存儲引擎分離。
- 數據緩沖區提前預熱。
- REDO日志從事務引擎中剝離,歸并到存儲引擎中。
- 儲存層可以有6個副本,多個副本之間通過Gossip協議可以保障數據的“自愈”能力。
- 主備服務的備機可達15份,提供強大的讀服務能力。
- 持續可靠的云數據庫的服務能力。
- 數據存儲跨多個區:提供了多級別容災能力。
- 數據容災能力:數據冗余、備份、實時恢復等多種能力集成到云服務,提高的數據的保障能力。
萬能數據庫的概念呼之欲出。之所以有這樣的設計,是因為Amazon認為:網絡IO已經成為數據庫最大的瓶頸[②]。
1. Aurora的整體架構
認識Aurora的整體架構,需要先理解AWS的物理設施,而論文中對Aurora基于的物理設施著墨不多,所以我們先來掌握物理設施與整體架構的關系。
1.1 物理設施與架構
Aurora的計算節點和存儲節點分離,分別位于不同的VPC(Virtual Private Cloud)中。這是Aurora架構最亮眼之處。
如圖1-1,用戶的應用,通過Customer VPC接入,然后可以讀寫位于不同AZ(Availability Zone)的數據庫。而不同的AZ分布于全球的不同的Region中(如圖1-2[③],截止到2017年初,AWS全球有16個區域即Region,有42個可用區即AZ,每個Region至少有2個AZ。而每個AZ由兩到多個數據中心組成,數據中心不跨AZ,每個AZ內部的數據延遲低于0.25ms[④]。AWS文檔稱,AZ之間的延遲低于2ms通常小于1ms)。
數據庫的部署,是一主多從的集群架構,圖1-1的Primary RW DB是寫數據的節點,只能有一個(這點說明Aurora還是傳統的數據庫架構,不是真正的對等分布式架構,這點也是一些批評者認為Aurora缺乏真正創新之處)。而Secondary RO DB是只讀的從節點,由零到多個備節點組成,最多可以有15個。主從節點可以位于不同的AZ(最多位于3個VPC,需要3個AZ)但需要位于同一個Region內,節點通過RDS (Relational Database Service)來交互。
RDS是由位于每個節點上的稱為HM(HostManager)的agent來提供主從集群的狀態監控、以應對主節點fail over的問題以便進行HA調度、以及某個從節點fail over需要被替換等問題。這樣的監控服務,稱為control plane。
圖1-1 Aurora整體架構
圖1-2 Aurora的Region分布圖
數據庫的計算服務和存儲分離,數據緩沖區和持久化的“數據”(對于Aurora實則是日志和由日志轉化來的以page為單位的數據,而不是直接由數據緩沖區刷出的page存儲的數據)位于Storage VPC中,這樣和計算節點在物理層面隔離。一個主從實例,其物理存儲需要位于同一個Region中,這樣的存儲稱為EC2 VMs集群,其是由一個個使用了SSD的Storage Node組成。
1.2 核心技術與架構
Aurora提倡“the log is the database”,這是其設計的核心。圍繞這個觀點,傳統數據庫的組件架構,發生了一些變化。
對于Aurora,每一個存儲節點,如圖1-3,由兩部分構成。
第一部分:Caching
第一部分是“Caching”,這是一個重要的關鍵點,可惜論文沒有描述其細節。
如同傳統數據庫架構的數據緩沖區,向事務層提供數據。傳統數據庫架構的數據緩沖區,向上起著消耗存儲IO的I加載數據到內存供計算層讀寫數據的作用、向下起著消耗IO的O寫出臟數據到存儲層以實現數據持久存儲的作用。對于一個寫密集的OLTP系統,大量隨機寫花費了很多時間,系統的性能因此經常表現為存儲層的IO瓶頸。盡管checkpoint技術緩解了每個寫操作刷出臟數據的沖動,盡管SSD的使用緩解了存儲層的瓶頸,但是,畢竟存儲層的I與O的時間消耗還是巨大的,尤其是對于隨機寫密集的OLTP系統。
Aurora的設計,消除了臟數據刷出的過程,數據緩沖區的作用,只是加載數據供上層使用,而臟數據不必從數據緩沖區刷出到物理存儲上,這對于隨機寫密集的OLTP系統而言,是一個福音,性能的瓶頸點被去掉了一個(如圖1-3,在“Caching”和“Logging+Storage”之間,豎線的箭頭,應該是指向“Caching”的,以表示數據只是加載到Caching中,不存在臟數據的刷出操作)。
但是,觀察圖1-3,“Caching”是位于了存儲層內還是計算層內?論文沒有明示。
從圖1-3觀察,似乎“Caching”是存儲層和計算層所共用的一個組件,那么就可能存在這樣的一個兩層設計:位于存儲層和計算層各有一部分“Caching”,這兩部分“Caching”組合成為一個邏輯上的“Caching”,而邏輯意義上的“Caching”似乎在AWS認為,其更像是屬于計算層的。如下文引自論文原文:
Althougheach instance still includes most of the components of a traditional kernel(query processor, transactions, locking, buffercache, access methods and undo management) several functions (redologging, durable storage, crash recovery,and backup/restore) are off-loaded tothe storage service.
位于存儲層內的“Caching”,更像是一個分布式的共享文件系統,為了提高性能也許是一個分布式內存型的共享文件系統,為主從架構的數據庫提供高速讀服務,此點妙處,論文沒有點出,這里權做推測。存儲層如果能為所有的主備節點提供一致的緩沖數據,則有更為積極的意義,可以對比參考的如Oracle的RAC。
而位于計算層內的“Caching”,是單個數據庫實例讀數據的場所,獨立使用。
Aurora提供了一個“自動恢復”緩沖預熱的功能,其官方宣稱如下:
“自動恢復”緩存預熱
當數據庫在關閉后啟動或在發生故障后重啟時,Aurora 將對緩沖池緩存進行“預熱”。即,Aurora 會用內存頁面緩存中存儲的已知常用查詢頁面預加載緩沖池。這樣,緩沖池便無需從正常的數據庫使用“預熱”,從而提高性能。
Aurora 頁面緩存將通過數據庫中的單獨過程進行管理,這將允許頁面緩存獨立于數據庫進行“自動恢復”。在出現極少發生的數據庫故障時,頁面緩存將保留在內存中,這將確保在數據庫重新啟動時,使用最新狀態預熱緩沖池。
源自:
http://docs.amazonaws.cn/AmazonRDS/latest/UserGuide/Aurora.Overview.html
“在出現極少發生的數據庫故障時,頁面緩存將保留在內存中”,這句話很重要,一是其表明數據不用很耗時地重新加載了,二是數據庫實例崩潰前的數據內存狀態被保留著,三是數據庫崩潰重啟不必再執行“故障恢復”的過程即使用REDO日志重新回放以保障數據的一致性了(事務的ACID中的C特性)。
那么,頁面緩沖是一直保留在哪個節點的內存中?是存儲節點還是計算節點?如果是位于計算節點,那么備機節點發生數據庫故障時,這樣的機制不會對備機節點起到保護作用。如果是位于存儲節點,則存儲作為一個服務,服務了一主多備的多個節點,則能更好的發揮“自動恢復”緩沖預熱的功效(存儲節點的caching一直存在,向上層計算節點的caching提供數據批量加載服務,但也許不是這樣,而是提供一個接口,能夠向計算層的caching提供高速讀數據的服務,論文沒有更多的重要細節披露,權做推測)。由此看來,“Caching”層的兩層設計,當是有價值的(價值點是“自動恢復”緩沖預熱,由存儲層提供此項服務),與預寫日志功能從事務層剝離是關聯的設計。
這就又回到前面引用的論文中的那段英文,其表明:Aurora的設計,把REDO日志、持久化存儲、系統故障恢復、物理備份與物理恢復這些功能模塊,歸屬到了存儲層。由此就引出了Aurora的另外一個重要話題---存儲層的設計(如下的第二部分和下一節內容)。
對于計算層的“Caching”,其實現將被大為簡化。臟數據不再被寫出,臟頁面不再需要復雜的淘汰策略進行管理,消除了后臺的寫任務線程,同時也消除了checkpoint線程的工作,數據緩沖區的管理大為簡化,即降低了系統的復雜度又減少了時間的消耗、還避免了因執行后臺寫等任務帶來的性能抖動,解耦帶來的功效確實宜人。Aurora額外需要做的一項新工作是:only pages with a long chain of modifications need to berematerialized。而計算層的“Caching”變成單向的讀入,此時需要解決的,僅僅是什么樣的數據可以(從存儲層的Caching)被讀入的問題,而論文原文描述:
Theguarantee is implemented by evicting a page from the cache only if its “pageLSN” (identifying the log record associated with the latest change to the page)is greater than or equal tothe VDL.
VDL是存儲層的最小一致點(參見3.1節),標識了可用日志的最低范圍,比VDL還老的數據頁不再可用,所以顯然如上的論文原文是錯誤的。如果有比當前數據頁還新的數據頁被從日志中恢復,則其LSN一定更大,所以頁面換入的條件是:存儲層Caching中存在頁面的LSN值更大的;頁面被換出的條件是:Caching中的頁面的LSN小于等于VDL。而且,這一定是發生在備機需要更新其計算層的Caching時刻,而不是主機需要更新其計算層的Caching時刻。存在此種情況,其原因已經很明顯,主機修改數據,形成臟頁,這樣的臟頁(數據的后像)才能作為REDO日志的一部分被主機刷出;而主機不會刷出臟頁,所以被修改后的數據頁應該一直在內存中,而被修改過的數據頁如果反復被修改,則意味著主機Caching中的相應臟頁數據一定是最新的,沒有必要從存儲層的Caching中讀入“繞道恢復后的數據頁”。如果以上猜想不成立,除非Aurora生成REDO日志時,存于REDO日志中的數據頁部分采取先復制然后其上的數據項被修改這樣的方式。可是多做一次復制,又有何必要呢?
圖1-3 存儲結構圖
另外,如果“Caching”確實存在兩層(另外一個證據,參加圖1-4[⑤]),而如2.1節所述,存儲層也在處理日志、并依據日志生成頁數據,則存儲節點也存在處理數據的能力,就類似于Oracle的ExaData。這樣導致的一個可能是,兩層的“Caching”還是可能存在差別的。存儲層的“Caching”能夠幫助做謂詞下推的工作,然后把較少的數據傳回計算層的“Caching”,由此實現類似Oracle的ExaData的智能掃描(Smart Scan)的功能。是否如此,或者Aorora的體系結構和功能模塊在未來繼續演變的時候,是否會在存儲層內的“Caching”做足文章,可以拭目以待。不過,目前制約存儲層內的“Caching”起更大作用的因素,主要在于分布式事務的機制的選取和InnoDB自身的事務實現機制。詳細討論參見3.2節。
圖1-4 存儲層的“Shared storage column”與計算層的“Caching”構成的兩層數據緩沖結構
第二部分:Logging+Storage
第二部分是“Logging+Storage”,日志和持久化存儲。日志與傳統數據庫對于預寫日志(WAL)的利用方式與MySQL不同,這點是Aurora實現計算與存儲分離的核心(下一節詳述存儲層實現細節)。
如圖1-5所示,對于日志數據,從Primary RW DB寫出到一個存儲節點,每個AZ至少有2份數據,寫出的日志數據會自動復制到3個AZ中的6個存儲節點,當其中的多數節點回應寫日志成功,則向上層返回寫成功的ACK。這表明寫日志信息采用了多數派協議(quorum)。
MySQL的事務模型符合SS2PL協議[⑥],當日志成功寫出,就可以在內存中標識事務提交成功[⑦],而寫日志信息是一個批量的、有序的IO操作,再加上Aurora去除了大量的緩沖區臟數據的隨機寫操作,因此Aurora的整體性能得到大幅提升。
借用官方論文的一組對比數據,可以感性認識存儲和計算分離的所帶來的巨大好處,如圖1-6所示,MySQL的每個事務的IO花費是Aurora的7.79倍,而事務處理量Aurora是MySQL的35倍,相差明顯。
圖1-5 主從復制日志存儲圖
圖1-5 主從復制日志存儲圖
對于主備系統之間,如圖1-5所示,主備之間有事務日志(LOG)和元數據(FRM FILES)的傳遞。也就是說備機的數據是源自主機的。如圖1-5所示的主備之間的紫色箭頭,表示主機向備機傳輸的是更新了的元數據,綠色箭頭表示日志作為數據流被發送給了備機(這個復制,應該是異步的,相關內容請參考2.1節)。所以備機的數據更新,應該是應用了主機傳輸來的事務日志所致。這是論文中表述的內容,原文如下:
In this model,the primary only writes log records to the storage service and streams those logrecords as well as metadata updates to the replica instances.
但是,日志的應用功能是被放到了存儲層實現的,如原文描述:
Instead,the log Applicator is pushed to thestorage tier where it can be used to generate database pages inbackground or on demand.
而官方的網站[⑧]用圖1-7描述了備機的數據,是從存儲節點讀入的。
鑒于以上幾點,備機數據獲取和更新的這個細節,算是個謎。
“Caching”如果確實分為兩層,在存儲層提供從日志中恢復成為數據頁的形式而被緩沖,則主備系統之間應該沒有必要再傳輸日志數據,對于備機而言,直接從統一的存儲層的“Caching”中獲取數據即可。
與此相關的一個問題是:為什么備機節點,可以多達15個呢?難道僅僅是應對讀負載嗎?或者,作為故障轉移的目標,需要這么多備機做備選嗎?這又是一個謎。
圖1-7 Aurora主備機數據流圖
1.3 其他組件
從圖1-1中可以看到,物理備份和恢復的數據,是直接存儲在Amazon S3,即Simple Storage Service上。物理備份和恢復的模塊功能被從事務引擎中剝離到了存儲層。
從圖1-3和1-4中可以看到,日志信息的持久化存儲,也是落在了S3上。
S3是AWS提供的對象存儲服務。S3提供了高耐久性、高可擴展性以及安全的解決方案來備份和歸檔用戶的關鍵數據。在云服務中,數據庫提供商業邏輯的支撐,S3提供了數據的持久存儲支撐。其作用不可小視。
另外,論文提及了heat management、OS and security patching 、software upgrades等特性,對于創造極高的云數據庫服務能力很有幫助,本文不再展開討論,請參閱論文和相關資料。
2 .Aurora的存儲架構
存儲層的設計和實現,體現了“the log is the database”,其含義是日志中包含了數據的信息,可以從日志中恢復出用戶的數據,所以數據不一定必須再獨立存儲一份。而數據庫的核心不僅是數據,保障數據的擁有ACID特性的事務和提供便捷查詢的SQL語句、對以數據為基礎提供商業的交易服務更是必不可缺失,所以更精確的說,“the log is the data”,日志就是數據也許更為合適。在筆者看來,數據庫的價值不僅在數據,還在數據庫的相關技術,尤其在現代巨量數據下、完備的數據庫理論下,對以分布為要求的數據庫架構提出新的工程實踐挑戰。Aurora就是走在這樣的實踐道路上的楷模。
2.1 存儲層的工作
如圖1-8所示,主機Primary RW DB寫出的REDO日志(MySQL生成的日志帶有LSN,Log Sequence Number,單調遞增的日志順序號)信息發送到六個Sotrage Node中的每一個Sotrage Node上的時候,只存在一個同步瓶頸點,就是圖中標識為?之處,這是Aurora的一個核心設計點,盡量最小化主節點寫請求的延時。在存儲節點,傳輸來的日志進入一個隊列等待被處理。
之后日志被快速持久化到物理存儲設備,并立刻給主機一個回應。這是標識為?的處理過程,這個過程極其簡單,沒有額外的操作,因而速度會很快,這樣能夠滿足如上所說的“盡量最小化主節點寫請求的延時”的設計理念。?和?之后的其他操作,都是異步操作,不影響系統的整體性能。這樣當主機Primary RW DB收到六個Sotrage Node中的四個節點的ACK后,就認為日志成功寫出,可以繼續其他工作了
?所做的工作,是對持久化了日志做處理,如排序/分組等操作作用在日志上,以便找出日志數據中的間隙,存在間隙的原因是多數派寫日志的機制下,少數派可能丟失日志從而導致日志不連貫。
?所做的工作,就是從其他存儲節點(6個存儲節點構成一個PG ,即Protection Group,每個節點是一個segment,存儲單位是10G,位于一個數據中心中。6個存儲節點每2個位于一個AZ,共分布于3個AZ)中,通過Gossip協議,來拉取本節點丟失的日志數據,以填充滿所?發現的日志間隙。在?和?的過程中,能發現所有的副本中:相同的、連續的日志段是哪一部分,其中最大的LSN被稱為VCL(Volume Complete LSN)。
?所做的工作,就是從持久化的日志數據中,產生數據,就如同系統故障時使用REDO日志做恢復的過程:解析REDO日志,獲取其中保存的數據頁的修改后像,恢復到類似于傳統數據庫的數據緩沖區中(這也是存儲層需要存在“Caching”的一個明證)。
之后,第六步,周期性地把修復后的日志數據和由日志生成的以頁為單位的數據刷出到S3作為備份。第七步,周期性地收集垃圾版本(PGMRPL,即Protection Group Min Read Point LSN),參考表1-2[⑨],可以看到,垃圾收集,是以VDL為判斷依據的,當日志的LSN小于VDL,則可以被作為垃圾回收;第八步,周期性地用CRC做數據校驗。
圖1-8 日志數據在存儲節點的處理過程圖
2.2 儲存層的設計討論
現在再來反觀Aurora的整體設計:
數據不再從數據緩沖區刷出,消除了隨機寫操作,減少了IO。
計算和存儲分離,日志跨AZ寫到多份存儲節點,存在網絡IO。
主備節點間傳輸日志和元數據,存在網絡IO。
如上是三條核心點,似乎網絡IO占了三分之二條,屬于多數。但是網絡IO都是批量數據順序寫,可極大地抵消很多次的隨機寫的網絡IO消耗,而且通過數據冗余,極大地保障了可用性和云數據的彈性,從測試數據看,整體性能得到了可觀的提升。因此這樣的設計是一個優秀的架構設計。
數據冗余且有效,是使用數據庫系統的基本要求。邏輯備份與還原、物理備份與恢復、主從復制、兩地三中心等災備技術方案等都是數據冗余的相關技術。數據庫走向對等分布式架構,除了應對巨量數據的存儲和計算的需要,也要靠數據冗余來保證數據的可用性。所以數據冗余是數據系統架構設計的一個必須考慮點。
Aurora自然也要實現數據冗余。如圖1-5所示,數據至少在3個AZ中存6份。如果不采用“the log is the database”的理念,而使用傳統數據庫的技術,在跨節點寫出多份數據時,勢必需要采用2PC/3PC等多階段的方式來保證提交數據的正確性,這樣網絡交互的次數就會很多,而且大量的隨機寫操作會在網絡蔓延。所以“the log is the database”的理念客觀上避免了傳統的、耗時昂貴的分布式事務的處理機制,而又達到了數據分布的目的,這又是一個亮點。
數據至少在3個AZ中存6份,其目的是要保證數據庫服務的持續可用。那么,什么算是可用呢?無論是數據中心內部的局部故障還是跨數據中心甚至跨AZ出現故障,AWS也要在某些情況下提供數據服務的可用。這就要分兩種情況確定,這兩種情況基于6個副本的前提[⑩](3個副本能滿足多數派的讀寫規則,但是一旦其中一個副本不可用,則其余2個就不能保證讀寫一致,基于3個副本的分布式設計是脆弱的,不能切實可用地起到依靠數據冗余來換取數據可用的保障):
第1種: 讀寫均可用。
如圖1-9,當一個AZ出現問題,即2個副本不可用,Aurora仍然能夠保證讀寫可用,保障數據一致。設置V=6,讀多數派為Vr = 3,寫多數派為Vw = 4,所以一個AZ出現故障,或者3個AZ中的兩個數據中心出現故障,Aurora依然能夠向外提供服務。
圖1-9 Aurora保障讀寫可用圖
第2種: 至少讀可用。
當寫服務不可用,至少還可以提供讀服務。設置V=6,讀多數派為Vr = 3,寫多數派為Vw = 4時,一個AZ出現故障依舊能夠提供讀服務,如圖1-10甚至跨不同AZ的3個數據中心出現故障(概率非常?。x服務依舊能夠提供。
圖1-10 Aurora保障讀可用圖
在1.1節,曾經說過“主從節點可以位于不同的AZ(最多位于3個VPC,需要3個AZ)但需要位于同一個Region內”。如表1-1所示,AWS在全球提供的AZ個數尚有限,按其自身的說法部署一個Aurora需要三個AZ,那么諸如只有2個AZ的Region如北京,尚不能得到較可靠的數據可用保障。
圖1-10 Aurora保障讀可用圖
2.3 Aurora設計的優點
首先,存儲層與事務管理分離,即ACID的D特性獨立,使得存儲有機會成為獨立的服務而存在,便于跨數據中心時實現數據的容錯(fault-tolerant)、自愈(self-healing service)[11]和快速遷移。一旦存儲層具備了容錯、自愈和可快速遷移特性,則對外提供服務就不用再擔心數據的短暫或長久的不可用性。在數據為王的時代,此舉能保護好最核心的財產,確保云數據庫服務能持續不斷地對外提供服務,這使得Aurora具備了云服務的彈性。此點在AWS看來,十分重要。有了這種需求,推動技術架構發生變化便水到渠成。
服務的過程中,局部數據修復的能力,速度很快。數據庫宕機后的恢復,速度也很快。
Once thedatabase starts up it performs volume recovery in collaboration with thestorage service and as a result, an Aurora database can recover very quickly (generally under 10 seconds) even ifit crashed while processing over 100,000write statements per second.
服務中斷后,最后的招數就是數據遷移加數據庫引擎重新部署,而AWS的整個云系統具備了快速遷移數據的能力,這使得以存儲為核心的云數據庫有了超強的持久服務能力。
Wemonitor and automatically repair faults as part of our service. A 10GB segment can be repaired in 10 seconds on a10Gbps network link. We would need to see two such failures in thesame 10 second window plus a failure of an AZ not containing either of thesetwo independent failures to lose quorum. At our observed failure rates, that’ssufficiently unlikely, even for the number of databases we manage for ourcustomers.
其次,存儲層從高度耦合的數據庫引擎中分離,降低了數據庫引擎的復雜度,數據庫組件的分離使得數據庫部署適應巨量數據的分布式處理需求。這將進一步帶動數據庫引擎上層的語法分析、查詢優化、SQL執行、事務處理等組件進一步的解耦。
筆者認為,這是Aurora用實踐為數據庫架構技術的發展指出的可行方向。一個具有實踐意義的分布式發展架構,總是最亮眼的,也總是具有指導意義的。存儲與計算解耦,各種組件互相解耦,不斷解耦...在此種思路下,AWS已經走在發展萬能數據庫引擎的道路上(參見4.2節)。
3.Aurora的事務處理
Aurora基于MySQL和InnoDB,實現的是單點寫的一主多從架構,所以在事務處理方面,沒有大的變動,事務處理技術得到繼承。整體上是依據SS2PL和MVCC技術實現了事務模型(參見《數據庫事務處理的藝術 事務管理與并發控制》一書的10.3.3、10.3.4節)和并發控制(參見《數據庫事務處理的藝術事務管理與并發控制》一書的第11、12章)。
3.1 持久性
對于Aurora,事務的ACID特性,只有D特性與MySQL和InnoDB有很大的不同。Aurora利用MySQL的Mini-transaction和LSN在存儲節點構造數據頁(基本過程參見2.1節)。
如前所述,Aurora的存儲層與計算層分離。存儲層其功能在2.1節討論,其設計思想在2.2節討論。本節從事務的角度來討論與存儲層緊密相關的持久性,如表1-2所示存儲層是表中的“存儲節點S1、S2、S3、S4、S5、S6”。
在存儲層,日志被寫到持久化的存儲設備后,主節點收到應答則不被阻塞,上層工作能夠繼續進行,且存儲層的日志落盤操作保證了整個Aorora的日志持久化。然后存儲層的利用日志做實時恢復,這樣使得日志數據轉變為了“Caching”中存儲的頁面格式的數據。這些工作完成,才相當于傳統架構的數據庫持久化完成。
但是,因為存儲層不再是單點而是分布式結構,故存在故障的種類變多,如多節點的數據在實時運行過程中的一致性問題、在系統故障后的數據恢復時多節點的數據一致性問題。Aurora使用如表1-2的幾個概念來表示關鍵的一些日志點信息,然后憑借這些點來解決“日志數據的不一致”問題,這幾個概念,分別是:
LSN, Log Sequence Number,日志序列號:單調遞增,唯一標識每一條日志記錄。如表1-2所示,LSN1到LSN9表示共有9條日志記錄,每條有獨立的LSN值。
CPL, Consistency Point LSN,一致性點:MySQL的每個Mini事務產生的最后一個LSN為一個CPL即一致性點(一個事務包括多個Mini事務,一個Mini事務包括一到多個日志記錄。這是在描述以Mini事務為基本單位的一個局部一致,尚不能達到事務一致)。如表1-2所示,“T1-Mini-t1”T1事務的第一個Mini事務的一致性點,是LSN3,如果此時系統故障,之后做恢復,事務T1不會被恢復成功;如果事務T1在主節點被標識為了提交(InnoDB的事務提交標志,是在內存標識為事務已經提交,然后才刷出日志,這點不符合預寫日志的要求),事務日志尚沒有持久化到存儲層,這意味著數據可能會丟失。但是,InnoDB對這種先標識事務提交后刷日志的方式給出了不丟失數據的解決方式,而Aurora改變了日志的刷出機制,可能會改變或不改變InnoDB原有的數據一致性保障機制[12],如果改變了原有機制,論文對這一個重要點沒有加以描述,只能存疑待問。
SCL,Segment CompleteLSN,段完整LSN:每一個存儲節點對應的最大連續LSN,在系統存活期間,可以利用SCN與其它節點交互,采用Gossip協議,填補丟失的日志記錄。如表1-2所示,只標識出了S1節點的SCL是LSN9,而對于S5節點,其SCL是LSN7。
VCL,Volume Complete LSN,卷完整LSN:每個存儲節點接收到的最大連續日志ID,因為多數派協議的使用,每個存儲節點的VCL會不不同。如表1-2所示,沒有表示出S1到S6各個存儲節點的VCL,而是只標示出了六個節點中所有VCL中的公共最大點,這個點,是系統故障后恢復所能恢復到的一致點。注意依舊不是事務一致而是Mini事務一致,存疑的是,不能達到事務一致,其意義何在?還有什么重要的細節沒有公開嗎?留意到下面這段話,我們可以看出一點端倪(存儲層的恢復不需要保證事務一致,存儲層恢復之后,計算層還會繼續恢復工作,這樣才能達到事務一致):
However,upon restart, before the database is allowed to access the storage volume, the storage service does its own recovery whichis focused not on user-level transactions, but on making sure thatthe database sees a uniform view of storage despite its distributed nature.
VDL,Volumn Durable LSN,卷持久點:傳統的數據庫提供CheckPoint功能,在日志中加入一個CheckPoint點,作為故障恢復時的起始點。VDL就是存儲層的“CheckPoint點”,在VDL之前的日志,已經無用可以被GC,但因存儲層的日志一直在持續不斷地被用于“恢復”日志為“Caching”中的數據頁,所以其作用和原始的“CheckPoint點”相反。注意VDL是所有存儲節點上的日志比較后得到的一個共同點,不是一個Segment級的點,這和VCL相似,都是PG(ProtectionGroup)級別的。其定義如下:
VDL or the Volume Durable LSN as thehighest CPL that is smaller than or equal to VCL and truncate all log recordswith LSN greater than the VDL.
表1-2 日志在主節點和存儲層的作用表(持久化實現表)
3.2 事務與數據分布
在1.2節,我們曾說,目前制約存儲層內的“Caching”起更大作用的因素,主要在于分布式事務的機制的選取和InnoDB自身的事務實現機制。
這有兩層含義。一是InnoDB自身的事務實現機制制約了存儲層內的“Caching”起更大作用。二是分布式事務的機制的選取關聯著存儲層內的“Caching”是否有機會起更大作用。
首先:InnoDB的事務信息,幾乎不在數據上(除了元組頭上有個事務ID用于版本可見性判斷外再無其他信息),而是位于內存中。這其實是在說,InnoDB的行級鎖即索引項的記錄鎖,其鎖表位于內存,不能隨著Aurora的數據分布而“分布”。而Oracle的RAC可是在數據頁上存儲了足夠多的事務信息(參見《數據庫事務處理的藝術事務管理與并發控制》一書的第六章),所以RAC中的其他節點,就能夠隨著被分布的數據而獲取事務相關的信息從而在分布的各節點上處理事務的ACID特性。此點是MySQL能否走向分布式事務的一個關鍵點(當然選用不同的分布式事務實現機制會反過來影響這點結論)。
其次:分布式事務的機制的選取為什么會影響著Aurora的存儲層內的“Caching”是否有機會起更大作用呢?
有的分布式事務架構,采取的是集中式架構,即中央點總控事務管理。事務的決策判斷,都要經過中央點進行,多個子節點需要和中央節點多次交互。比如PostgreSQL-XC提供了全局事務管理器。如果MySQL/InnoDB或者Aurora的分布式架構向這個方向發展,則存儲層內的“Caching”就沒有多少機會起更大的作用了。
而有的分布式事務架構,采取的是事務信息隨同存儲分布。這樣不同的節點就可以進行“分布式”的事務處理。比如基于BigTable的Percolator系統,其核心不在于兩階段提交,而是在于分布的數據項上,有著豐富的事務信息,這些信息足以被任何節點用于做ACID的實現判斷(參考《Large-scale Incremental Processing Using Distributed Transactionsand Notifications》)。如果MySQL/InnoDB或者Aurora的分布式架構向這個方向發展,則存儲層內的“Caching”就有很大的機會起更大的作用。
走向哪條路,或走向另外的路,需看Aurora的雄心有多大。目前的Aurora告訴我們的是,其分布式架構的選擇,僅是用戶數據分布。事務數據的分布,其實是更大的一個話題。
3.3 事務處理
MySQL和InnoDB的事務處理技術,采用了SS2PL,把強嚴格兩階段鎖融合到平板事務模型中,以提交和回滾機制實現A特性,并進一步在讀數據時加鎖確保C特性,通過MVCC實現了I特性中的RR和RC隔離級別以提高并發度。這些技術,在目前的Aurora中沒有大的改變。如前所述,Aurora改變的是依據事務日志做持久化處理(D特性)和系統故障后的恢復的一部分流程處理(A、C特性的一部分),從整體上看,沒有革命性的變化。但是,Aurora的事務提交卻是異步的且和VDL相關(確保持久化),這點在論文中描述很細致如下:
In Aurora, transaction commits arecompleted asynchronously. When a client commits a transaction, the threadhandling the commit request sets the transaction aside by recording its “commit LSN” as part of aseparate list of transactions waiting on commit and moves on to performother work. The equivalent to the WAL protocol is based on completing a commit,if and only if, the latest VDL is greater than or equal to the transaction’scommit LSN. As the VDL advances, the database identifies qualifyingtransactions that are waiting to be committed and uses a dedicated thread tosend commit acknowledgements to waiting clients. Worker threads do not pausefor commits, they simply pull other pending requests and continueprocessing.
在1.2節我們提到“鑒于以上幾點,備機數據獲取和更新的這個細節,算是個謎”,即備機的數據獲取,是從存儲層而來還是從主節點而來?我們不妨做個論文沒有提及的猜想:備機的數據,源自存儲層和主節點,存儲層統一向上層提供數據頁的緩沖服務,用以不斷響應計算層的數據缺頁請求,這起到了傳統的數據緩沖區的作用。而主節點傳輸日志給備節點,備節點可以從中解析出UNDO日志信息(UNDO也是受到REDO的保護的),從而能夠構造出主節點在某個時刻的完整的計算環境狀態(數據緩沖區+UNDO信息),這樣,備機就可以為接到的讀請求構造一致的“ReadView”,為讀操作提供了事務讀數據的一致性狀態。如為此點,則是一個巧妙的設計。更進一步,主機直接傳輸給備機的,可以只是準備寫入REDO的UNDO信息。
3.4 鎖管理
基于MySQL的Aurora同樣使用了基于封鎖的并發訪問控制技術。但是,Aurora改造了MySQL的鎖管理器,這點論文沒有提及,而在2017年的Percona技術大會上,Aurora的一個分享展示了如圖1-11的內容。圖中顯示,在MySQL的鎖表管理器上,對于Scan、Delete、Insert三種操作,把lock互斥了三種類型的并發,而Aurora分別按操作類型加鎖“lock manager”,提高了并發度,這樣的鎖,看起來是一個系統鎖,把一個粗粒度的系統鎖拆分為三個細粒度的系統鎖。但是,較為奇怪的是,如圖1-12,Aurora展示了其效果卻十分的驚人(圖1-13是測試環境的配置)。
圖1-11 Aurora鎖管理器改進圖
圖1-12 Aurora鎖管理器改進后的性能測試對比圖
圖1-13 測試環境配置圖[13]
4 .云服務能力
4.1 強化的云服務能力
除了通過更多的數據冗余(跨3個AZ的 6個副本)提高高可用性外,Aurora還有著其他強大的云服務能力,這是云數據庫需要重點建設的能力。
存儲方面,存儲的單位是段(segment),每個段的大小為10G,單實例數據庫存儲最大限是64 TB。
處理系統故障方面:
- 10秒內完成一個 10G的Segment的網絡遷移。30秒完成故障轉移。
- 以Segment為單位周期性并行備份。
- 以REDO日志為單位周期性并行備份。
- 通過日志實時地持續恢復,提供了更快的crashrecovery。
性能方面:
- 更快的索引構建。采用自底向上的索引構建方式,比MySQL快2倍到4倍。
- 無鎖并發Read-View算法。構造ReadView采用無鎖算法減少競爭提高性能。
- 無鎖隊列提高審計功能的速度。
- 其他如熱行競爭、批量數據插入等性能提升明顯。
其他云服務:
- 提供快速 provisioning 和部署。
- 自動安裝補丁和軟件升級。
- 備份和 point-in-time 恢復。
- 計算和存儲的擴展性支持。
如圖1-3所示,存儲系統的元數據存于Amazon DynamoDB中,使用Amazon SWF提供的工作流實現對Aurora的自動化管理,這也是云中規模化服務的重要能力。
萬能數據庫
AWS的Aurora不只是MySQL的一個分支版本,更像是一個萬能的數據庫系統,這樣的系統,通過兼容各種主流數據庫的SQL語法、功能,也許能在云上一統數據庫的服務,把各種數據庫的用戶應用接入,通過統一的一個分布式的數據庫引擎,提供各種數據庫的數據服務能力。
AWS的官網,聲明了“兼容 PostgreSQL的Amazon Aurora”如下:
AmazonRelational Database Service (Amazon RDS) 正在提供 Aurora(PostgreSQL) 預覽版,即兼容 PostgreSQL 的 Amazon Aurora。Aurora 是一種完全托管的、兼容 PostgreSQL 和 MySQL 的關系數據庫引擎。
單從字面看,Aurora不再是MySQL,而是MySQL+PostgreSQL,所以將來將會是 “MySQL+PostgreSQL+...+...”,各種數據庫都將融于Aurora當中。這樣提供強大無比的云數據庫服務,此點非常重要,用戶基于任何數據庫的應用均不用修改應用的代碼,無縫接入Aurora。
從技術的層面看,實現這樣的目標,有多種方式。簡單的方式,就是利用相同的云基礎設施和云服務概念,把各個數據庫單獨云化,然后用Aurora統一命名。但如果進一步把計算層分離,如把語法解析、查詢器、執行器拆分,不同種類的數據庫使用各自的語法解析和查詢優化,然后統一執行計劃交給統一的執行器去執行,事務處理和數據存儲則可以獨自研發獨立于上層的計算。如此,想象空間得以打開......
5. 小結
本文探討了Aurora的實現方面的技術內容,由于作者水平有限,錯漏之處,請不吝指正。Aurora在實現方面的諸多細節,論文并沒有提及,期待以此文拋磚引玉,期待多方指點討論,共同進步。
附錄
參考資料:
1. 《Amazon Aurora: Design Considerations for High Throughput CloudNative Relational Databases》
2. https://aws.amazon.com/
3. 《數據庫事務處理的藝術事務管理與并發控制》,機械工業出版社,2017年10月出版
4. Aurora deep dive - Percona Live 2017
5. https://aws.amazon.com/tw/blogs/database/category/aurora/?nc1=h_l
6. 《High performance transactions in deuteronomy》