深度解析Google雲新資料庫產品AlloyDB

語言: CN / TW / HK

在上週的Google I/O大會上,GCP(Google雲平臺)正式對外發布了資料庫AlloyDB(Preview版本)。這裡對AlloyDB的架構也做一個較為深入的分析,看看與當前的雲原生資料庫PolarDB、Aurora有哪些異同。 0 1 AlloyDB 整體架構圖

AlloyDB是GCP上的一個全託管的雲資料庫服務,當前完全相容PostgreSQL 14,提供企業級的效能、擴充套件性與可用性。聲稱是標準PostgreSQL效能的4倍,AWS同類服務的兩倍(應該是指RDS PostgreSQL和Aurora PostgreSQL),如果是分析查詢,則可能有100倍的效能加速。另外,在介紹時,還特別提到,價格非常透明,這應該是針對當前AWS資料庫大多數都對IOPS獨立並按量計費而說的。

根據當前資料,其整體架構如下:

AlloyDB資料庫架構
  • 簡單來說,其架構與現有的雲原生資料庫Aurora、PolarDB都非常相似。使用了儲存計算分離,分散式儲存提供了多節點掛載能力。分散式儲存,會帶來海量儲存能力,以及非常強的IO吞吐能力;多點掛載,大大增強了資料庫的讀擴充套件能力,同時因為底層使用同一個儲存,所以也不再有資料拷貝和延遲等問題。
  • 在實現上,體現了”the log is the database”,儘可能只傳輸日誌,避免資料塊的傳輸與複製。例如,計算節點與儲存節點的不再傳輸資料塊(當然,就多了一個日誌應用的過程)。這一點與Aurora類似,但是PolarDB在日誌下推上,做得比較少,而是選擇將儲存以”較為標準”的檔案系統提供給計算節點,資料庫本身的各個模組還是比較完整的,這帶來的好處是,對資料庫的侵入要稍微小一些,對於新版本的支援和不同的資料庫的支援會更加簡單和一致。Aurora和AlloyDB的這種做法,則是將資料庫的解構更加徹底,將資料庫的日誌模組一定程度下沉到儲存層。在AlloyDB在實現時,還將這個部分徹底的做了分散式,通過多個不同的日誌處理程序(LPS)進行分散式併發處理。
  • 這種日誌處理的下推,也讓資料庫在進行崩潰恢復的時候,相比傳統的一體化架構要快非常多,也就讓資料庫所提供的SLA可以更高。因為沒有checkpoint,也應該就沒有什麼fuzzy或者sharp一說了,後端的LPS程序會持續的將redo apply到本地儲存,分散式儲存上的資料塊的版本總是非常新的。而不用像傳統資料庫,資料庫crash後,所有的沒有刷寫到磁碟的髒資料塊(記憶體中該資料庫已經更新,但是還沒有刷寫到磁碟)都需要通過redo應用到最新狀態,所以,傳統資料庫在崩潰恢復時總是需要一定的時間,而且記憶體越大,這個時間可能會越長。
  • 另外,AlloyDB的日誌儲存使用了較為獨立的儲存,也就是文中提到了”log storage”或者”log store”。考慮日誌與資料塊的讀寫特性都不相同,使用獨立的儲存在效能優化上,會更加有效。一般來說,日誌寫入通常是append-only的,而且是”同步”操作,需要非常低的延遲,另外,在AlloyDB的設計中,日誌寫入後,需要立刻讀取並應用到資料塊中。只需要將記憶體中已經更新過的資料塊覆蓋寫入本地儲存就可以了。而資料塊的處理,通常來說是一個非同步的過程(不阻塞資料庫的寫入),並且會有大量的隨機讀,這與日誌資料的訪問有很大的不同。這裡的一個猜測是,日誌儲存和資料塊儲存可能使用同一套儲存架構,但是可能使用面向不同場景的優化和引數,如果有Google的人,希望求證一下。
  • 計算節點使用了”ultra-fast cache”,猜測一下,可能是使用了與PolarDB類似的optane儲存作為加速,雖然使用optane卡的場景不同。這也是另一個希望求證的點。
  • AlloyDB的資料塊請求是帶有LSN號的,而每個可用區(Zone)內都有完整的資料塊,所以,在各個可用區的節點(可能是read replica)總是可以在本地可用區獲得最新的資料塊。也就是無需像Aurora使用的多數派協議,資料塊的讀取需要3份(寫入四份,4+3>6),當然Aurora也對這裡做了很多的優化(例如,通過一個bookkeeping記錄寫入資料和node的對應關係,儘可能將多數派讀取變成一次單節點的讀取[參考])。
  • AlloyDB下沉到儲存的日誌處理服務(LPS),也做了徹底的分散式。日誌儲存在一個底層的相對獨立的日誌儲存中,日誌處理服務則是一個分散式的、相對”無狀態”的程序,因為也做了存算分離,所以有非常好的擴充套件性。另外,在日誌處理的分片上,AlloyDB通過將底層的資料塊分成一個個獨立的分片(Shard,應該類似於PolarDB或其他系統中的chunk),每個分片由一個獨立的LPS處理,一個LPS可以根據系統壓力情況處理一個或多個分片。這樣就通過分散式的方式解決了日誌應用的問題。並且,這個日誌應用是在各個不同的可用區獨立執行。
  • 關於資料副本數量的問題:Aurora是3*2的副本設計,每個可用區兩個副本,每次寫入應該是3個副本,讀取可能需要4個副本,這種效能應該比較差,達到的效果是宣傳”AZ+1”的容災能力,也就是一個可用區失敗,再加一個副本失敗,依舊可以恢復資料。在實現上,Aurora對於底層副本感知是要更強的,並與上層實現結合起來了。但是AlloyDB使用Google底層統一的儲存,這裡看到的資料分佈在三個zone,有三個副本,但實際上,每個zone的資料是儲存在一個分散式儲存的,這個分散式儲存資料的副本數情況,並沒有對資料庫暴露。這裡可以猜測,可能是兩個副本或者更多,對於資料庫這裡IO敏感型的應用,應該比較難使用EC演算法去做去重。所以,實際上,一份資料,可能會有超過6份的副本數。
  • 另外,這裡看到,Block storage部分是可以通過一些智慧化的方式,對資料塊進行分級,降低整體的儲存成本的,這應該是底層儲存的資料分層能力。

AlloyDB的寫操作

這裡通過一個寫操作來看看,AlloyDB的整個處理流程。客戶端通過TCP連線,連線到主例項,然後將變更SQL傳送到主例項。主節點進行SQL解析、並在內容中更新資料和索引頁,同時,準備好WAL日誌。在事務提交時,則同步地將日誌寫入低延遲的日誌儲存,這些日誌則會被日誌處理程序(LPS)非同步的消費並處理。

儲存層被分成了三個部分:日誌儲存、日誌處理服務、資料塊儲存。日誌儲存本身是順序寫,並對寫入延遲要求很高,會直接影響事務處理的效能。AlloyDB專門針對該模式/場景進行了優化,以提供一個高效能的、低延遲的日誌儲存服務。

多個日誌處理服務(LPS)則會根據”Shard”(一組資料庫的資料塊)機制,對不同的日誌進行處理。先從儲存層讀取需要處理的資料塊(隨機讀),然後將redo日誌應用到這些資料塊,並回寫(持久化)資料塊到儲存中,並最終刪除日誌儲存中的日誌記錄。

AlloyDB的讀操作

讀操作有兩種情況,一個是從主節點提供服務,一個是從讀節點(read replica)提供服務。如果查詢所需要的資料都在記憶體中,那麼就和單機的PostgreSQL例項一樣,進行SQL解析、執行計劃生成、查詢執行,並響應使用者。為了加速查詢處理,AlloyDB在資料庫中額外集成了一個”ultra-fast block cache”。

如果,需要的資料塊在上面的兩級快取中都不存在,則需要到儲存中獲取。在把請求傳送給儲存層的時候,需要附帶把LSN(log-sequence number)號也作為請求的一部分,而底層儲存則返回滿足該LSN對應事務能夠看到資料塊。

從整體儲存層來看,LPS程序也會參與資料塊的請求的處理。LPS程序也有自己的快取,如果請求的資料塊在這個快取中,則會立刻返回給上層節點。如果,這裡再次快取缺失,則再向資料塊儲存讀取資料塊並響應請求。

這裡,LPS程序需要儲存一個”列表”,用於記錄日誌已經提交,但是,還沒有應用到底層的塊記錄。對於此類資料塊的請求,則需要先完成日誌應用再返回。雖然,此類情況不應該經常出現,因為如果是一個最近日誌沒有應用的塊,快取應該不太會把這樣的頁面清除。

其他

  • 雖然是Preview,但已經是目前看到的最具誠意的Preview了:任何使用者立刻就可以開通使用,並且給予了非常大的免費額度,具體的,計算節點每月免費不超過1.5萬美元、儲存節點不超過650美元的資源。
  • 另外,注意到,GCP會說這是一個”fully-managed, PostgreSQL-compatible database”,而不會過多的強調這是一個雲原生的資料庫系統。對於使用者來說,這就是一個具備高效能、高可用以及高可靠的PostgreSQL。至於,是不是Cloud-Native的,Google似乎對於這個概念並不那麼”感冒”。
  • 通過實現”non-disruptive instance resizing”、Vacuum優化管理、Crash Recovery的速度提升,這個服務推出就是99.99%的SLA。
  • 更底層使用的是Google內部統一的分散式儲存層,經過Gmail、Youtube等大型系統的驗證,效能/穩定性等經過了驗證。這一點上,AlloyDB與PolarDB、Aurora是不一樣的。PolarDB和Aurora都選擇了實現自己面向資料庫的分散式儲存系統,而AlloyDB選擇了更加通用的儲存層,再面向資料庫進行優化。這兩個路線,客戶價值都是直接的,但哪個方案的生命力會更加持久,可能需要幾十年的時間去觀察。
  • 與AlloyDB一起,GCP還推出一個Oracle到PostgreSQL的遷移服務,只是這個服務看起來推出的也比較倉促,比較困難的結構遷移部分,使用了一個第三方的開源產品來實現。一方面可以看到這個,遷移是非常重要的模組,另一方面也看到,這一塊做起來其實比較難。從這裡看到,AlloyDB考慮優先推出PostgreSQL版本的一個重要原因,是認為:Oracle資料庫的遷移至關重要,且PostgreSQL是Oracle遷移的重要目標資料庫。
  • 目前,釋出的內容來看,關於資料庫內部的併發訪問/多版本管理的內容比較少,這部分應該是另一個複雜的點。期待後續的文章。

一些已知的不確定的點

  • ultra-fast cache是什麼介質?如何被使用?
  • 對於其他zone(非primary節點所在的zone),他的WAL日誌(在log storage上)從哪裡獲取?WAL一定是具備跨zone的容災能力的,這裡WAL的容災是在資料層去做的(日誌寫時寫兩份或者三份),還是log storage去做的?
  • 與上面的問題相關的另一個重要的問題,LPS程序是全域性的還是屬於某個Zone的?
  • log storage是針對日誌場景專門進行優化的,其模式是,append-only、延遲敏感並直接影響效率,這裡的疑問是,做了哪些優化?

如果有Google的同學,可以一起討論一下。

參考

  • AlloyDB for PostgreSQL under the hood: Intelligent, database-aware storage
  • AlloyDB for PostgreSQL
  • Introducing AlloyDB for PostgreSQL: Free yourself from expensive, legacy databases