阿里妹導讀:TPC-C是TPC組織(國際事務性能委員會)制定的關於商品銷售的訂單建立和訂單支付等的基準測試標準,是數據庫聯機交易處理系統的權威基準測試標準。
螞蟻金服自研的分佈式關係數據庫OceanBase得到TPC-C測試第一名後,引發了大量關注,今天,咱們邀請了OceanBase的核心研發人員對本次測試作專業的技術解讀。node
有機會挑戰TPC-C測試相信是全部數據庫內核開發人員的夢想,但TPC-C測試標準很是複雜。因爲這是國產數據庫同時也是分佈式數據庫第一次衝擊這個榜單,爲了完成此次挑戰,OceanBase團隊先後準備時間超過一年。web
前期準備算法
TPC-C測試首先須要找到官方惟一認證的審計員來對測試進行審計監察,他們對此次OceanBase的審計也至關重視,全世界僅有的三個審計員此次就有兩個參與到測試審計工做中。sql
測試系統數據庫
目前市面上基本找不到一個可以開箱即用的符合TPC-C標準的測試工具。以目前各個廠商PoC環境最常遇到的benchmarksql爲例,能夠說只是模擬TPC-C壓力模型的壓測工具,連最基本的數據導入都不合規,大量的字符串生成未保證全局隨機,缺少壓測階段最基本的think time、keying time這些基本配置致使極小的數據量就能跑出很高的tpmC,最關鍵的是它將測試模型大大簡化爲工具直連DB測試,徹底沒有遵照TPC-C測試標準規範。編程
在標準定義中,測試系統能夠分爲RTE(Remote Terminal Emulator)和SUT兩部分,但實際上從角色上看SUT能夠進一步拆分爲兩部分:WAS(web application server)和DB Server。緩存
這其中DB Server是每一個測試廠商的數據庫服務;RTE扮演的角色是測試模型中的客戶終端,事務的觸發、RT的統計等都在這裏完成;標準明確要求每個用戶terminal都必須保持一個長鏈接,顯然在海量Warehouse時DB是沒法承受這麼多鏈接的,WAS就是RTE和DB之間橋樑,標準定義可使用鏈接池,在保證對應用透明的狀況下它能夠作全部請求的管理。服務器
這三個角色中,WAS和DB是必須商業化可購買且提供支付服務的,OceanBase此次是使用了OpenResty做爲WAS供應商。而RTE則通常由各個參測廠商自行根據標準實現,但全部實現代碼必須通過審計的嚴格審計,OceanBase此次完整的實現了一整套徹底合規的RTE,而且支持在大規模測試系統中部署。要知道在實際的TPC-C測試流程中,不僅是對DB端能力的考驗,RTE端一樣存在極大的資源消耗和壓力。以此次6088w tpmC測試結果看,咱們一共在64臺64c128G的雲服務器上運行了960個RTE客戶端,來模擬總計47942400個用戶terminal,最後還須要基於這麼多RTE統計結果進行一致性和持久化審計驗證。網絡
雖然只是測試客戶端,但RTE的中一樣有大量的可能致使最後測試失敗的小細節,好比你們可能注意不到的全部事務都由於用了web端模擬終端後須要增長的100毫秒rt,又好比爲了模擬用戶終端輸出顯示的100毫秒延時。數據結構
測試規劃
TPC-C歷來都不是一個簡單的測試,它很科學並無給出強制的軟硬件配置,只是給出測試規範和各類審計檢查限制標準,全部數據庫廠商能夠根據本身的特性充分調優來拿到一個最好的性能或性價比。但這同時也對全部參測廠商提出了一個巨大的難題,如何對已有的資源進行合理規劃來保證順利完成一次對TPC-C榜單的衝擊。
性能壓測
最受關注的性能壓測部分在TPC-C標準中規定了如下三個狀態:
因此以前通常數據庫進行性能壓測通常是如下的流程,先進行一段時間的預熱到達穩態,等待穩定運行一段時間並完成一個checkpoint後開始進入2小時的性能採集階段。
而OceanBase此次是使用了TPC-C測試迄今以來最嚴苛的一個流程來完成這個性能測試的,咱們首先使用了10分鐘進行預熱,而後在6088w tpmC穩態保持運行25分鐘並完成一個檢查點,再繼續跑了完整的8小時性能壓測採集階段,總耗時超過8個半小時,中間性能最大波動不到0.5%,最終結果也讓審計員異常興奮。
整個性能測試先後,審計員還須要進行數據及事務隨機分佈檢查,簡單說來就是大量全表掃描和統計sql,最大的一條sql須要訪問超過萬億行的order_line表結果,能夠算是TPC-C裏的「TPC-H測試」。現場審計第一次遇到這些sql時咱們也大量的出現sql執行超時狀況,但後續基於OceanBase2.2版本最新的並行執行框架咱們仍是很快搞定了這些大sql,因此要順利完成TPC-C測試並不能只是一個偏科生,保持自身沒有短板纔是真正意義上的通用關係數據庫,從這點上說Oracle還是OceanBase學習的榜樣。
ACID
面對D測試標準中最嚴格的一項-部分存儲介質永久故障,OceanBase還使用了最嚴苛的測試場景,在使用超出標準要求的全量6000W tpmC壓力下,咱們強行銷燬了一個雲服務器節點,總體tpmC在兩分鐘內恢復到6000w並持續跑到測試時間結束,這些表現都是遠遠超過TPC-C規範要求的,相比較而言其它傳統數據庫基本面對有日誌的存儲介質故障D測試場景都是依賴磁盤RAID來恢復,OceanBase應該算是首個沒有raid徹底依賴數據庫自身恢復機制完成所有D測試的數據庫廠商了。
同時咱們在D測試中是連續殺掉了兩臺服務器節點,首先殺掉一個數據節點,等待tpmC恢復且穩定5分鐘後,再次殺掉了rootserver leader節點,tpmC仍然快速恢復。
對TPC-C有所瞭解人都知道,TPC-C是一個典型的OLTP (On-Line Transaction Processing) 場景測試,考察的是數據庫在高併發壓力場景下的事務處理能力,最終的性能指標以tpmC(transaction per minute,也即每分鐘系統處理TPC-C模型中的new order事務的數量)和平均到每tpmC的系統成本做爲衡量標準。在OLTP場景中,每條請求的響應時間都是極短的。所以,各個數據庫廠商在進行TPC-C測試時,都會盡一切可能將每個操做時間壓縮到最短,不誇張的說,在TPC-C的測試中,一些關鍵操做的優化每每須要細化到CPU指令級。
在進入咱們的主題前,咱們先來談談TPC-C中的事務模型,主要分爲五種事務,訂單建立、訂單支付、訂單查詢、訂單發貨以及庫存查詢,這五種事務按照必定的比例發生,測試最終衡量的是每分鐘訂單建立事務的執行個數。你們知道,每個數據庫的事務,其實就是由必定邏輯關係關聯的若干條SQL語句組成,他們在一個事務中,要麼所有成功,要麼所有失敗,這個在數據庫中稱爲「原子性」,也就是ACID中的「A」。那麼TPC-C中的一個事務的耗時大約是多久呢?看一下報告就很清楚了——只有十幾個毫秒。考慮到一個事務由多條SQL構成,那麼每一條SQL的平均耗時都不到1毫秒!
在C/S(client-server)模型中,一條SQL語句從發起到執行完成須要經歷從客戶端輸入、網絡傳輸、SQL優化、執行、結果返回到客戶端這樣一個流程。而具體每一條SQL的執行可能只是作一個字段的更新,所須要的執行時間是很是短暫的,從整個鏈路的角度來看,大量的時間會花費在與客戶端的交互過程當中,形成資源的浪費和耗時的增長。那麼如何解決這個問題的呢?答案就是使用存儲過程。
存儲過程
所謂「存儲過程」就是數據庫爲用戶提供的一種面向過程的編程語言。基於這種語言,用戶能夠將應用程序的邏輯封裝爲一個可調用的過程(procedure)存放在數據庫中並隨時進行調用。經過這種方式,用戶能夠將原本須要與數據庫進行屢次交互才能完成的工做經過一次交互完成,省去了中間網絡的傳輸和等待時間(參見圖1)。假如一條事務的網絡開銷平均是30%,也就是說30%的CPU都花在了網絡的收發和解析上。那麼在6千萬規模tpmC測試中節省下來30%的CPU資源換算成系統處理能力是驚人的。使用存儲過程還能夠帶來事務響應時間的降低,致使數據庫內核中事務鎖的臨界區縮短,間接的提高了系統CPU利用率,整個吞吐量也隨之提升。存儲過程在縮短應用端的等待耗時上一樣有很大做用。
在TPC-C中,存儲過程對於整個系統的執行效率提高是相當重要的。OceanBase 的2.2版本不只全面支持了存儲過程,並且對存儲過程的執行效率作了大量極致的優化。
編譯執行
存儲過程做爲一種面向過程的高級語言,須要轉換成機器碼纔可以執行。這個過程通常能夠分爲「編譯執行」和「解釋執行」兩種,通常來講,編譯執行相比解釋執行有代碼優化充分、執行效率高等特色。OceanBase利用近兩年逐漸成熟的LLVM編譯器框架實現了一個支持存儲過程的編譯器,經過動態編譯(Just-in-Time Compilation)的方式將存儲過程翻譯成高效的二進制可執行代碼,在執行效率上得到了數量級的提高。同時,過程當中LLVM框架將存儲過程轉換爲與機器無關的中間代碼,使得存儲過程也天然而然地得到了跨平臺的編譯執行能力,LLVM內置的優化過程確保咱們在各類不一樣的硬件平臺上均可以得到正確、高效的可執行代碼。
Array Binding
另一個在TPC-C測試中發揮了重要做用的功能就是對DML語句進行批量處理的能力,在Oracle中該功能也稱爲「Array Binding」。一條SQL在數據庫中的執行過程大體上能夠分爲「計劃生成」和「執行」兩個階段。儘管咱們對SQL的執行計劃作了高速緩存,但找到一個合適的執行計劃在整個執行過程當中仍然是比較耗時的一個部分。那有沒有辦法省去這個時間呢?當一組SQL的執行計劃徹底同樣而只有執行參數不一樣時,在存儲過程當中咱們能夠經過特定的語法將他們的執行作成一個批量處理的過程,此時「計劃生成」只須要作一次便可,這就是所謂的「Array Binding」。
在Array Binding中,數據庫會首先找到須要使用的計劃,而後執行該計劃,並在每次執行完畢後,從新執行參數綁定(binding)的過程。打個比方,這就像是在一個C語言的for循環中,反覆賦值而不是從新定義一個數據結構。Array Binding的使用受用戶控制,須要在存儲過程當中使用FORALL關鍵字來觸發這一功能,在TPC-C的測試過程當中,咱們屢次使用了Array Binding來提高系統的處理能力,效果很是明顯。
Prepared Statement與執行計劃緩存
Prepared Statement是一種二進制的請求交互協議,能夠大大下降系統的交互成本。OceanBase不只支持用戶程序與數據庫間使用Prepared Statement, 也支持在存儲過程引擎調用SQL引擎執行時使用這種交互方式。存儲過程在對SQL進行一次Prepare操做並獲取惟一id後, 後續的每次執行僅須要傳入該id和對應的參數,系統能夠經過高速緩存找到對應的存儲過程或SQL計劃開始執行。該過程相比使用SQL文本的交互方式,省去了大量請求文本解析的CPU開銷。
OceanBase內部實現了高速緩存來緩存存儲過程的可執行代碼及SQL執行計劃,不一樣參數的存儲過程和SQL能夠經過這一高速緩存快速獲取須要的執行對象, 耗時通常在幾十微秒之內, 有效避免了從新編譯帶來的毫秒級的延遲和CPU消耗。
可更新視圖
在OLTP場景中,經過減小應用與數據庫的交互次數來實現性能提高的例子不少,可更新視圖就是其中之一。咱們常見的數據庫視圖一般是隻讀的,經過定義視圖,用戶能夠定義本身感興趣的數據以及其獲取接口,但視圖同時也能夠做爲更新操做的入口,好比在TPC-C的new order建立場景中,應用須要獲得商品信息,更新庫存並獲得更新後的值。通常能夠經過兩條SQL實現這一過程:
select i_price,i_name, i_data from item where i_id = ?; UPDATE stock SET s_order_cnt = s_order_cnt + 1, s_ytd = s_ytd + ?, s_remote_cnt = s_remote_cnt + ?, s_quantity = (CASE WHEN s_quantity< ? + 10 THEN s_quantity + 91 ELSE s_quantity END) - ? WHERE s_i_id = ? AND s_w_id = ? RETURNING s_quantity, s_dist_01, CASE WHEN i_data NOT LIKE'%ORIGINAL%' THEN 'G' ELSE (CASE WHEN s_data NOT LIKE '%ORIGINAL%' THEN 'G'ELSE 'B' END) END BULK COLLECT INTO ...;
但經過創建一個可更新視圖:
CREATE VIEW stock_item AS SELECT i_price, i_name, i_data, s_i_id,s_w_id, s_order_cnt, s_ytd, s_remote_cnt, s_quantity, s_data, s_dist_01 FROM stock s, item i WHERE s.s_i_id =i.i_id;
咱們就能夠經過一條語句更新庫存並獲得商品和庫存信息:
UPDATE stock_item SET s_order_cnt = s_order_cnt + 1, s_ytd = s_ytd + ?, s_remote_cnt = s_remote_cnt + ?, s_quantity = (CASE WHEN s_quantity< ? + 10 THEN s_quantity + 91 ELSE s_quantity END) - ? WHERE s_i_id = ? AND s_w_id = ? RETURNING i_price, i_name, s_quantity,s_dist_01, CASE WHEN i_data NOT LIKE'%ORIGINAL%' THEN 'G' ELSE (CASE WHEN s_data NOT LIKE '%ORIGINAL%' THEN 'G'ELSE 'B' END) END BULK COLLECT INTO ...;
這樣就省去了一條語句的交互,而且更新邏輯更加直觀。可更新視圖容許用戶能夠像普通表同樣操做視圖,但不是全部視圖均可以定義爲可更新視圖。好比帶distinct, group by的視圖,具體更新哪些行語義是不明確的,所以不能容許更新。具體到上面的stock_item兩表join的視圖,須要知足所更新表的unique key在join以後保持unique(key-preserved table),即item.i_id必須是惟一的這個前提。
須要強調,TPC-C規範禁止使用物化視圖,而可更新視圖並無改變底層數據表格的存儲形式,是符合規範的。
由於TPC-C的設計原則是儘量的「真實」反應一個OLTP系統的運行場景,咱們所作的不少優化都具備普遍的適用性。例如,對於一個高併發的OLTP系統來講,大部分的SQL請求的耗時是很是短的,採用純粹的C/S交互模型的後果必然使系統的時間浪費在應用與數據庫的頻繁交互中,而使用存儲過程能夠大大緩解這種交互的耗時,而且加強系統對於網絡抖動的免疫力,這種核心能力對於一個分佈式OLTP數據庫是不可或缺的。
在此次的TPC-C測試中,咱們採用了OceanBase 2.0版本開始支持的Oracle兼容模式,存儲過程和SQL所有使用了兼容Oracle的數據類型和語法,這樣作也是爲了在追求極致優化的同時,確保產品迭代能夠沿着通用和正規的方向發展。
OceanBase此次TPC-C測試與榜單上Oracle和DB2等其餘數據庫在硬件使用上有很是大的不一樣,OceanBase的數據庫服務器使用的是204+3臺型號是ecs.i2.16xlarge阿里雲ECS服務器,其中204臺做爲data node,還有3臺做爲root node,每位讀者均可以在阿里雲網站上輕鬆按需購買。若是讀者翻看Oracle和DB2的TPC-C測試報告會發現,這些數據庫都會使用專用的存儲設備,例如前最高記錄保持者Oracle在2010年的測試,使用了97臺COMSTAR專用的存儲設備,其中28臺用來存儲數據庫的重作日誌(Redo Log)。
硬件的差別給軟件架構提出了徹底不一樣的挑戰,專用的存儲設備其內部經過硬件冗餘實現了設備自身的可靠保證,數據庫軟件在使用這樣的存儲設備時就自然的預設了數據不會丟失。可是,這種方式帶來了成本的極大消耗,專用的存儲設備的價格都是特別昂貴的。
OceanBase使用通用的ECS服務器提供數據庫服務,而且只使用ECS機器自帶的本地硬盤作數據存儲,這是最通用的硬件條件。可是這種方式對軟件架構提出了很大的挑戰,由於單個ECS服務器的不如專用的存儲設備可靠性高。這也對OceanBase的事務引擎提出了很大的挑戰,OceanBase是在普通的ECS服務器上就能夠實現ACID特性。
TPC-C測試是對事務ACID特性有完整而且嚴格的要求。下面分別介紹OceanBase針對事務ACID的特性的解決方案。
Paxos日誌同步保證持久性(Durability)
OceanBase數據庫的事務持久性(Durability)保證是依賴事務重作日誌(Redo Log)的持久性來達成的。全部的 Redo Log 會實時強同步到另外兩臺數據庫服務機器上,包含產生 Redo Log 的機器在內,總共會有三臺機器在硬盤中持久化 Redo Log。
OceanBase 採用了 Paxos 一致性同步協議來協調這三臺機器上 Redo Log 的持久化,Paxos協議採用超過半數(也叫「多數派」)成功即算成功的算法(三個副本時,兩個成功即超過半數),當其中兩臺機器完成持久化後,事務便可完成提交,剩下的一臺機器的 Redo Log 在一般狀況下,也是當即就持久化完成了。但若是這臺機器碰巧出現異常,也不會影響事務的提交,系統會在其恢復後自動補齊所缺失的 Redo Log。若是機器永久故障,系統會將故障機器所應負責同步的數據分散給集羣內的其餘機器,這些機器會自動補齊所缺失內容,並跟上最新的 Redo Log 寫入。
使用Paxos一致性協議的最大優點是數據持久化和數據庫服務可用性的完美平衡。當使用三個副本時,任什麼時候候壞掉一個副本時至少還有另外一個副本有數據,而且寫入還能夠持續,由於還剩下兩個副本,後續的寫入也不受影響。
因此,OceanBase 在保證了事務持久性的同時,也大大提高了數據庫的連續服務能力。TPC組織的審計員在現場審計OceanBase持久性能力時,在客戶端持續產生壓力的狀況下,從OceanBase集羣中隨意挑選了一臺機器作了強制斷電操做,發現數據庫的數據不只沒丟,數據庫不須要任何人工干預還能持續的提供服務,審計員們都很吃驚,而且對OceanBase大爲讚揚。
依靠自動兩階段提交解決原子性(Atomicity)
TPC-C測試模型的五種事務中的「訂單建立」和「訂單支付」兩個事務分別會對不少數據作修改,是其中相對複雜的兩個事務。TPC-C標準對事務的原子性(Atomicity)是強制性的要求,要求一個事務內部對倉庫、訂單、用戶等表格的修改必定要原子的生效,不容許出現只有一半成功的狀況。
OceanBase的數據是按照倉庫ID(Warehouse_ID)拆分到多臺機器上的,若是全部的事務都是發生在同一個倉庫內部,那麼不管數據量有多大,事務的修改都只會涉及一臺機器的數據,也就是在一臺機器上完成事務提交,這是一種完美的線形擴展的場景。可是這不符合實際的業務場景,大多數的實際業務都會有不少不一樣維度之間的數據交互。TPC-C測試標準也是對此認真考慮,因此對於事務操做數據的隨機性規則提出了要求,最終要保證產生10%的「訂單建立」事務和15%的「訂單支付」事務要操做兩個及以上的倉庫。在OceanBase數據庫內,這樣就產生了跨機器的事務操做,而這必須使用兩階段提交協議來保證原子性。
OceanBase會自動跟蹤一個事務內全部SQL語句操做的數據,根據實際數據修改的位置自動肯定兩階段提交的參與者,事務開始提交時,OceanBase自動選擇第一個參與者做爲協調者,協調者會給全部參與者發送Prepare消息,每一個參與者都須要寫各自的Redo Log和Prepare Log(也意味着每一個參與者各自作本身的Paxos同步),等協調者確認全部參與者的Redo Log和Prepare Log完成後,而後再給全部參與者發送Commit消息,再等全部參與者的Commit工做完成。整個協議是在事務提交過程當中自動完成,對用戶徹底透明。OceanBase爲每個兩階段提交事務自動選擇一個協調者,整個系統任何機器均可以分擔協調者工做,因此OceanBase能夠將事務處理能力進行線形擴展。
多版本併發控制保證事務的隔離性(Isolation)
TPC-C標準裏要求「訂單建立」、「訂單支付」、「訂單配送」、「訂單支付」事務之間都是串行化隔離級別(Serializable)。OceanBase採用的方法是基於多版本的併發控制機制。事務提交時會申請一個事務的提交時間戳,事務內的修改以新的版本寫入存儲引擎,而且保證以前版本的數據不受影響。事務開始時會獲取一個讀取時間戳,整個事務內數據的讀取操做只會看到基於讀取時間戳的已提交數據。因此,事務的讀取不會遇到髒數據、不可重複讀數據以及幻讀數據。同時,事務的修改會在修改的數據行上持有行鎖,保證兩個併發的修改相同行的事務會互斥。
OceanBase的全局時間戳生成器也是由多副本組成,能夠獨立部署在三臺機器上,也能夠像此次TPC-C評測中同樣部署在root node機器上,與root node共享資源。全局時間戳的三副本是一種極高可用的架構,任何一次時間戳的獲取操做都至少在三臺機器上的兩臺得到了確認,因此任意一臺機器出現故障,獲取時間戳的操做不會有一點影響。
按照TPC-C標準,OceanBase準備了9種不一樣的場景測試有讀-讀、讀-寫衝突時事務的隔離性,最終都完美經過了審計員的審計。
一致性保證(Consistency)
在有了上述的事務能力後,OceanBase能夠完美的保證各類數據的一致性的約束。TPC-C標準裏提出了12種不一樣的一致性測試場景在各類測試運行先後對數據庫內的數據進行一致性校驗。由於OceanBase這次測試數據規模龐大,一致性校驗的SQL須要覈對大量的數據,因此一致性校驗的挑戰在於校驗的SQL自己運行的效率。基於OceanBase的並行查詢能力,發揮整個集羣全部的計算資源,校驗SQL的運行時間均縮短了幾個數量級,很好的完成一致性功能的審計工做。
複製表
TPC-C測試模型中有一張商品(ITEM)表,這張表的內容是測試所模擬的銷售公司全部售賣的商品信息,包含了商品的名字、價格等信息。「訂單建立」事務執行中須要請求這張表內的數據來肯定訂單的價格信息,若是商品表的數據只存放在一臺機器上,那麼全部機器上發生的「訂單建立」事務都會請求包含商品表的機器,這臺機器就會成爲瓶頸。OceanBase支持複製表功能,將商品表設置爲複製表後,商品表的數據會自動複製到集羣中的每一臺機器上。
TPC-C標準不限制數據的副本數,可是無論數據的組織形式,標準裏要求事務的ACID必定要保證。OceanBase使用特殊的廣播協議保證複製表的全部副本的ACID特性,當複製表發生修改時,全部的副本會同時修改。而且,當有機器出現故障時,複製表的邏輯會自動剔除無效的副本,保證數據修改過程當中不會由於機器故障出現無謂的等待。複製表在不少業務場景中都有使用,例如不少業務中存儲關鍵信息的字典表,還有金融業務中存儲匯率信息的表。
TPC-C規範要求被測數據庫的性能(tpmC)與數據量成正比。TPC-C的基本數據單元是倉庫(warehouse),每一個倉庫的數據量一般在70MB左右(與具體實現有關)。TPC-C規定每一個倉庫所得到的tpmC上限是12.86(假設數據庫響應時間爲0)。
假設某系統得到150萬tpmC,大約對應12萬個倉庫,按照70MB/倉庫計算,數據量約爲8.4TB。某些廠商採用修改過的不符合審計要求的TPC-C測試,不限制單個warehouse的tpmC上限,測試幾百到幾千個warehouse所有裝載到內存的性能,這是沒有意義的,也不可能經過審計。在真實的TPC-C測試中,存儲的消耗佔了很大一部分。OceanBase做爲第一款基於shared nothing架構登上TPC-C榜首的數據庫,同時也做爲第一款使用LSM Tree存儲引擎架構登上TPC-C榜首的數據庫,在存儲架構上有以下關鍵點:
兩份數據
爲了保證可靠性和不丟數據(RPO=0),有兩種不一樣的方案:一種方案是在硬件層面容錯,另外一種方案是在軟件層面容錯。OceanBase選擇在軟件層面容錯,優點是硬件成本更低,帶來的問題是須要冗餘存儲多個副本的數據。OceanBase使用Paxos協議保證在單機故障下數據的強一致。在Paxos協議中,一份數據須要被同步到多數派(超過一半),才被認爲是寫入成功,因此通常來講副本個數老是奇數,出於成本考慮最多見的部署規格是三副本。
三副本帶來的首要問題就是存儲成本的上升,以前商業數據庫的TPC-C測試大多基於磁盤陣列,而TPC-C規範中明確對磁盤陣列不作容災要求,使用相對於傳統數據庫三倍的存儲空間進行TPC-C測試顯然難以接受。
咱們注意到這樣一個事實,經過Paxos協議同步的只是日誌,日誌須要寫三份,但數據不是,數據只須要有兩份就能夠完成單機故障的容災了,當一份數據因爲服務器宕機不可用時,另外一份數據只要經過日誌把數據補齊,就能夠繼續對外提供訪問。
和數據存儲相比,日誌的存儲量比較小。咱們將數據與日誌分開,定義了三種不一樣的副本類型:F副本既包含數據又同步日誌,並對外提供讀寫服務;D副本既包含數據又同步日誌,但對外不提供讀寫服務;L副本只同步日誌,不存儲數據。當F副本出現故障時,D副本能夠轉換爲F副本,補齊數據後對外提供服務。在TPC-C測試中咱們使用FDL模式進行部署(一個F副本,一個D副本,一個L副本),使用了兩倍數據副本的存儲空間。不管是D副本仍是L副本,都須要回放日誌,D副本還須要同步數據,這些都是都會消耗網絡和CPU。
在線壓縮
在sharednothing架構下,OceanBase至少須要存儲兩份數據才能夠知足容災的要求,這意味着OceanBase須要比傳統數據庫多耗費一倍的存儲空間。
爲了緩解這個問題,OceanBaseTPC-C測試選擇對數據進行在線壓縮,Oracle數據庫中一個warehouse的存儲容量接近70MB,而OceanBase壓縮後存儲容量只有50MB左右,大幅下降了存儲空間。TPC-C規範要求磁盤空間可以知足60天數據量的存儲,對於OceanBase,因爲須要保存兩份數據,雖然可靠性更好,但須要保存至關於120天的數據量,這些存儲成本都要計入整體價格。
OceanBase使用了204臺ECS i2雲服務器存儲數據,服務器規格和線上真實業務應用保持一致。每臺服務器的日誌盤1TB,數據盤接近13TB。計算兩份壓縮後的數據60天的存儲空間以後,服務器的數據盤基本沒有太多餘量,從服務器的資源成本消耗來看,已經達到了比較好的平衡。若是OceanBase的單機性能tpmC進一步提高,磁盤容量將成爲瓶頸。OceanBase LSM引擎是append-only的,它的優點是沒有隨機修改,可以在線壓縮。不管是TPC-C測試,仍是最核心的OLTP生產系統(例如支付寶交易支付),OceanBase都會打開在線壓縮,經過CPU換存儲空間。
存儲性能平滑
TPC-C測試很大的挑戰在於在整個壓測過程當中性能曲線要求是絕對平滑的,曲線上的波動幅度不能超過2%,這對於傳統數據庫來講都是一件困難的事情,由於這要求對於全部後臺任務的精細控制,不能因爲某個後臺任務的資源過分使用致使前臺請求的阻塞積壓。而對於OceanBase而言,事情變得更爲困難,由於OceanBase的存儲引擎是基於LSM Tree的,在LSM Tree要按期執行compaction操做。Compaction是個很是重的後臺操做,會佔用大量CPU和磁盤IO資源,這對前臺的用戶查詢和寫入自然就會形成影響。咱們作了一些優化,來平滑後臺任務對性能的影響,從最終的測試結果來看,性能曲線在整個8小時壓測過程當中的抖動小於0.5%。
在LSMTree中,數據首先被寫入內存中的MemTable,在必定時候爲了釋放內存,MemTable中的數據須要與磁盤中的SSTable進行合併,這個過程被稱爲compaction。在不少基於LSM Tree的存儲系統中,爲了解決寫入的性能問題,一般會將SSTable分爲多層,當一層的SSTable個數或者大小達到某個閾值時,合併入下一層SSTable。多層SSTable解決了寫入的問題,可是SSTable的個數過多,會極大拖慢查詢的性能。OceanBase一樣借鑑了分層的思路,但同時使用了更加靈活的compaction策略,確保SSTable總數不會太多,從而在讀取和寫入性能之間作了更好的平衡。
Compaction等後臺任務須要消耗大量的服務器資源,爲了減小後臺任務對用戶查詢和寫入的影響,咱們在CPU、內存、磁盤IO和網絡IO四個方面對先後臺任務作了資源隔離。在CPU方面,咱們將後臺任務和用戶請求分爲不一樣的線程池,並按照CPU親和性作了隔離。在內存方面,對先後臺請求作了不一樣的內存管理。在磁盤IO方面,咱們控制後臺任務IO請求的IOPS,使用deadline算法進行流控。在網絡IO方面,咱們將後臺任務RPC和用戶請求RPC分爲不一樣隊列,並對後臺任務RPC的帶寬使用進行流控。
存儲CPU佔用
TPC-C基準測試主要考察總體性能tpmC,不少人也會關注單核的tpmC。然而,這個指標只有在相同架構下才有意義。對於存儲模塊的CPU佔用,有以下三點:
所以,簡單地對比OceanBase和Oracle的CPU核是不科學的,還須要算上共享存儲設備的CPU核,以及OceanBase存儲多副本和在線壓縮帶來的CPU開銷。TPC-C推薦的方案是不關注具體的軟件架構和硬件架構,關注硬件整體成本。在OceanBase的測試中,硬件成本只佔總體成本的18%左右,只考慮硬件的性價比大幅優於集中式數據庫。
後續發展
OceanBase的優點在於採用分佈式架構,硬件成本更低,可用性更好且可以作到線性擴展,可是,OceanBase單機的性能離Oracle、DB2還有不小的差距,後續須要重點優化單機存儲性能。另外,OceanBase的定位是在同一套引擎同時支持OLTP業務和OLAP業務,而目前OceanBase的OLAP處理能力還不如Oracle,後續須要增強存儲模塊對大查詢的處理能力,支持將OLAP算子下壓到存儲層甚至在壓縮後的數據上直接作OLAP計算。
本文做者:陽振坤(OceanBase創始人)、曹暉(OceanBase技術專家)、陳萌萌(OceanBase資深技術專家)、潘毅(OceanBase資深技術專家)、韓富晟(OceanBase資深技術專家)、趙裕衆(OceanBase高級技術專家)
本文來自雲棲社區合做夥伴「阿里技術」,如需轉載請聯繫原做者。