陽振坤 楊傳輝 韓富晟 王國平 楊志豐 成肖君
(北京奧星貝斯科技有限公司 北京 100102)
1970 年Edgar.F.Codd 博士發(fā)明關(guān)系模型[1]以及隨后SQL 語言的出現(xiàn),關(guān)系數(shù)據(jù)庫系統(tǒng)從1980 年代起逐步發(fā)展成為了業(yè)務(wù)信息系統(tǒng)的基石.由于業(yè)務(wù)信息系統(tǒng)的穩(wěn)定性、可用性、實(shí)時(shí)性和高性能的要求以及事務(wù)的原子性(Atomicity)、數(shù)據(jù)的一致性(Consistency)、事務(wù)操作的隔離性(Isolation)、事務(wù)修改的持久性(Durability)(即ACID 屬性),關(guān)系數(shù)據(jù)庫的技術(shù)門檻非常高,當(dāng)前全世界廣泛使用的關(guān)系數(shù)據(jù)庫系統(tǒng)都是集中式系統(tǒng),可以離線、垂直擴(kuò)展(scale-up),難以在線、水平擴(kuò)展(scale-out),處理能力和容量有限.
1990 年代,隨著互聯(lián)網(wǎng)的發(fā)展和普及,以電子商務(wù)為代表的各種線上業(yè)務(wù)產(chǎn)生了百倍、千倍于線下實(shí)體店(商場、酒店、工廠等)的并發(fā)訪問量和數(shù)據(jù)量,遠(yuǎn)遠(yuǎn)超出了集中式關(guān)系數(shù)據(jù)庫的處理能力和存儲容量,對應(yīng)用系統(tǒng)進(jìn)行拆分并對數(shù)據(jù)庫進(jìn)行分庫分表幾乎成為了唯一可行的手段.然而,這種削足適履的辦法意味著應(yīng)用系統(tǒng)的重構(gòu),低效率、低性能的跨庫訪問和跨庫事務(wù),外鍵、全局唯一約束、全局索引等只能被束之高閣,數(shù)據(jù)分析無法直接進(jìn)行,數(shù)據(jù)管理的成本顯著增加.
分布式關(guān)系數(shù)據(jù)庫具備在線、敏捷的水平伸縮能力,能夠很好地克服業(yè)務(wù)的高并發(fā)以及海量數(shù)據(jù)的挑戰(zhàn).然而,與集中式關(guān)系數(shù)據(jù)庫相比,分布式關(guān)系數(shù)據(jù)庫更加復(fù)雜,在高可用、數(shù)據(jù)一致性、事務(wù)性能等方面面臨更大的技術(shù)挑戰(zhàn).
2019 年,OceanBase 分布式關(guān)系數(shù)據(jù)庫[2-3]通過了國際事務(wù)處理性能委員(TPC)的TPC-C 聯(lián)機(jī)事務(wù)處理基準(zhǔn)測試[4]并打破Oracle 保持了9 年的性能記錄.2021 年,OceanBase 通過了TPC-H 聯(lián)機(jī)分析處理基準(zhǔn)測試[5]并登頂性能榜首(@30 000 GB).OceanBase是迄今為止唯一獲得了TPC-C 和TPC-H 性能榜首的數(shù)據(jù)庫.
作為一個分布式關(guān)系數(shù)據(jù)庫,OceanBase 集群由若干可用區(qū)(Zone)組成,通常是1~5 個Zone,圖1 是一個3-Zone 集群.每個Zone 包含1 個或多個Ocean-Base 節(jié)點(diǎn),稱為OBServer.每個OBServer 由SQL 引擎、事務(wù)引擎和存儲引擎等構(gòu)成.每個Zone 都包含了整個系統(tǒng)的全部數(shù)據(jù),Zone 內(nèi)每個OBServer 管理其中的部分?jǐn)?shù)據(jù)即若干數(shù)據(jù)分片,單個Zone 內(nèi)各個OBServer 管理的數(shù)據(jù)彼此沒有交集.每個數(shù)據(jù)分片在每個Zone 里都有一個副本,這些副本構(gòu)成該數(shù)據(jù)分片的Paxos 組[6].
盡管應(yīng)用系統(tǒng)可以通過與任何一個OBServer 建立連接來訪問OceanBase 數(shù)據(jù)庫,但通常情況下應(yīng)用系統(tǒng)通過OBProxy(OceanBase Database Proxy)來訪問OceanBase 數(shù)據(jù)庫,以屏蔽OBServer 節(jié)點(diǎn)乃至Zone的上下線、負(fù)載均衡等導(dǎo)致的數(shù)據(jù)在OBServer 之間的遷移等.
高可用和數(shù)據(jù)一致性是業(yè)務(wù)系統(tǒng)對關(guān)系數(shù)據(jù)庫的根本要求,大部分業(yè)務(wù)都要求至少99.99%即4 個9 的可用率,重要業(yè)務(wù)和關(guān)鍵業(yè)務(wù)則要求99.999%即5 個9 的可用率.傳統(tǒng)集中式關(guān)系數(shù)據(jù)庫采用了高可靠的服務(wù)器和存儲以及基于主備鏡像的主庫+備庫的高可用解決方案,但這個方案有2 個不足:
1)成本高昂.高可靠服務(wù)器和高可靠存儲的價(jià)格十分昂貴,顯著地增加了成本.
2)主副本(主庫)故障后備副本(備庫)數(shù)據(jù)有損.若備副本與主副本完全同步,則主副本的每一筆事務(wù)必須到達(dá)備副本并持久化后才能認(rèn)為成功,一旦備副本故障或者主副本與備副本之間的網(wǎng)絡(luò)異常,那么主副本的寫入將被阻塞,從而導(dǎo)致服務(wù)中斷,這對于大部分業(yè)務(wù)是無法接受的.因此盡管主副本與備副本之間號稱主備鏡像,但實(shí)際上備副本數(shù)據(jù)通常略微落后于主副本,一旦主副本故障,則備副本的數(shù)據(jù)并不完整即修復(fù)點(diǎn)目標(biāo)(recovery point object,RPO)大于0,這使得業(yè)務(wù)恢復(fù)面臨較大的挑戰(zhàn),特別是在金融等數(shù)據(jù)一致性要求較高的業(yè)務(wù)場景.
分布式關(guān)系數(shù)據(jù)庫由多個節(jié)點(diǎn)組成,整個系統(tǒng)出現(xiàn)節(jié)點(diǎn)故障的概率隨著節(jié)點(diǎn)數(shù)的增加而快速增加,如表1 所示.
Table 1 Availability Rate of Distributed System表1 分布式系統(tǒng)的可用率%
因此,即使每個節(jié)點(diǎn)的可用率都是5 個9(99.999%),當(dāng)節(jié)點(diǎn)數(shù)達(dá)到10 時(shí)整個系統(tǒng)的可用率只有99.99%,而當(dāng)節(jié)點(diǎn)數(shù)達(dá)到100 時(shí)整個系統(tǒng)的可用率只有99.90%,這已經(jīng)無法滿足大部分業(yè)務(wù)的需求,而普通PC 服務(wù)器的可用率顯著低于5 個9.
為了解決分布式關(guān)系數(shù)據(jù)庫高可用和數(shù)據(jù)一致性問題,2013 年OceanBase 引入Paxos 分布式一致性協(xié)議[6].
如圖2 所示,數(shù)據(jù)庫每個分區(qū)(未分區(qū)的表被當(dāng)作單分區(qū)表,下同)由1 個主副本和2 個備副本組成,主副本執(zhí)行了1~5 共計(jì)5 個事務(wù),每個事務(wù)都在提交前把事務(wù)日志同步給備副本1 和備副本2,其中備副本1 收到了事務(wù)1、3 和4 的日志,備副本2 收到了事務(wù)1、3、4 和5 的日志,由于事務(wù)2 沒有在超過半數(shù)參與者上持久化成功,因此事務(wù)2 被回滾,其余4個事務(wù)成功提交.
圖2 OceanBase 的3 副本分布式架構(gòu)Fig.2 Three-replica distributed architecture of OceanBase
Paxos 分布式一致性協(xié)議的引入帶來的顯著好處:
1) 主副本故障后系統(tǒng)可在短時(shí)間內(nèi)自動選舉出新的主副本,新的主副本通過與活著的備副本握手快速補(bǔ)齊自身可能缺失的事務(wù)數(shù)據(jù),然后繼續(xù)提供服務(wù).
2) 系統(tǒng)無需高可靠的服務(wù)器和存儲等硬件.即使是普通的PC 服務(wù)器,2 臺服務(wù)器同時(shí)出故障的概率也非常低.對可用性要求特別高的業(yè)務(wù),可以采用5 副本即1 個主副本和4 個備副本,這樣即使2 個節(jié)點(diǎn)同時(shí)故障,數(shù)據(jù)庫服務(wù)也可以在短時(shí)間內(nèi)無損、自動地恢復(fù).
基于Paxos 分布式一致性協(xié)議,從0.5 版本開始,OceanBase 實(shí)現(xiàn)了少數(shù)副本,例如3 副本(圖3a)時(shí)單個副本故障、5 副本(圖3b)時(shí)2 個副本故障后,RPO 為0,且RTO(recovery time object)小于30 s,從4.0 開始,RTO 降為了8 s.
圖3 OceanBase 的3 副本和5 副本Fig.3 Three replicas and five replicas in OceanBase
OceanBase 的數(shù)據(jù)以分區(qū)為單位進(jìn)行管理,任何時(shí)刻每個分區(qū)都屬于且只屬于一個日志流,日志流用于記錄所包含的分區(qū)的數(shù)據(jù)操縱語言(data manipulation language,DML)對應(yīng)的WAL(write ahead log)日志,OceanBase 通過在日志流中記錄事務(wù)操作的日志完成對事務(wù)的提交.
數(shù)據(jù)庫的事務(wù)功能要保證ACID 四個基本特性[7],在數(shù)據(jù)庫系統(tǒng)內(nèi)部有2 個重要的模塊來實(shí)現(xiàn)這4 種特性,即故障恢復(fù)模塊和并發(fā)控制模塊.
故障恢復(fù)模塊通過日志系統(tǒng)和事務(wù)提交協(xié)議實(shí)現(xiàn)原子性和持久性這2 個特性.日志系統(tǒng)保證了事務(wù)的修改日志的持久化,并且在出現(xiàn)故障等異常時(shí)也能將日志恢復(fù)出來,進(jìn)而恢復(fù)事務(wù)的全部操作,也就保證了事務(wù)的持久性.事務(wù)提交協(xié)議通過日志持久化的原子性,以實(shí)現(xiàn)事務(wù)的原子性.
并發(fā)控制模塊用于協(xié)調(diào)多個并行執(zhí)行的事務(wù)的操作順序,通過識別并控制有沖突的多個修改操作和讀取操作,保證事務(wù)執(zhí)行的隔離性語義和數(shù)據(jù)的一致性.
接下來首先介紹日志系統(tǒng),然后介紹事務(wù)提交協(xié)議,之后將并發(fā)控制內(nèi)容分成寫寫操作和讀寫操作兩部分進(jìn)行介紹.
OceanBase 將事務(wù)日志存入多臺機(jī)器的多個副本中,比如3 副本或5 副本.如果少數(shù)副本出現(xiàn)故障(如機(jī)器掉電、硬盤損壞等),日志可以從活著的多數(shù)副本中恢復(fù)出來,保證數(shù)據(jù)不會丟失.Paxos 一致性協(xié)議[6]用于在各個副本之間同步事務(wù)產(chǎn)生的日志,實(shí)現(xiàn)了少數(shù)派副本故障時(shí)自動容災(zāi)切換和故障恢復(fù).
一致性協(xié)議有選舉和日志同步2 個主要的部分.
1)選舉.OceanBase 的選舉協(xié)議針對無主選舉和有主改選2 種場景分別處理.當(dāng)系統(tǒng)剛啟動時(shí)或者主副本節(jié)點(diǎn)故障時(shí),各個選舉的參與者發(fā)現(xiàn)沒有主副本后會進(jìn)行無主選舉,OceanBase 無主選舉協(xié)議會在最短的時(shí)間內(nèi)選舉出優(yōu)先級最高的副本作為新的主副本節(jié)點(diǎn),并開始提供服務(wù).有主改選發(fā)生在主副本節(jié)點(diǎn)認(rèn)為自己不再能勝任主副本節(jié)點(diǎn)的工作或人工干預(yù)時(shí),主副本節(jié)點(diǎn)會將作為主副本的角色轉(zhuǎn)讓給其他節(jié)點(diǎn),同時(shí)自身降級為備副本節(jié)點(diǎn).
2)日志同步.正常工作時(shí),主副本節(jié)點(diǎn)把數(shù)據(jù)庫的事務(wù)日志同步給其他副本,所有副本按照一致性協(xié)議對該日志進(jìn)行確認(rèn),當(dāng)日志獲得多數(shù)成員的確認(rèn)后即完成了日志的寫入.以常見的3 副本為例,主副本將日志同步給其他2 個副本,當(dāng)包括主副本在內(nèi)的任意2 個副本接受了日志并在本地硬盤中成功持久化,則日志就寫入成功,出現(xiàn)任意副本的故障時(shí),剩余的2 個副本中至少會有一個副本包含剛寫入的日志,保證日志不會丟失.
在單個日志流中,一個事務(wù)的日志通過一致性協(xié)議獲得多數(shù)派確認(rèn)后事務(wù)的修改就被持久化地記錄了下來,事務(wù)也就完成了原子提交.對于一個分布式事務(wù),事務(wù)的修改涉及多個日志流,日志要在對應(yīng)的日志流中記錄,此時(shí),任何一個日志流的持久化成功都不能代表整個事務(wù)的提交,需要事務(wù)涉及的所有日志都持久化成功才能保證事務(wù)提交的完整性.OceanBase 通過“兩階段提交協(xié)議”保證分布式事務(wù)的原子性.
經(jīng)典的兩階段提交協(xié)議中[8],協(xié)調(diào)者與參與者都會執(zhí)行多次持久化日志的操作,協(xié)調(diào)者記錄事務(wù)的執(zhí)行流程和最終提交狀態(tài),參與者記錄局部事務(wù)的持久化狀態(tài),從使用者視角看到分布式事務(wù)的提交延遲需要至少4 次日志提交的延遲之和.OceanBase實(shí)現(xiàn)了優(yōu)化的兩階段提交協(xié)議,顯著縮短了事務(wù)提交的延遲.
為了讓兩階段提交協(xié)議可以在更短的時(shí)間內(nèi)完成,OceanBase 的策略是不依賴協(xié)調(diào)者記錄的事務(wù)的狀態(tài)日志,而是依賴參與者記錄的操作日志,在兩階段執(zhí)行過程中如果出現(xiàn)了系統(tǒng)故障,那么由參與者互相校驗(yàn)事務(wù)的日志是否記全了,最終依然可以通過確認(rèn)超過半數(shù)的參與者都記全了各自的操作日志,來確認(rèn)事務(wù)最終提交的狀態(tài).如果不是超過半數(shù)的參與者都記全了日志,那么事務(wù)就沒有完成提交,最終就是回滾狀態(tài).OceanBase 的兩階段提交協(xié)議將事務(wù)的提交延遲減小到只有一次日志同步,顯著提高了事務(wù)提交的效率.
如圖4 所示,當(dāng)事務(wù)開始提交時(shí)有2 個參與者P0 和P1,OceanBase 選擇某個參與者作為協(xié)調(diào)者,該協(xié)調(diào)者只有內(nèi)存狀態(tài)沒有持久化狀態(tài).協(xié)調(diào)者首先會給所有的參與者發(fā)送事務(wù)的Prepare 請求,各個參與者收到此請求后,會將事務(wù)中所做的修改提交到日志中并進(jìn)行持久化.待Prepare 日志持久化成功后,參與者發(fā)送Prepare ok 消息給協(xié)調(diào)者.當(dāng)協(xié)調(diào)者收到所有參與者的Prepare ok 消息后,事務(wù)的所有修改均已提交到日志中并持久化成功,無論出現(xiàn)何種異常事務(wù)均可以恢復(fù),所以此時(shí)事務(wù)事實(shí)上已經(jīng)提交完成,因此協(xié)調(diào)者應(yīng)答客戶端事務(wù)提交成功.與此同時(shí),協(xié)調(diào)者發(fā)送Commit 給各個參與者,通知他們提交事務(wù),因?yàn)槭聞?wù)實(shí)際已經(jīng)提交,所以各參與者的提交動作可以異步完成.
圖4 OceanBase 兩階段提交協(xié)議Fig.4 Two-Phase Commit Protocol in OceanBase
2 個同時(shí)執(zhí)行的事務(wù)如果修改同一條數(shù)據(jù),后執(zhí)行修改操作的事務(wù)需要等待先執(zhí)行修改操作的事務(wù)完成后才能執(zhí)行,這樣才能保證對于數(shù)據(jù)修改的正確語義,也才能保證數(shù)據(jù)的一致性[7,9].
在OceanBase 中,事務(wù)修改的每一行數(shù)據(jù)都記錄事務(wù)的標(biāo)識,此標(biāo)識也用來標(biāo)記該行數(shù)據(jù)是否正在被事務(wù)修改.當(dāng)一個事務(wù)執(zhí)行修改操作時(shí),首先需要判斷被修改的行是否有其他事務(wù)的修改標(biāo)識,如果有則判斷對應(yīng)的事務(wù)當(dāng)前的狀態(tài),如果事務(wù)是正在執(zhí)行中的狀態(tài),那么當(dāng)前行依然被活躍事務(wù)修改,后續(xù)的事務(wù)必須等待之前的事務(wù)執(zhí)行結(jié)束,如果事務(wù)已經(jīng)處于提交或者回滾狀態(tài),那么當(dāng)前行則可以被后續(xù)的事務(wù)繼續(xù)修改.
OceanBase 采用多版本并發(fā)控制[10]的方法來處理并發(fā)的事務(wù)讀取操作與修改操作.在OceanBase 中,事務(wù)修改的數(shù)據(jù)都不是原地更新,而是生成新的版本,對于同一行數(shù)據(jù),每次修改后的數(shù)據(jù)版本都存在.數(shù)據(jù)的版本號是全局的,在事務(wù)提交時(shí)確定事務(wù)的提交版本號,作為此事務(wù)修改的所有數(shù)據(jù)的版本.
在OceanBase 里,提供事務(wù)版本號的服務(wù)叫全局時(shí)間戳服務(wù)(global timestamp service, GTS),此時(shí)間戳服務(wù)每秒可以處理幾百萬次請求,OceanBase 采用了聚合方式,每臺服務(wù)器同一時(shí)間并發(fā)的事務(wù)可以聚合起來取時(shí)間戳,大大降低對于時(shí)間戳服務(wù)的請求.在2020 年OceanBase的第2次TPC-C測試中,OceanBase每分鐘要執(zhí)行15 億個事務(wù),時(shí)間戳服務(wù)完全可以支持.
讀取操作使用的版本號有2 種獲取方法,對于可串行化隔離級別(Serializable)的事務(wù),在事務(wù)開始時(shí)從全局時(shí)間戳服務(wù)獲取1 次,作為整個事務(wù)所有讀取操作使用的版本號.對于讀已提交(Read Committed)隔離級別的事務(wù),在每條SQL 語句開始執(zhí)行時(shí)從全局時(shí)間戳獲取一次,作為本語句的讀取版本號.
讀取操作執(zhí)行的過程中,對于每一行需要讀取的數(shù)據(jù)會選擇小于等于讀版本號的最大的數(shù)據(jù)版本作為讀取的版本.這樣的操作能夠?qū)崿F(xiàn)所有的讀取操作讀取到的是系統(tǒng)的一個快照,因?yàn)閷τ谝粋€事務(wù)來說其修改的數(shù)據(jù)使用的是同一個提交版本號,所以讀取操作要么全部讀取到,要么全都不讀取,不會出現(xiàn)讀取一部分的情況.
關(guān)系數(shù)據(jù)庫需要保證事務(wù)的持久性,為了抵御突發(fā)的電力等故障,數(shù)據(jù)需要保存到硬盤(機(jī)械磁盤或固態(tài)盤)等非易失性存儲介質(zhì)即持久化,事務(wù)的日志需在事務(wù)提交前持久化.由于各種硬盤都是塊設(shè)備即按一定尺寸大小的塊對齊進(jìn)行讀寫,比如4 KB等,通常關(guān)系數(shù)據(jù)庫都采用了定長塊(4 KB,8 KB 等)原地更新的方式,如圖5(a)所示.
圖5 OceanBase 存儲引擎Fig.5 Storage engine of OceanBase
OceanBase 選擇了基于LSM-tree[11]的存儲架構(gòu),如圖5(b)所示.跟傳統(tǒng)的定長塊原地更新的存儲架構(gòu)相比,LSM-tree 存儲有顯著的不同,即修改數(shù)據(jù)(修改增量)記在內(nèi)存、基線數(shù)據(jù)只讀等.
LSM-tree 存儲有顯著的優(yōu)勢:
1)寫入性能好,且存儲設(shè)備無需隨機(jī)寫能力.
2)周期地(每天)進(jìn)行修改增量與基線數(shù)據(jù)合并,由于這樣通常避開業(yè)務(wù)高峰,因此系統(tǒng)的CPU、I/O和網(wǎng)絡(luò)資源等有一定的空閑,故可對數(shù)據(jù)進(jìn)行一些較為消耗CPU、I/O 和/或網(wǎng)絡(luò)等的處理,比如數(shù)據(jù)壓縮、數(shù)據(jù)統(tǒng)計(jì)等,且不對系統(tǒng)性能產(chǎn)生負(fù)面影響.這使得OceanBase 通常有3 倍或更高的數(shù)據(jù)壓縮率,降低用戶存儲成本,卻不會降低業(yè)務(wù)吞吐量或增加業(yè)務(wù)延時(shí).表2 是部分用戶業(yè)務(wù)從MySQL/Oracle 遷移到OceanBase 時(shí)遷移前后數(shù)據(jù)量的對比.
Table 2 Some User Business Data Compression Rates of OceanBase表2 部分用戶業(yè)務(wù)的OceanBase 數(shù)據(jù)壓縮率
3)基線數(shù)據(jù)只讀,這簡化了數(shù)據(jù)存儲的數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)緩存的實(shí)現(xiàn).
4)既適合行存又適合列存,解決了基于定長塊原地更新的數(shù)據(jù)庫的列存數(shù)據(jù)難以實(shí)時(shí)更新的難題,使得數(shù)據(jù)庫既能進(jìn)行交易處理,又能進(jìn)行分析處理.
當(dāng)然,LSM-tree 存儲也有一些劣勢:
1)讀需要融合修改增量和基線數(shù)據(jù).
2)數(shù)據(jù)寫入較多時(shí),修改增量需要轉(zhuǎn)儲到硬盤以釋放內(nèi)存.
3)需要周期地(每天)進(jìn)行修改增量與基線數(shù)據(jù)的合并.
4)SQL 執(zhí)行的代價(jià)模型既需要考慮基線數(shù)據(jù)又需要考慮修改增量.
針對這些劣勢,OceanBase 在設(shè)計(jì)和實(shí)現(xiàn)中進(jìn)行了相應(yīng)的處理和優(yōu)化,減少了這些劣勢帶來的性能和功能等方面的影響.
查詢優(yōu)化器是關(guān)系數(shù)據(jù)庫系統(tǒng)的核心組件之一,是衡量關(guān)系數(shù)據(jù)庫系統(tǒng)成熟度的“試金石”.查詢優(yōu)化理論誕生已有四十多年,學(xué)術(shù)界和工業(yè)界已經(jīng)形成了一些比較完善的查詢優(yōu)化框架,其中包括IBM System-R[12]的優(yōu)化框架和Volcano[13]/Cascades[14]的Top-down 優(yōu)化框架.然而,圍繞查詢優(yōu)化的核心難題始終沒有改變,即如何利用有限的系統(tǒng)資源來選擇一個“好”的執(zhí)行計(jì)劃.作為一個分布式關(guān)系數(shù)據(jù)庫系統(tǒng),OceanBase 需要克服分布式查詢優(yōu)化的挑戰(zhàn).
OceanBase 查詢優(yōu)化器的設(shè)計(jì)參考了System-R的設(shè)計(jì),圖6 展示了OceanBase 查詢優(yōu)化器的總體框架.OceanBase 查詢優(yōu)化器主要由計(jì)劃優(yōu)化模塊和計(jì)劃管理模塊組成,其中計(jì)劃優(yōu)化模塊負(fù)責(zé)生成最優(yōu)的執(zhí)行計(jì)劃,計(jì)劃管理模塊負(fù)責(zé)緩存和演進(jìn)執(zhí)行計(jì)劃.接下來,依次介紹OceanBase 的查詢改寫機(jī)制、分布式計(jì)劃生成機(jī)制、計(jì)劃緩存機(jī)制和計(jì)劃演進(jìn)機(jī)制.
圖6 OceanBase 查詢優(yōu)化器框架Fig.6 Query optimizer framework of OceanBase
查詢改寫是指利用查詢改寫規(guī)則對查詢語句進(jìn)行重寫或轉(zhuǎn)換,以便更好地利用數(shù)據(jù)庫的索引、優(yōu)化技術(shù)和查詢處理算法來提升查詢性能.OceanBase 設(shè)計(jì)并實(shí)現(xiàn)了大量的查詢改寫規(guī)則,涵蓋了不同的關(guān)系代數(shù)之間的相互轉(zhuǎn)換.這些策略一部分來自于已有的文獻(xiàn),如謂詞移動[15]、子查詢提升[16]、分組上拉和分組下壓[17]等;然而,當(dāng)前已有的研究并沒有也無法窮盡所有的改寫策略,很多已有的改寫策略仍有提升的空間,并且還有許多值得探索的新策略.OceanBase 在服務(wù)大量的客戶過程中,對業(yè)務(wù)SQL 使用模式進(jìn)行抽象并提出了許多新的改寫策略.
例如,已有的數(shù)據(jù)庫系統(tǒng)實(shí)現(xiàn)了 OR 展開的技術(shù)來優(yōu)化以下查詢:
原始查詢中,T1 和T2 表之間只有一個OR 條件的連接謂詞,只能進(jìn)行笛卡爾積.經(jīng)過OR 展開后,T1 和T2 表之間是兩次等值連接,可以應(yīng)用更多的連接算法.但是,該策略僅適用于內(nèi)連接,不適用于其他連接類型.為此,OceanBase 設(shè)計(jì)實(shí)現(xiàn)了針對不同連接類型的OR 展開策略,能夠?qū)⑼膺B接、半連接、反連接上的OR 連接謂詞展開為等值連接.
當(dāng)前,OceanBase 查詢優(yōu)化器已經(jīng)積累了多種針對不同關(guān)系代數(shù)式的改寫策略,能夠滿足復(fù)雜查詢的多個方面的改寫需求.除了一些常見的簡單改寫策略之外,其中有少部分復(fù)雜策略是基于已有文獻(xiàn)實(shí)現(xiàn)的,更多復(fù)雜策略則是基于業(yè)務(wù)場景的抽象得到的.在整個模塊的發(fā)展過程中,查詢優(yōu)化器還積累了許多基礎(chǔ)改寫算法,例如判定2 個關(guān)系代數(shù)的包含關(guān)系和判定謂詞的空值拒絕性質(zhì)等.這些基礎(chǔ)算法在不同的場景中被不同的改寫策略復(fù)用,使得OceanBase 能夠快速實(shí)現(xiàn)多種新型的改寫策略.
計(jì)劃生成主要負(fù)責(zé)枚舉所有等價(jià)的執(zhí)行計(jì)劃,并根據(jù)代價(jià)模型選擇代價(jià)最小的執(zhí)行計(jì)劃.OceanBase使用自底向上的動態(tài)規(guī)劃算法來進(jìn)行計(jì)劃枚舉[12].首先,它會枚舉基表路徑,然后再枚舉連接順序和連接算法,最后按照SQL 語義的順序枚舉其他算子.與單機(jī)關(guān)系數(shù)據(jù)庫系統(tǒng)相比,OceanBase 的分布式架構(gòu)在計(jì)劃枚舉中引入了許多額外的復(fù)雜因素,如分區(qū)信息、并行度、分區(qū)裁剪和分布式算法等.這些因素從根本上增加了分布式計(jì)劃枚舉的復(fù)雜性,并顯著擴(kuò)大了其計(jì)劃枚舉空間.
為了應(yīng)對分布式計(jì)劃枚舉的復(fù)雜性,業(yè)界大多數(shù)系統(tǒng)[18]采用了二階段的計(jì)劃枚舉方法.第一階段假設(shè)所有表都是單機(jī)的,并依賴現(xiàn)有的單機(jī)計(jì)劃枚舉能力選擇一個本地最優(yōu)的執(zhí)行計(jì)劃.第二階段將第一階段的單機(jī)執(zhí)行計(jì)劃通過適當(dāng)?shù)囊?guī)則轉(zhuǎn)換成一個分布式執(zhí)行計(jì)劃.這種二階段的分布式計(jì)劃枚舉方法通過枚舉部分計(jì)劃空間來降低分布式計(jì)劃枚舉的復(fù)雜性,但會導(dǎo)致計(jì)劃次優(yōu)的問題.核心問題在于第一階段優(yōu)化時(shí)沒有考慮分區(qū)信息,因此可能會選擇次優(yōu)的連接順序和單機(jī)算法.
為了解決二階段計(jì)劃次優(yōu)的問題,OceanBase 采用了一階段的計(jì)劃枚舉方法.計(jì)劃枚舉的其中一個目標(biāo)是為執(zhí)行計(jì)劃中的每個算子選擇一種具體的實(shí)現(xiàn)方法.在單機(jī)的場景下,算子的實(shí)現(xiàn)方法只需要考慮單機(jī)的實(shí)現(xiàn),但在分布式的場景中,算子的實(shí)現(xiàn)方法除了要考慮單機(jī)實(shí)現(xiàn)之外,還需要考慮其分布式的實(shí)現(xiàn).以數(shù)據(jù)庫中的連接算子為例,常見的單機(jī)算法有hash join、merge join 和nested loop join 等,常見的分布式方法有partition-wise-join,hash-hash distribution join 和broadcast distribution join 等.OceanBase 一階段計(jì)劃枚舉的核心思想是同時(shí)枚舉算子的本地算法和分布式算法,并使用分布式代價(jià)模型來計(jì)算代價(jià),而不是通過二階段的方式分階段地枚舉算子的本地算法和分布式算法.通過這種方式,OceanBase 可以從根本上解決二階段計(jì)劃枚舉導(dǎo)致的分布式計(jì)劃次優(yōu)的問題.
相較于二階段的計(jì)劃枚舉方法,OceanBase 一階段的計(jì)劃枚舉方法能夠完整枚舉出所有的分布式計(jì)劃空間,但也會引入計(jì)劃枚舉效率問題,尤其是在復(fù)雜查詢的場景下.為了解決這一問題,OceanBase 發(fā)明了大量快速裁剪計(jì)劃的方法,并新增了新的連接枚舉算法來支持超大規(guī)模表的計(jì)劃枚舉,從而根本性地提升了分布式計(jì)劃枚舉的性能.我們的實(shí)驗(yàn)結(jié)果也表明,在OceanBase 中,可以在秒級內(nèi)完成對50張表的分布式計(jì)劃枚舉.
查詢優(yōu)化是數(shù)據(jù)庫中非常耗時(shí)的一個過程.隨著查詢復(fù)雜度的增加,相應(yīng)的計(jì)劃數(shù)量也會呈指數(shù)級增長,查詢優(yōu)化本身也變得異常復(fù)雜.因此,對于執(zhí)行速度本身很快的查詢來說,查詢優(yōu)化帶來的開銷也變得不可忽視.為了降低查詢優(yōu)化的性能開銷,與其他關(guān)系數(shù)據(jù)庫一樣,OceanBase 對執(zhí)行計(jì)劃進(jìn)行了緩存.
與Oracle 的RAC 架構(gòu)不同,OceanBase 的sharednothing 分布式架構(gòu)給計(jì)劃緩存帶來了額外的挑戰(zhàn).由于OceanBase 中特定的分布式算法對分區(qū)的位置信息有強(qiáng)烈的依賴,有時(shí)可能無法使用已緩存的執(zhí)行計(jì)劃來執(zhí)行相同的查詢.例如,在OceanBase 中,如果緩存的執(zhí)行計(jì)劃包含了A表和B表進(jìn)行partitionwise-join 的算子,而partition-wise-join 要求A表和B表對應(yīng)的分區(qū)位于同一臺機(jī)器上,如果A表或B表發(fā)生了分區(qū)遷移,它們可能就無法執(zhí)行partition-wisejoin 操作,這時(shí)緩存的執(zhí)行計(jì)劃可能就變得無效,需要重新生成計(jì)劃.
為了解決這個問題,OceanBase 會為每一條SQL緩存多個執(zhí)行計(jì)劃.在計(jì)劃緩存階段,OceanBase 會遍歷執(zhí)行計(jì)劃,并從依賴位置信息的算子中提取位置信息約束,然后將該執(zhí)行計(jì)劃與約束一起緩存到計(jì)劃緩存器中.在計(jì)劃匹配階段,如果存在多個緩存計(jì)劃,OceanBase 會按照平均執(zhí)行時(shí)間從小到大的順序進(jìn)行匹配,找到第一個滿足分區(qū)位置約束的計(jì)劃進(jìn)行執(zhí)行.如果沒有滿足約束的計(jì)劃,就重新生成計(jì)劃并將其加入到計(jì)劃緩存器中.通過這種方式,OceanBase 成功解決了分布式計(jì)劃的緩存問題,并提升了分布式查詢的性能.
在關(guān)系數(shù)據(jù)庫系統(tǒng)中,因?yàn)閿?shù)據(jù)增刪導(dǎo)致統(tǒng)計(jì)信息的變化、數(shù)據(jù)庫的升級以及Schema 的變更等,執(zhí)行計(jì)劃發(fā)生變化是一個比較常見的現(xiàn)象.為了避免由于執(zhí)行計(jì)劃變化而導(dǎo)致的性能回退問題,Oracle 12c 引入了離線計(jì)劃演進(jìn)[19]的方案.該方案的核心思想是始終執(zhí)行經(jīng)過驗(yàn)證的基線計(jì)劃,而不執(zhí)行未經(jīng)驗(yàn)證的新計(jì)劃.只有在新計(jì)劃經(jīng)過離線演進(jìn)并通過驗(yàn)證后,才可以使用它.然而,離線計(jì)劃演進(jìn)的問題在于,在用戶未進(jìn)行干預(yù)之前,不能立即使用性能更好的新計(jì)劃.與Oracle 的離線計(jì)劃演進(jìn)方案不同,OceanBase 提出了一種基于用戶實(shí)時(shí)流量的在線計(jì)劃演進(jìn)方法,該方法的主要優(yōu)勢是能夠快速接受性能更好的新計(jì)劃.
圖7 展示了OceanBase 的在線計(jì)劃演進(jìn)方法.在優(yōu)化器生成新的計(jì)劃時(shí),該方法首先檢查是否存在歷史基線計(jì)劃.如果不存在,則直接執(zhí)行新計(jì)劃并將其添加到基線計(jì)劃集合中;否則,選擇基線計(jì)劃和當(dāng)前新計(jì)劃進(jìn)行在線演進(jìn).如果演進(jìn)成功,就用新計(jì)劃替換舊的基線計(jì)劃,否則直接舍棄新計(jì)劃.
圖7 OceanBase 在線計(jì)劃演進(jìn)方法Fig.7 Online plan evolution method of OceanBase
OceanBase 使用內(nèi)部表存儲歷史的基線計(jì)劃集合.為了完整地復(fù)現(xiàn)基線計(jì)劃,OceanBase 在內(nèi)部表中存儲了原始的SQL 和用于復(fù)現(xiàn)該計(jì)劃的完整Outline數(shù)據(jù).Outline 數(shù)據(jù)是OceanBase 中一組可用于固定執(zhí)行計(jì)劃的Hint 組合.同時(shí),為了降低在線演進(jìn)可能導(dǎo)致的潛在性能問題,OceanBase 采用了自適應(yīng)的演進(jìn)策略,即根據(jù)當(dāng)前新計(jì)劃和基線計(jì)劃的執(zhí)行時(shí)間,動態(tài)地調(diào)整新計(jì)劃和基線計(jì)劃的流量比例.如果新計(jì)劃的執(zhí)行性能優(yōu)于基線計(jì)劃,則將更多流量分配給新計(jì)劃;否則,將更多流量分配給基線計(jì)劃.
與其他關(guān)系數(shù)據(jù)庫相比,OceanBase 的在線計(jì)劃演進(jìn)方法能夠快速接受性能優(yōu)越的新計(jì)劃,避免了性能較差的新計(jì)劃對數(shù)據(jù)庫穩(wěn)定性的影響,減少了數(shù)據(jù)庫的運(yùn)維工作.
OceanBase 數(shù)據(jù)庫采用了集群內(nèi)原生多租戶設(shè)計(jì),不依賴于外部容器等實(shí)現(xiàn)了一個集群內(nèi)的多個互相獨(dú)立的數(shù)據(jù)庫服務(wù).通過實(shí)現(xiàn)原生多租戶,可以實(shí)現(xiàn)3 個功能:
1)實(shí)現(xiàn)資源隔離,使得每個數(shù)據(jù)庫服務(wù)的實(shí)例不感知其他實(shí)例的存在,并通過底層控制確保租戶數(shù)據(jù)的安全性;
2)簡化了集群的部署和運(yùn)維,能夠原生提供安全、靈活的 DBaaS (Database as a service)服務(wù);
3)實(shí)現(xiàn)一個集群對原來多個數(shù)據(jù)庫實(shí)例的資源整合,降低硬件資源總體成本.
租戶(tenant)是一個邏輯概念.在 OceanBase 數(shù)據(jù)庫中,租戶是資源分配的單位,是數(shù)據(jù)庫對象管理和資源管理的基礎(chǔ),對于系統(tǒng)運(yùn)維,尤其是對于云數(shù)據(jù)庫的運(yùn)維有著重要的影響.租戶在一定程度上相當(dāng)于傳統(tǒng)數(shù)據(jù)庫的“實(shí)例”概念.租戶之間是隔離的,類似于操作系統(tǒng)的虛擬機(jī)或容器.在數(shù)據(jù)安全方面,OceanBase 數(shù)據(jù)庫不允許跨租戶的數(shù)據(jù)訪問,以確保用戶的數(shù)據(jù)資產(chǎn)沒有被其他租戶竊取的風(fēng)險(xiǎn).在資源使用方面,OceanBase 數(shù)據(jù)庫表現(xiàn)為租戶獨(dú)占其資源配額.總體上來說,租戶既是各類數(shù)據(jù)庫對象的容器,又是資源(CPU、內(nèi)存、存儲I/O 等)的容器.
租戶有系統(tǒng)租戶和用戶租戶2 種類型.系統(tǒng)租戶是集群默認(rèn)創(chuàng)建的租戶,與集群的生命周期一致,負(fù)責(zé)管理集群和所有租戶的生命周期.因?yàn)橄到y(tǒng)租戶只用來管理其他租戶,并存儲集群的元數(shù)據(jù),為了設(shè)計(jì)簡單,系統(tǒng)租戶僅支持單點(diǎn)寫入,不具備擴(kuò)展能力.
用戶租戶是為用戶創(chuàng)建的租戶,對外提供完整的數(shù)據(jù)庫功能,支持 MySQL 和 Oracle 兩種兼容模式.用戶租戶支持服務(wù)能力水平擴(kuò)展到多臺機(jī)器上,支持動態(tài)擴(kuò)容和縮容,內(nèi)部會根據(jù)用戶的配置自動創(chuàng)建和刪除日志流.
新建一個租戶的時(shí)候,管理員需要定義其資源單元配置(UNIT_CONFIG)、所在Zone 列表(ZONE_LIST)、每個Zone 中資源單元數(shù)目(UNIT_NUM)這3 個因子.其中,資源單元配置包括CPU、內(nèi)存、存儲IOPS、存儲空間限制等物理資源的規(guī)格限制.系統(tǒng)允許通過在線調(diào)整租戶的資源單元配置,實(shí)現(xiàn)資源的垂直擴(kuò)容縮容;通過在線調(diào)整資源單元數(shù)目,實(shí)現(xiàn)租戶資源的水平擴(kuò)容縮容;通過增刪Zone 列表,實(shí)現(xiàn)租戶數(shù)據(jù)和服務(wù)副本數(shù)的增刪,從而調(diào)整單個租戶的容災(zāi)等級,也可以用來實(shí)現(xiàn)租戶數(shù)據(jù)的跨數(shù)據(jù)中心遷移.
OceanBase 數(shù)據(jù)庫中把資源單元(UNIT)當(dāng)作給租戶分配資源的基本單位,一個資源單元可以類比于一個包含CPU、內(nèi)存、存儲資源的容器.一個節(jié)點(diǎn)上可以創(chuàng)建多個資源單元,在節(jié)點(diǎn)上每創(chuàng)建一個資源單元都會占用一部分該節(jié)點(diǎn)的相應(yīng)資源.
一個租戶可以在多個節(jié)點(diǎn)上放置多個資源單元,但一個租戶在單個節(jié)點(diǎn)上只能有一個資源單元.一個租戶的多個資源單元相互獨(dú)立,每個節(jié)點(diǎn)控制本地多個資源單元間的資源分配.類似的技術(shù)是 Docker容器和虛擬機(jī),但 OceanBase 并沒有依賴 Docker 或虛擬機(jī)技術(shù),而是在數(shù)據(jù)庫內(nèi)部實(shí)了資源隔離.在數(shù)據(jù)庫內(nèi)原生實(shí)現(xiàn)資源隔離有4 個優(yōu)勢:
1)資源共享,降低單個租戶成本;
2)支持輕量級租戶,如資源單元可以支持0.5c CPU 規(guī)格;
3)實(shí)現(xiàn)快速的規(guī)格變化和快速遷移;
4)便于實(shí)現(xiàn)租戶內(nèi)更細(xì)粒度的資源隔離和優(yōu)先級管理.
通過實(shí)現(xiàn)資源隔離,用戶租戶之間可以實(shí)現(xiàn):
1)內(nèi)存隔離;
2)CPU 在隔離的同時(shí),允許共享;
3)存儲IOPS 在隔離的同時(shí),允許共享.
6.2.1 CPU 的隔離
為了控制CPU 分配,每個資源單元可以指定MIN_CPU,MAX_CPU 這2 個參數(shù).MIN_CPU 決定了在一個調(diào)度周期內(nèi)最少給該租戶保留的時(shí)間片,MAX_CPU 決定了最大分配的時(shí)間片.當(dāng)節(jié)點(diǎn)上實(shí)際使用的CPU 低于所有資源單元的MAX_CPU 總要求時(shí),所有資源要求都得到滿足;否則,超出部分按MAX_CPU 與MIN_CPU 之間的差值決定的權(quán)重共享.實(shí)現(xiàn)時(shí),節(jié)點(diǎn)內(nèi)通過控制活躍線程數(shù)來控制租戶CPU 的占用,但由于 SQL 執(zhí)行過程中可能會有 I/O 等待、鎖等待等,所以1 個線程無法用滿1 個CPU,節(jié)點(diǎn)會按需給每個虛擬 CPU 啟動多個線程.
在典型的工作負(fù)載中,大量高并發(fā)的短事務(wù),往往和少量低頻但資源消耗較多的“大查詢”混合在一起.相比于大查詢,讓短查詢盡快返回對用戶更有意義,即大查詢的查詢優(yōu)先級更低,當(dāng)大查詢和短查詢同時(shí)爭搶 CPU 時(shí),系統(tǒng)會限制大查詢的 CPU 使用,即用于大查詢的線程被限制在一定的比例.一方面,當(dāng)一個線程執(zhí)行的 SQL 查詢耗時(shí)超過閾值,這條查詢就會被判定為大查詢, 一旦判定為大查詢,如果大查詢使用的線程比例達(dá)到上限,則該大查詢的線程會進(jìn)入等待狀態(tài),為其它工作線程讓出CPU.當(dāng)一個工作線程因?yàn)閳?zhí)行大查詢被掛起時(shí),作為補(bǔ)償,系統(tǒng)按需新建工作線程.另一方面,系統(tǒng)會根據(jù)執(zhí)行歷史,在開始執(zhí)行前就判定一個查詢?yōu)椤按蟛樵儭?
6.2.2 IOPS 的隔離
除了存儲容量,數(shù)據(jù)庫硬盤(包括本地硬盤、云盤等)的IOPS 也是影響性能的關(guān)鍵因素.有時(shí)用戶希望不同租戶的硬盤帶寬可以完全隔離,就像他們運(yùn)行在不同的物理硬盤上一樣;有時(shí)用戶則希望系統(tǒng)提供一定的靈活能力,租戶間實(shí)現(xiàn)閑時(shí)共享、忙時(shí)隔離.OceanBase 使用iops.{min, max, weight}三元組描述一個租戶的硬盤(云盤等)帶寬規(guī)格,iops.min 描述硬盤帶寬的下限,這部分資源為租戶預(yù)留資源;iops.weight 描述租戶的資源權(quán)重,如果一個租戶實(shí)際使用的硬盤帶寬超過了iops.min,那他通過iops.weight 與其他租戶劃分資源;iops.max 描述硬盤帶寬的上限,租戶使用的硬盤帶寬不允許超過該上限.
如果租戶要求硬盤帶寬完全隔離,則設(shè)置iops.max = iops.min,該租戶的硬盤帶寬按照iops.min的值剛性保留.如果租戶希望自己的硬盤帶寬除了保底能力外,還有一定的彈性上浮空間,可以配置iops.max > iops.min,并根據(jù)業(yè)務(wù)自身的權(quán)重配置合理的iops.weight,從而按需使用共享的硬盤帶寬.作為關(guān)系數(shù)據(jù)庫,iops.min 預(yù)留硬盤資源的能力對在線事務(wù)處理提供穩(wěn)定的時(shí)延是很重要的.而對于OLAP 型業(yè)務(wù)負(fù)載,則可以把iops.min 配置為0,完全共享硬盤帶寬,以最大化利用資源.
系統(tǒng)需要對資源單元進(jìn)行管理,并通過把資源單元在多個節(jié)點(diǎn)間調(diào)度,對系統(tǒng)資源進(jìn)行有效利用.
1)資源單元的分配,即新建一個資源單元時(shí),系統(tǒng)需要決定其分配到哪個節(jié)點(diǎn)上.
2)資源單元的均衡,即在系統(tǒng)運(yùn)行過程中,系統(tǒng)根據(jù)資源單元的資源規(guī)格等信息對資源單元進(jìn)行再平衡的一個調(diào)度過程.
單一類型資源的多機(jī)負(fù)載均衡比較容易實(shí)現(xiàn),只需要計(jì)算單一資源的利用率,并通過資源單元的遷移達(dá)到每個節(jié)點(diǎn)上的資源均衡.當(dāng)系統(tǒng)中有多種資源需要進(jìn)行分配和均衡時(shí),僅使用其中一種資源的占用率去進(jìn)行分配和均衡很難達(dá)到較好的分配和均衡效果,為此,在多種資源(CPU 、 內(nèi)存)均衡和分配時(shí),為每種資源分配一個權(quán)重,作為計(jì)算節(jié)點(diǎn)總的資源占用率時(shí)該資源所占的百分比.而每種資源的權(quán)重,依賴于集群中該資源的總體使用率,即某種資源使用的越多,則該資源的權(quán)重就越高.
2022 年,國內(nèi)公有云數(shù)據(jù)庫已經(jīng)占據(jù)整個數(shù)據(jù)庫市場一半以上的份額[20].作為一款分布式關(guān)系數(shù)據(jù)庫,水平伸縮能力使得OceanBase 十分契合公有云服務(wù).
OceanBase 云服務(wù)有2 種類型:租戶級實(shí)例服務(wù)和集群級實(shí)例服務(wù).使用租戶級實(shí)例服務(wù)時(shí),使用者不感知OceanBase 集群資源,只要按需對租戶進(jìn)行擴(kuò)容和縮容等操作,以滿足業(yè)務(wù)發(fā)展的需求并節(jié)省成本.使用集群級實(shí)例服務(wù)時(shí),使用者不僅可以按需對集群進(jìn)行擴(kuò)容和縮容,還可以在集群內(nèi)創(chuàng)建和管理租戶,對這些租戶按需進(jìn)行擴(kuò)容和縮容等,通過充分發(fā)揮租戶級資源共享的能力,以最大化利用集群資源,滿足業(yè)務(wù)的需求并降低成本.
OceanBase 已經(jīng)在多個國際主流云平臺上提供OceanBase Cloud 云服務(wù),OceanBase的MySQL和Oracle兼容性大大降低了業(yè)務(wù)遷移到OceanBase Cloud 的風(fēng)險(xiǎn)和成本,目前已有大量用戶使用OceanBase Cloud云服務(wù),并且在快速增長中.
與OceanBase 類似,MySQL MGR 使用Paxos 協(xié)議實(shí)現(xiàn)分布式一致性(Oracle 等尚無類似的技術(shù)方案).本文使用比較常見的Sysbench、TPC-H 測試工具對OceanBase 和MySQL 的OLTP 和OLAP 性能進(jìn)行了對比.MySQL 版本是8.0.31 Community Server,OceanBase 版本是4.2.1,測試使用的數(shù)據(jù)庫服務(wù)器是阿里云r7.8xlarge ECS,硬件配置是32 vCPU(Intel Xeon Platinum 8369 B CPU @ 2.70 GHz) 、256 GB 內(nèi)存,日志盤和數(shù)據(jù)盤使用阿里云云盤,云盤的最大性能吞吐量可以達(dá)到350 MB/s.
測試工具的版本是Sysbench 1.1.Sysbench OLTP測試一共創(chuàng)建30 張表,單張表有100 萬行的數(shù)據(jù)量,壓測客戶端部署在同機(jī)房一臺獨(dú)立的服務(wù)器上,壓測時(shí)長為5 min,在壓測時(shí)會調(diào)整客戶端的壓測并發(fā)數(shù),讓MySQL 和OceanBase 跑出各自最好的性能.Sysbench OLTP 讀寫混合場景是個讀多寫少的多表事務(wù),一個事務(wù)包括18 條讀寫SQL,包括點(diǎn)查詢、范圍查詢、求和、排序、去重、增刪、更新等,OLTP 只讀場景只運(yùn)行其中的14 條讀SQL,OLTP 只寫場景只運(yùn)行其中的4 條寫SQL,性能指標(biāo)TPS 指的是每秒處理的事務(wù)數(shù).
MySQL 和OceanBase 都提供了單機(jī)部署的形態(tài),這種數(shù)據(jù)庫部署形態(tài)下的高可用完全依賴硬件的可靠性,數(shù)據(jù)庫軟件本身沒有高可用能力.
在單機(jī)模式下,所有表的數(shù)據(jù)集中在一臺服務(wù)器上.圖8 表明,OceanBase 在各種場景下的性能都優(yōu)于MySQL;在只寫事務(wù)的場景下,OceanBase 的性能是MySQL 的2 倍多;在其他2 個場景下,OceanBase 的性能是MySQL 的1.27 倍.
圖8 單機(jī)模式下OceanBase 和MySQL 的性能對比Fig.8 Performance comparison between OceanBase and MySQL in stand-alone mode
與OceanBase 類似,MySQL MGR 是基于Paxos協(xié)議的分布式數(shù)據(jù)庫集群,事務(wù)提交必須經(jīng)過半數(shù)以上的節(jié)點(diǎn)同意方可提交.本文采用比較常用的三節(jié)點(diǎn)的部署進(jìn)行分布式數(shù)據(jù)庫集群的性能對比.單主模式表示一個節(jié)點(diǎn)為主、另外兩個節(jié)點(diǎn)為備,備副本節(jié)點(diǎn)從主副本節(jié)點(diǎn)同步事務(wù)日志,只有主副本節(jié)點(diǎn)能夠提供讀寫訪問,當(dāng)主副本節(jié)點(diǎn)故障時(shí),其中1個備副本節(jié)點(diǎn)會被自動選舉為新主,兼顧數(shù)據(jù)一致性和可用性.
下述性能測試采用了3 臺ECS.r7.8xlarge 服務(wù)器,sysbench 測試的參數(shù)跟單機(jī)模式相同,為了避免對數(shù)據(jù)庫性能的影響,客戶端和OceanBase 的代理服務(wù)部署在獨(dú)立的機(jī)器上,OceanBase 代理服務(wù)在分布式部署模式下負(fù)責(zé)路由請求到數(shù)據(jù)所在的數(shù)據(jù)庫服務(wù)器的組件.在分布式集群單主模式的部署下,所有表格的主副本節(jié)點(diǎn)會集中在一臺服務(wù)器上,類似單機(jī)模式,sysbench 測試運(yùn)行的事務(wù)都是單機(jī)多表事務(wù),寫事務(wù)的日志需要同步到超過半數(shù)(2 臺)的機(jī)器,預(yù)期寫性能比單機(jī)部署會有所下降,讀性能影響不大.
OceanBase 的3 副本單主部署下,讀寫混合、只讀和只寫3 個場景的性能較單機(jī)部署分別下降8%、3%、20%;MySQL 的3 副本單主部署下,讀寫混合、只讀和只寫三個場景的性能較單機(jī)部署分別下降12%、1%、19%.在OLTP 只寫場景下,OceanBase 的性能是MySQL 的近2 倍,讀寫混合和只讀場景OceanBase的性能分別是MySQL 的1.34 倍和1.25 倍,如圖9 所示.
圖9 3 副本單主模式OceanBase 和MySQL 的性能對比Fig.9 Performance comparison between OceanBase and MySQL in three-replica single-master mode
分布式集群的多主模式指任何一個數(shù)據(jù)庫節(jié)點(diǎn)都可以寫,即3 個節(jié)點(diǎn)都是主副本節(jié)點(diǎn),每條用戶請求訪問的數(shù)據(jù)可能分布在不同的主副本節(jié)點(diǎn)上,3 個數(shù)據(jù)庫節(jié)點(diǎn)是完全對等的.
性能測試采用的數(shù)據(jù)庫服務(wù)器是阿里云3 臺ECS.r7.8xlarge 型號的ECS 服務(wù)器,Sysbench 測試使用的數(shù)據(jù)量和表數(shù)量跟單機(jī)模式、分布式集群單主模式相同.為了避免對數(shù)據(jù)庫性能的影響,客戶端和OceanBase 的代理服務(wù)部署在獨(dú)立的機(jī)器上,并且確保壓力機(jī)不會是性能的瓶頸.在多主模式的部署下,Sysbench 30 張表格的主副本節(jié)點(diǎn)會隨機(jī)分布在3 臺ECS 服務(wù)器上.Sysbench OLTP 是個多表的測試場景,對應(yīng)的數(shù)據(jù)庫事務(wù)基本上都是需要從3 臺機(jī)器上讀寫數(shù)據(jù)的分布式事務(wù),3 臺數(shù)據(jù)庫服務(wù)器的資源開銷是相當(dāng)?shù)?
OceanBase 多主模式相對于單主模式,OLTP 讀寫混合場景的TPS 提升了86%,只讀事務(wù)場景的TPS提升了156%,只寫事務(wù)場景的TPS 提升了49%.除了只寫事務(wù)場景,MySQL 多主模式較單主模式也有不錯的性能提升,但性能較OceanBase 仍然有較大的差距,讀寫混合、只讀和只寫3 個場景下,OceanBase的性能分別是MySQL 的1.27 倍、1.09 倍和3.1 倍,尤其在OLTP 只寫場景下,OceanBase 的性能有3 倍多的優(yōu)勢,如圖10 所示.
圖10 3 副本多主模式OceanBase 和MySQL 的性能對比Fig.10 Performance comparison between OceanBase and MySQL in three-replica multi-master mode
本文也對比了MySQL 和OceanBase 在多機(jī)3 副本多主的集群模式下處理復(fù)雜SQL 的性能,采用比較流行的TPC-H 作為測試工具,測試采用的數(shù)據(jù)量是100 GB.實(shí)驗(yàn)數(shù)據(jù)表明,在多機(jī)3 副本多主模式下OLAP 復(fù)雜查詢,OceanBase 的性能是MySQL 的6~327 倍,如圖11 所示.
圖11 OceanBase 和MySQL 的TPC-H 22 條SQL 查詢耗時(shí)對比Fig.11 Time-consuming comparison of TPC-H 22 SQL queries between OceanBase and MySQL
分布式關(guān)系數(shù)據(jù)庫融合了分布式系統(tǒng)和傳統(tǒng)關(guān)系數(shù)據(jù)庫2 個方面的理論和技術(shù),兩者的發(fā)展都對分布式關(guān)系數(shù)據(jù)庫產(chǎn)生了顯著的影響.
Google 分布式文件系統(tǒng)(GFS)[21]實(shí)踐了如何在一組普通PC 服務(wù)器和普通數(shù)據(jù)中心網(wǎng)絡(luò)之上構(gòu)建一個可靠的海量數(shù)據(jù)存儲系統(tǒng)來面向大文件提供高吞吐率的文件讀寫.GFS 每個文件由若干chunk 組成,每個chunk 有若干個副本(典型為3),分別存儲在多個chunk server 上.執(zhí)行寫入時(shí),通過主從復(fù)制把數(shù)據(jù)同步寫入到多個副本上.為了自動容災(zāi)和提升寫入性能,GFS 允許副本里出現(xiàn)重復(fù)的記錄并允許空的占位記錄,需要應(yīng)用在讀取時(shí)候特殊處理,這一設(shè)計(jì)與之前的要求強(qiáng)一致性甚至與Posix 兼容的文件系統(tǒng)有顯著不同.Google 分布式文件系統(tǒng)的masterchunk server 架構(gòu)、自動容災(zāi)處理、多副本、原子追加等經(jīng)典設(shè)計(jì),對之后的分布式存儲系統(tǒng)產(chǎn)生了很大的影響,比如開源的Hadoop 分布式文件系統(tǒng)(HDFS).
MapReduce[22]提供了一種用于海量數(shù)據(jù)處理的編程模型和分布式處理框架.用戶只需要定義一組簡單的map 和reduce 函數(shù),系統(tǒng)將自動把計(jì)算過程在一組普通PC 服務(wù)器上并行化,并自動處理任務(wù)劃分、任務(wù)調(diào)度、中間結(jié)果傳輸、節(jié)點(diǎn)故障容災(zāi)等.MapReduce 刻畫了利用分布式系統(tǒng)分析處理海量數(shù)據(jù)的關(guān)鍵特征,對后來的大數(shù)據(jù)系統(tǒng)產(chǎn)生了深遠(yuǎn)的影響.
Bigtable[23]構(gòu)建在GFS 之上,是一個用來管理PB 級的結(jié)構(gòu)化數(shù)據(jù)的分布式存儲系統(tǒng).Bigtable 的數(shù)據(jù)模型是一個支持元素級多版本的稀疏表,其中,元素的鍵和值都是無類型的二進(jìn)制串.為了支持實(shí)時(shí)更新,存儲結(jié)構(gòu)采用了LSM-tree 的數(shù)據(jù)結(jié)構(gòu),對表的修改在記錄持久化日志后,存儲在內(nèi)存Memtable 中,并在后臺按需與硬盤上的SSTable 文件進(jìn)行合并.Bigtable 的數(shù)據(jù)模型后來被稱為寬列模型,是NoSQL類數(shù)據(jù)庫的典型代表,開源項(xiàng)目HBase 和Cassandra都受到其影響.Bigtable 只支持單行內(nèi)的事務(wù),不支持通用事務(wù),也就無法通過維護(hù)二級索引來加速查詢.
Dynamo[24]是同時(shí)期另一個NoSQL 系統(tǒng),它是一個分布式鍵值存儲系統(tǒng).為了在設(shè)計(jì)上達(dá)到極高的可用性目標(biāo),它的架構(gòu)采用了去中心化的分布式架構(gòu),所有節(jié)點(diǎn)對等,整個系統(tǒng)中的組件避免任何中心節(jié)點(diǎn).Dynamo 使用一致性哈希對數(shù)據(jù)進(jìn)行分片,使得容災(zāi)處理和擴(kuò)容、縮容時(shí)數(shù)據(jù)遷移量最小.為了寫操作的高可用,系統(tǒng)選擇放棄故障時(shí)的強(qiáng)一致性,只保證最終一致性.Dynamo 無主副本節(jié)點(diǎn)的異步數(shù)據(jù)復(fù)制協(xié)議,適合于跨數(shù)據(jù)中心部署.
Bigtable 雖然具有良好的擴(kuò)展性,但是因?yàn)橹恢С謫涡惺聞?wù),應(yīng)用的并發(fā)修改無法確保數(shù)據(jù)集的一致性,提升了應(yīng)用開發(fā)的難度和成本.為了解決這個問題,Percolator[25]在Bigtable 的模型和服務(wù)之上,通過在行數(shù)據(jù)中添加版本和鎖信息,對應(yīng)用提供了支持快照隔離級別的通用事務(wù).但是因?yàn)槿我獾亩嘈袑懖僮鞫夹枰鳛榉植际绞聞?wù)處理,且對鎖狀態(tài)多副本持久化和延遲清理,這并不適合對事務(wù)處理時(shí)延有嚴(yán)格要求的OLTP 系統(tǒng).
Google Spanner[26-27]實(shí)現(xiàn)了一個跨全球部署的分布式數(shù)據(jù)庫,提供了外部強(qiáng)一致性,并支持SQL 語言.Spanner 把數(shù)據(jù)進(jìn)行分片,每個分片有多個副本,通過基于Paxos 協(xié)議的分布式狀態(tài)機(jī)保證多副本間的數(shù)據(jù)一致.Spanner 對后續(xù)的類似系統(tǒng)產(chǎn)生了顯著影響,例如CockroachDB[28]和YugaByteDB[29]等.Spanner開發(fā)了TrueTime 時(shí)間服務(wù)以提供全球范圍內(nèi)誤差很小的時(shí)間戳服務(wù),避免了跨地域獲取事務(wù)版本號的開銷,但這要求讀寫操作必須在對應(yīng)的時(shí)間戳所示時(shí)間之后進(jìn)行從而增加了讀寫延時(shí),同時(shí)TrueTime需要多臺高精度的GPS 原子鐘以提供精確的時(shí)間,限制了它的業(yè)務(wù)應(yīng)用和部署場景.
作為一個分布式數(shù)據(jù)庫,OceanBase 實(shí)現(xiàn)了高可用以及在線水平擴(kuò)展.未來,OceanBase 期望能夠在同一套系統(tǒng)內(nèi)更好地處理多種不同的工作負(fù)載和數(shù)據(jù)類型,無論是事務(wù)型還是分析型,大數(shù)據(jù)還是小數(shù)據(jù),結(jié)構(gòu)化數(shù)據(jù)還是半結(jié)構(gòu)化數(shù)據(jù),滿足企業(yè)從小到大成長過程中的全生命周期數(shù)據(jù)管理需求.OceanBase系統(tǒng)的后續(xù)技術(shù)發(fā)展方向包括5 個方面:
1)HTAP 混合負(fù)載.多數(shù)業(yè)務(wù)不僅需要交易處理(OLTP),還需要對業(yè)務(wù)進(jìn)行多個維度的分析、生成各種報(bào)表(OLAP)等,當(dāng)前OceanBase 的OLTP 功能比較豐富,而OLAP 功能還有待進(jìn)一步完善,OLTP和OLAP 事務(wù)處理的優(yōu)先級、資源隔離等方面還有待進(jìn)一步完善.未來將進(jìn)一步豐富OLAP 功能,通過列式存儲等技術(shù)提升OLAP 的執(zhí)行性能,并完善OLTP和OLAP 混合執(zhí)行能力.
2)Oracle/MySQL 兼容功能.在功能支持方面,OceanBase 兼容絕大部分MySQL 功能和大部分Oracle功能,包括存儲過程、數(shù)據(jù)庫安全等,然而,系統(tǒng)的查詢優(yōu)化能力與Oracle 相比有一定的差距,數(shù)據(jù)庫功能也不如Oracle 豐富.未來將加強(qiáng)SQL 查詢優(yōu)化和并行執(zhí)行能力,提升Oracle 兼容性,進(jìn)一步完善MySQL兼容性,進(jìn)一步降低從Oracle/MySQL 遷移到該系統(tǒng)的成本.
3)多模態(tài)數(shù)據(jù)處理.多數(shù)業(yè)務(wù)不僅需要處理結(jié)構(gòu)化數(shù)據(jù),還需要處理其它類型的數(shù)據(jù),例如地理信息數(shù)據(jù)、文檔數(shù)據(jù)和鍵值數(shù)據(jù)等半結(jié)構(gòu)化數(shù)據(jù),并基于這些數(shù)據(jù)執(zhí)行事務(wù)、分析、在線搜索等各種操作.通過使用一套系統(tǒng)處理多種數(shù)據(jù),能夠簡化企業(yè)的技術(shù)棧,降低企業(yè)的業(yè)務(wù)系統(tǒng)實(shí)現(xiàn)的復(fù)雜度.當(dāng)前,OceanBase 的關(guān)系模型數(shù)據(jù)管理功能比較豐富,其它數(shù)據(jù)模型管理功能還有不少需要完善之處.未來將進(jìn)一步豐富多模數(shù)據(jù)管理功能,并探索多種數(shù)據(jù)模型之間的互通操作.
4)多云原生數(shù)據(jù)庫.OceanBase 支持多種不同的部署模式,包括公有云、專有云和獨(dú)立軟件部署.公有云、多云、混合云將會是未來的趨勢,因此,后續(xù)OceanBase 將會進(jìn)一步增強(qiáng)對全球主流云平臺的支持和適配,并進(jìn)行軟硬件協(xié)同優(yōu)化以實(shí)現(xiàn)更好的性價(jià)比.
5)自治數(shù)據(jù)庫.當(dāng)前OceanBase 運(yùn)行維護(hù)參數(shù)較多,運(yùn)行維護(hù)人員學(xué)習(xí)和使用有一定的學(xué)習(xí)成本.未來我們計(jì)劃利用機(jī)器學(xué)習(xí)和人工智能技術(shù)來分析系統(tǒng)運(yùn)行環(huán)境狀態(tài)和日志數(shù)據(jù)等信息,從而實(shí)現(xiàn)較為智能的動態(tài)系統(tǒng)參數(shù)調(diào)整、系統(tǒng)優(yōu)化、在線預(yù)警、實(shí)時(shí)監(jiān)測等,實(shí)現(xiàn)智能診斷、智能調(diào)優(yōu)、智能運(yùn)維等.
OceanBase 作為一個基礎(chǔ)軟件,生態(tài)構(gòu)建至關(guān)重要.2021 年6 月1 日,OceanBase 將內(nèi)核代碼(超過300萬行)在GitHub[30]開源,目前已經(jīng)有成百上千的企業(yè)使用OceanBase 開源版本.未來,OceanBase 會繼續(xù)堅(jiān)持開源開放的路線,進(jìn)一步加大對用戶、開發(fā)者、合作伙伴的支持力度,基于開源社區(qū)的協(xié)作模式,通過大量用戶的反饋不斷迭代,不斷提升OceanBase 的成熟度,更好地滿足用戶的需求.
作者貢獻(xiàn)聲明:陽振坤提出論文思路、整體架構(gòu)設(shè)計(jì),參與文獻(xiàn)調(diào)研,撰寫和修訂論文;楊傳輝、韓富晟、王國平、楊志豐參與文獻(xiàn)調(diào)研和論文撰寫;成肖君參與文獻(xiàn)調(diào)研和論文撰寫,并負(fù)責(zé)性能對照實(shí)驗(yàn).