OceanBase架構剖析(讀寫事務、單點效能、SSD支援、資料正確性、分層結構)

凌洛發表於2018-02-10

讀寫事務

在OceanBase系統中,使用者的讀寫請求,即讀寫事務,都發給MergeServer。MergeServer解析這些讀寫事務的內容,例如詞法和語法分析、schcma檢查等。對於只讀事務,由MergeScrver 發給相應的ChunkServer分別執行後再合併每個ChunkServer的執行結果;對於讀寫事務,由MergeServer進行預處理後,傳送給UpdateServer執行。

只讀事務執行流程如下:
1)MergeServer解析SQL語句,詞法分析、語法分析、預處理(schema合法性檢查、許可權檢查、資料型別檢查等),最後生成邏輯執行計劃和物理執行計劃。
2)如果SOL請求只涉及單張表格,MergeServer將請求拆分後同時發給多臺
ChunkServer併發執行,每臺ChunkServer將讀取的部分結果返回MergeServer,由MergeServer來執行結果合併。
3)如果SQL請求涉及多張表格,MergeServer還需要執行聯表、巢狀查詢等操作。
4)MergeServer將最終結果返回給客戶端。

讀寫事務執行流程如下:
1)與只讀事務相同,MergeServer首先解析SQL請求,得到物理執行計劃。
2)MergeServer請求ChunkServer獲取需要讀取的基線資料,並將物理執行計劃和基線資料一起傳給Updateserver。
3)Updatesever根據物理執行計劃執行讀寫事務,執行過程中需要使用MergeServer傳入的基線資料。
4)UpdateServer返回MergeServer操作成功或者失敗,MergeServer接著會把操作結果返回客戶端。

例如,假設某SQL語句為update t1 set c1 = c1 + 1 where rowkey=1 ,即將表格t1中主鍵為1的c1列加1,這一行資料儲存在Chunkserver中.c1列的值原來為2012。那麼,MergeServer執行SQL時首先從ChunkServer讀取主鍵為1的資料行的c1列,接著將讀取結果(c1=2012)以及SOL語句的物理執行計劃一起傳送給UpdateServer。UpdateServer根據物理執行計劃將c1加1,即將c1變為2013並記錄到記憶體表(McmTable)中。當然,更新記憶體表之前需要記錄操作日誌。

單點效能

OceanBase架構的優勢在於既支援跨行跨表事務,又支援儲存伺服器線性擴充套件。當然,這個架構也有一個明顯的缺陷:UpdateServer單點,這個問題限制了OceanBase叢集的整體讀寫效能。

下面從記憶體容量、網路、磁碟等幾個方面分析UpdateServer的讀寫效能。其實大部分資料庫每天的修改次數相當有限,只有少數修改比較頻繁的資料庫才有每天幾億次的修改次數。另外,資料庫平均每次修改涉及的資料量很少,很多時候只有幾十個位元組到幾百個位元組。假設資料庫每天更新1億次,平均每次需要消耗100位元組,每天插入1000萬次,平均每次需要消耗1000位元組,那麼,一天的修改量為:1億×100+1000
萬×1000=20GB,如果記憶體資料結構膨脹2倍,佔用記憶體只有40GB。而當前主流的伺服器都可以配置96GB記憶體,一些高檔的伺服器甚至可以配置192GB、384GB乃至更多記憶體。

從上面的分析可以看出,UpdateServer的記憶體容量一般不會成為瓶頸。然而,伺服器的記憶體畢竟有限,實際應用中仍然可能出現修改量超出記憶體的情況。例如,淘寶雙11網購節資料庫修改量暴漲,某些特殊應用每天的修改次數特別多或者每次修改的資料量特別大,DBA資料訂正時一次性寫入大量資料。為此,Updateserver設計實現了幾種方式解決記憶體容量問題,Updancesever的記憶體表達到一定大小時,可自動或者手工凍結並轉儲到SSD中,另外,OceanBase支援通過定期合併或者資料分發的方式將Updateserver的資料分散到叢集中所有的ChunkServer機器中,這樣不僅避免了Updateserver單機資料容量問題,還能夠使得讀取操作往往只需要訪問UpdateServer記憶體中的資料,避免訪問SSD磁碟,提高了讀取效能。

從網路角度看,假設每秒的讀取次數為20萬次,每次需要從UpdateServer中獲取100位元組,那麼,讀取操作佔用的UpdateServer出口頻寬為:20萬×100=20MB,遠遠沒有達到千兆網路卡頻寬上限。另外,UpdateServer還可以配置多塊千兆網路卡或者萬兆網路卡,例如,OceanBase線上叢集一般給UpdateServer配置4塊千兆網路卡。當然,如果軟體層面沒有做好,硬體特性將得不到充分發揮。針對UpdateServer全記憶體、收發的網路包一般比較小的特點,開發團隊對UpdateServer的網路框架做了專門的優化,大大提高了每秒收發網路包的個數,使得網路不會成為瓶頸。

從磁碟的角度看,資料庫事務需要首先將操作日誌寫人磁碟。如果每次寫人都需要將資料刷入磁碟,而一塊SAS磁碟每秒支援的IOPS很難超過300,磁碟將很快成為瓶頸。為了解決這個問題,UpdateServer在硬體上會配置一塊帶有快取模組的RAID卡,UpdateServer寫操作日誌只需要寫入到RAID卡的快取模組即可,延時可以控制在1毫秒之內。RAID卡帶電池,如果UpdateServer發生故障,比如機器突然停電,RAID卡能夠確保將快取中的資料刷入磁碟,不會出現丟資料的情況。另外,UpdateServer 還實現了寫事務的成組提交機制,將多個使用者寫操作湊成一批一次性提交,進一步減少磁碟IO次數。

SSD支援

磁碟隨機10是儲存系統效能的決定因素,傳統的SAS盤能夠提供的IOPS不超過300。關聯式資料庫一般採用快取記憶體(Bufcr Cache)9的方式緩解這個問題,讀取操作將磁碟中的頁面快取到快取記憶體中,並通過LRU或者類似的方式淘汰不經常訪問的頁面:同樣,寫人操作也是將資料寫入到快取記憶體中,由快取記憶體按照一定的策略將記憶體中頁面的內容刷人磁碟。這種方式面臨一些問題,例如,Cache冷啟動問題,即資料庫剛啟動時效能很差,需要將讀取流量逐步切人。另外,這種方式不適合寫入特別多的場景。

最近幾年,SSD磁碟取得了很大的進展,它不僅提供了非常好的隨機讀取效能,功耗也非常低,大有取代傳統機械磁碟之勢。一塊普通的SSD磁碟可以提供35000 IOPS甚至更高,並提供300MB/s或以上的讀出頻寬。然而,SSD盤的隨機寫效能並不理想。這是因為,儘管SSD的讀和寫以頁(page,例如4KB,8KB等)為單位,但SSD寫入前需要首先擦除已有內容,而擦除以塊(block)為單位,一個塊由若干個連續的頁組成,大小通常在512KB~2MB。假如寫人的頁有內容,即使只寫人一個位元組,SSD也需要擦除整個512KB~2MB大小的塊,然後再寫入整個頁的內容,這就是SSD的寫入放大效應。雖然SSD硬體廠商都針對這個問題做了一些優化,但整體上看,隨機寫入不能發揮SSD的優勢。

OceanBase設計之初就認為SSD為大勢所趨,整個系統設計時完全摒棄了隨機寫,除了操作日誌總是順序追加寫入到普通SAS盤上,剩下的寫請求都是對響應時間要求不是很高的批量順序寫,SSD盤可以輕鬆應對,而大量查詢請求的隨機讀,則發揮了SSD良好的隨機讀的特性。摒棄隨機寫,採用批量的順序寫,也使得固態盤的使用壽命
不再成為問題,主流SSD盤使用MLCSSD晶片,而MLC號稱可以擦寫1萬次(SLC可以擦寫10萬次,但因成本高而較少使用),即使按最保守的2500次擦寫次數計算,而且每天全部擦寫一遍,其使用壽命為2500/365=6.8年。

資料正確性

資料丟失或者資料錯誤對於儲存系統來說是一種災難。OceanBase設計為強一致性系統,設計方案上保證不丟資料。然而,TCP協議傳輸、磁碟讀寫都可能出現資料錯誤,程式Bug則更為常見。為了防止各種因素導致的資料損毀,OceanBase採取了以下資料校驗措施:

  • 資料儲存校驗。每個儲存記錄(通常是幾KB到幾十KB)同時儲存64位CRC校驗碼,資料被訪問時,重新計算和比對校驗碼。
  • 資料傳輸校驗。每個傳輸記錄同時傳輸64位CRC校驗碼,資料被接收後,重新計算和比對校驗碼。
  • 資料映象校驗。UpdateServer在機群內有主UpdateServer和備UpdateServer,叢集間有主叢集和備叢集,這些UpdateServer的記憶體表(MemTable)必須保持一致。為此,UpdateServer為MemTable生成一個校驗碼,MemTable每次更新時,校驗碼同步更新並記錄在對應的操作日誌中。備UpdateServer收到操作日誌並重放到MemTable時,也同步更新MemTable校驗碼並與接收到的校驗碼對照。UpdateServer 重新啟動後重放日誌恢復MemTable時也同步更新MemTable校驗碼並與儲存在每條操作日誌中的校驗碼對照。
  • 資料副本校驗。定期合併時,新的子表由各個ChunkServer獨立地融合舊的子表中的SSTable與凍結的MemTable而生成,如果發生任何異常或者錯誤(比如程式bug),同一子表的多個副本可能不一致,則這種不一致可能隨著定期合併而逐步累積或擴散且很難被發現,即使被察覺,也可能因為需要追溯較長時間而難以定位到源頭。為了防止這種情況出現,ChunkServer在定期合併生成新的子表時,也同時為每個子表生成一個校驗碼,並隨新子表彙報給RootServer,以便RootServer核對同一子表不同副本的校驗碼。

分層結構

OceanBase對外提供的是與關聯式資料庫一樣的SQL操作介面,而內部卻實現成一個線性可擴充套件的分散式系統。系統從邏輯實現上可以分為兩個層次:分散式儲存引擎層以及資料庫功能層。

OceanBase一期只實現了分散式儲存引擎,這個儲存引擎支援如下特性:

  • 支援分散式資料結構,基線資料邏輯上構成一顆分散式B+樹,增量資料為記憶體中的B+樹:
  • 支援目前OceanBase的所有分散式特性,包括資料分佈、負載均衡、主備同步、容錯、自動增加/減少伺服器等;
  • 支援根據主健更新、插入、刪除、隨機讀取一條記錄,另外,支援根據主鍵範圍順序查詢一段範圍的記錄。

二期的OceanBase版本在分散式儲存引之上增加了SQL支援:

  • 支援SQL語言以及MySQL協議,MySQL客戶端可以直接訪問;
  • 支援讀寫事務;
  • 支援多版本併發控制;
  • 支援讀事務併發執行。

從另外一個角度看,OceanBase融合了分散式儲存系統和關聯式資料庫這兩種技術。通過分散式儲存技術將基線資料分佈到多臺ChunkServer,實現資料複製、負載均衡、伺服器故障檢測與自動容錯,等等;UpdateServer相當於一個高效能的記憶體資料庫,底層採用關聯式資料庫技術實現。我們後來發現,有一個號稱“世界上最快的記憶體資料庫”MemSQL採用了和OceanBase UpdateServer類似的設計,在擁有64個CPU核心的伺服器上實現了每秒150萬次單行寫事務。OceanBase相當於GFS+MemSQL,ChunkServer的實現類似GFS,UpdateServer的實現類似MemSQL,目標是成為可擴充套件的、支援每秒百萬級單行事務操作的分散式資料庫。


相關文章